Skip to content

Commit c9e8540

Browse files
Fznamznontru
authored andcommitted
[clang] Fix C23 constexpr crashes (llvm#112708)
Before using a constexpr variable that is not properly initialized check that it is valid. Fixes llvm#109095 Fixes llvm#112516
1 parent 81005af commit c9e8540

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

clang/lib/AST/Decl.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -2503,7 +2503,8 @@ bool VarDecl::isUsableInConstantExpressions(const ASTContext &Context) const {
25032503
if (!DefVD->mightBeUsableInConstantExpressions(Context))
25042504
return false;
25052505
// ... and its initializer is a constant initializer.
2506-
if (Context.getLangOpts().CPlusPlus && !DefVD->hasConstantInitialization())
2506+
if ((Context.getLangOpts().CPlusPlus || getLangOpts().C23) &&
2507+
!DefVD->hasConstantInitialization())
25072508
return false;
25082509
// C++98 [expr.const]p1:
25092510
// An integral constant-expression can involve only [...] const variables
@@ -2610,8 +2611,11 @@ bool VarDecl::hasICEInitializer(const ASTContext &Context) const {
26102611
}
26112612

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

26172621
// In C++, it depends on whether the evaluation at the point of definition

clang/test/Sema/constexpr.c

+17
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,20 @@ void constexprif() {
364364
void constevalif() {
365365
if consteval (300) {} //expected-error {{expected '(' after 'if'}}
366366
}
367+
368+
struct S11 {
369+
int len;
370+
};
371+
void ghissue112516() {
372+
struct S11 *s11 = 0;
373+
constexpr int num = s11->len; // expected-error {{constexpr variable 'num' must be initialized by a constant expression}}
374+
void *Arr[num];
375+
}
376+
377+
void ghissue109095() {
378+
constexpr char c[] = { 'a' };
379+
constexpr int i = c[1]; // expected-error {{constexpr variable 'i' must be initialized by a constant expression}}\
380+
// expected-note {{declared here}}
381+
_Static_assert(i == c[0]); // expected-error {{static assertion expression is not an integral constant expression}}\
382+
// expected-note {{initializer of 'i' is not a constant expression}}
383+
}

0 commit comments

Comments
 (0)