Skip to content

[clang][ExprConst] Can't be past an invalid LValue designator #84293

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9211,7 +9211,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 @@ -12899,6 +12900,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}}