Skip to content

Commit

Permalink
[clang] Fix C23 constexpr crashes (llvm#112708)
Browse files Browse the repository at this point in the history
Before using a constexpr variable that is not properly initialized check
that it is valid.

Fixes llvm#109095
Fixes llvm#112516
  • Loading branch information
Fznamznon committed Oct 18, 2024
1 parent 7ba7d8e commit d3121f2
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 3 deletions.
10 changes: 7 additions & 3 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2503,7 +2503,8 @@ bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
if (!DefVD->mightBeUsableInConstantExpressions(Context))
return false;
// ... and its initializer is a constant initializer.
if (Context.getLangOpts().CPlusPlus && !DefVD->hasConstantInitialization())
if ((Context.getLangOpts().CPlusPlus || getLangOpts().C23) &&
!DefVD->hasConstantInitialization())
return false;
// C++98 [expr.const]p1:
// An integral constant-expression can involve only [...] const variables
Expand Down Expand Up @@ -2610,8 +2611,11 @@ bool VarDecl::hasICEInitializer(const ASTContext &Context) const {
}

bool VarDecl::hasConstantInitialization() const {
// In C, all globals (and only globals) have constant initialization.
if (hasGlobalStorage() && !getASTContext().getLangOpts().CPlusPlus)
// In C, all globals and constexpr variables should have constant
// initialization. For constexpr variables in C check that initializer is a
// constant initializer because they can be used in constant expressions.
if (hasGlobalStorage() && !getASTContext().getLangOpts().CPlusPlus &&
!isConstexpr())
return true;

// In C++, it depends on whether the evaluation at the point of definition
Expand Down
14 changes: 14 additions & 0 deletions clang/test/Sema/constexpr.c
Original file line number Diff line number Diff line change
Expand Up @@ -357,3 +357,17 @@ void infsNaNs() {
constexpr double db5 = LD_SNAN; // expected-error {{constexpr initializer evaluates to nan which is not exactly representable in type 'const double'}}
constexpr double db6 = INF;
}

void ghissue112516() {
struct S11 *s11 = 0;
constexpr int num = s11->len; // expected-error {{constexpr variable 'num' must be initialized by a constant expression}}
void *Arr[num];
}

void ghissue109095() {
constexpr char c[] = { 'a' };
constexpr int i = c[1]; // expected-error {{constexpr variable 'i' must be initialized by a constant expression}}\
// expected-note {{declared here}}
_Static_assert(i == c[0]); // expected-error {{static assertion expression is not an integral constant expression}}\
// expected-note {{initializer of 'i' is not a constant expression}}
}

0 comments on commit d3121f2

Please sign in to comment.