Skip to content

Commit

Permalink
[clang][ExprConst] Can't be past an invalid LValue designator (#84293)
Browse files Browse the repository at this point in the history
For the test case in C, both `LV.getLValueOffset()` and
`Ctx.getTypeSizeInChars(Ty)` are zero, so we return `true` from
`isOnePastTheEndOfCompleteObject()` and ultimately diagnose this as
being one past the end, but the diagnostic doesn't make sense.
  • Loading branch information
tbaederr committed Mar 18, 2024
1 parent 1d9fb2e commit 4294841
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 5 deletions.
7 changes: 6 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9253,7 +9253,8 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) {
Info.getLangOpts().CPlusPlus26)) {
// Permitted.
} else {
if (SubExpr->getType()->isVoidPointerType()) {
if (SubExpr->getType()->isVoidPointerType() &&
Info.getLangOpts().CPlusPlus) {
if (HasValidResult)
CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
<< SubExpr->getType() << Info.getLangOpts().CPlusPlus26
Expand Down Expand Up @@ -12942,6 +12943,10 @@ static bool isOnePastTheEndOfCompleteObject(const ASTContext &Ctx,
if (Ty->isIncompleteType())
return true;

// Can't be past the end of an invalid object.
if (LV.getLValueDesignator().Invalid)
return false;

// We're a past-the-end pointer if we point to the byte after the object,
// no matter what our type or path is.
auto Size = Ctx.getTypeSizeInChars(Ty);
Expand Down
4 changes: 2 additions & 2 deletions clang/test/AST/Interp/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ _Static_assert((&a - 100) != 0, ""); // pedantic-ref-warning {{is a GNU extensio
// pedantic-ref-note {{-100 of non-array}} \
// pedantic-expected-note {{-100 of non-array}}
/// extern variable of a composite type.
/// FIXME: The 'cast from void*' note is missing in the new interpreter.
/// FIXME: The 'this conversion is not allowed' note is missing in the new interpreter.
extern struct Test50S Test50;
_Static_assert(&Test50 != (void*)0, ""); // all-warning {{always true}} \
// pedantic-ref-warning {{is a GNU extension}} \
// pedantic-ref-note {{cast from 'void *' is not allowed}} \
// pedantic-ref-note {{this conversion is not allowed in a constant expression}} \
// pedantic-expected-warning {{is a GNU extension}}

struct y {int x,y;};
Expand Down
3 changes: 1 addition & 2 deletions clang/test/Sema/const-eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ void PR21945(void) { int i = (({}), 0l); }

void PR24622(void);
struct PR24622 {} pr24622;
EVAL_EXPR(52, &pr24622 == (void *)&PR24622); // expected-error {{not an integer constant expression}}
// expected-note@-1 {{past the end}}
EVAL_EXPR(52, &pr24622 == (void *)&PR24622);

// We evaluate these by providing 2s' complement semantics in constant
// expressions, like we do for integers.
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Sema/constexpr-void-cast.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %clang_cc1 -x c -fsyntax-only %s -verify=c
// RUN: %clang_cc1 -x c -fsyntax-only %s -pedantic -verify=c-pedantic
//
// RUN: %clang_cc1 -x c++ -fsyntax-only %s -verify=cxx
// RUN: %clang_cc1 -x c++ -fsyntax-only %s -pedantic -verify=cxx-pedantic

// c-no-diagnostics
// cxx-no-diagnostics

void f(void);
struct S {char c;} s;
_Static_assert(&s != (void *)&f, ""); // c-pedantic-warning {{not an integer constant expression}} \
// c-pedantic-note {{this conversion is not allowed in a constant expression}} \
// cxx-pedantic-warning {{'_Static_assert' is a C11 extension}}

0 comments on commit 4294841

Please sign in to comment.