Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ Bug Fixes in This Version
- Fixed a crash with an invalid member function parameter list with a default
argument which contains a pragma. (#GH113722)
- Fixed assertion failures when generating name lookup table in modules. (#GH61065, #GH134739)
- Fixed an assertion failure in constant compound literal statements. (#GH139160)

Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7241,10 +7241,20 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo,
? VK_PRValue
: VK_LValue;

// C99 6.5.2.5
// "If the compound literal occurs outside the body of a function, the
// initializer list shall consist of constant expressions."
if (IsFileScope)
if (auto ILE = dyn_cast<InitListExpr>(LiteralExpr))
for (unsigned i = 0, j = ILE->getNumInits(); i != j; i++) {
Expr *Init = ILE->getInit(i);
if (!Init->isTypeDependent() && !Init->isValueDependent())
if (!Init->isConstantInitializer(Context, /*IsForRef=*/false)) {
Diag(Init->getExprLoc(), diag::err_init_element_not_constant)
<< Init->getSourceBitField();
return ExprError();
}

ILE->setInit(i, ConstantExpr::Create(Context, Init));
}

Expand Down
22 changes: 22 additions & 0 deletions clang/test/SemaCXX/cxx2a-consteval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1300,3 +1300,25 @@ void foo() {
}

}

// https://github.com/llvm/llvm-project/issues/139160
namespace GH139160{
// original test case taken from Github
struct A {int x[1]; };
A f(); // expected-note {{declared here}}
typedef int *t[];
consteval int* f(int* x) { return x; }

int ** x = (t){f(f().x)}; // expected-error {{call to consteval function 'GH139160::f' is not a constant expression}}
// expected-note@-1 {{non-constexpr function 'f' cannot be used in a constant expression}}
// expected-error@-2 {{initializer element is not a compile-time constant}}

struct B {int value, value_two;};
B make_struct() {return {10, 20};} // expected-note {{declared here}}
consteval int get_value(B container) {return container.value;}
B result = (B){10, get_value(make_struct())}; // expected-error {{initializer element is not a compile-time constant}}
// expected-error@-1 {{call to consteval function 'GH139160::get_value' is not a constant expression}}
// expected-note@-2 {{non-constexpr function 'make_struct' cannot be used in a constant expression}}
};