Skip to content

Commit d58d5d6

Browse files
authored
[clang] Compound Literal Statement Constant Expression Assertion Fix (#139479)
Compound literals initializer-list should be a constant expression if it is defined outside the body of a function. Emit error instead of falling through tripping assertion error. Fixes #139160
1 parent 21d5064 commit d58d5d6

File tree

3 files changed

+33
-0
lines changed

3 files changed

+33
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,7 @@ Bug Fixes in This Version
601601
- Fixed a crash with an invalid member function parameter list with a default
602602
argument which contains a pragma. (#GH113722)
603603
- Fixed assertion failures when generating name lookup table in modules. (#GH61065, #GH134739)
604+
- Fixed an assertion failure in constant compound literal statements. (#GH139160)
604605

605606
Bug Fixes to Compiler Builtins
606607
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaExpr.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7318,10 +7318,20 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
73187318
? VK_PRValue
73197319
: VK_LValue;
73207320

7321+
// C99 6.5.2.5
7322+
// "If the compound literal occurs outside the body of a function, the
7323+
// initializer list shall consist of constant expressions."
73217324
if (IsFileScope)
73227325
if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr))
73237326
for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
73247327
Expr *Init = ILE->getInit(i);
7328+
if (!Init->isTypeDependent() && !Init->isValueDependent() &&
7329+
!Init->isConstantInitializer(Context, /*IsForRef=*/false)) {
7330+
Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
7331+
<< Init->getSourceBitField();
7332+
return ExprError();
7333+
}
7334+
73257335
ILE->setInit(i, ConstantExpr::Create(Context, Init));
73267336
}
73277337

clang/test/SemaCXX/cxx2a-consteval.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,3 +1300,25 @@ void foo() {
13001300
}
13011301

13021302
}
1303+
1304+
// https://github.com/llvm/llvm-project/issues/139160
1305+
namespace GH139160{
1306+
// original test case taken from Github
1307+
struct A {int x[1]; };
1308+
A f(); // expected-note {{declared here}}
1309+
typedef int *t[];
1310+
consteval int* f(int* x) { return x; }
1311+
1312+
int ** x = (t){f(f().x)}; // expected-error {{call to consteval function 'GH139160::f' is not a constant expression}}
1313+
// expected-note@-1 {{non-constexpr function 'f' cannot be used in a constant expression}}
1314+
// expected-error@-2 {{initializer element is not a compile-time constant}}
1315+
1316+
struct B {int value, value_two;};
1317+
B make_struct() {return {10, 20};} // expected-note {{declared here}}
1318+
consteval int get_value(B container) {return container.value;}
1319+
B result = (B){10, get_value(make_struct())}; // expected-error {{initializer element is not a compile-time constant}}
1320+
// expected-error@-1 {{call to consteval function 'GH139160::get_value' is not a constant expression}}
1321+
// expected-note@-2 {{non-constexpr function 'make_struct' cannot be used in a constant expression}}
1322+
};
1323+
1324+

0 commit comments

Comments
 (0)