diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b42d5f8425af6..b4103af1fb35c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -680,6 +680,8 @@ Bug Fixes in This Version ``#include`` directive. (#GH138094) - Fixed a crash during constant evaluation involving invalid lambda captures (#GH138832) +- Fixed compound literal is not constant expression inside initializer list + (#GH87867) - Fixed a crash when instantiating an invalid dependent friend template specialization. (#GH139052) - Fixed a crash with an invalid member function parameter list with a default diff --git a/clang/include/clang/Sema/Scope.h b/clang/include/clang/Sema/Scope.h index ad12a3d73413b..07b9e1bc10f5a 100644 --- a/clang/include/clang/Sema/Scope.h +++ b/clang/include/clang/Sema/Scope.h @@ -427,6 +427,17 @@ class Scope { return false; } + /// isInObjcMethodScope - Return true if this scope is, or is contained, in an + /// C function body. + bool isInCFunctionScope() const { + for (const Scope *S = this; S; S = S->getParent()) { + if (S->isFunctionScope()) + return true; + } + + return false; + } + /// isInObjcMethodScope - Return true if this scope is, or is contained in, an /// Objective-C method body. Note that this method is not constant time. bool isInObjcMethodScope() const { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index c7abbbd6993de..710f71650e385 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7281,6 +7281,7 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, TypeSourceInfo *TInfo, // void func(char *para[(int [1]){ 0 }[0]); const Scope *S = getCurScope(); bool IsFileScope = !CurContext->isFunctionOrMethod() && + !S->isInCFunctionScope() && (!S || !S->isFunctionPrototypeScope()); // In C, compound literals are l-values for some reason. diff --git a/clang/test/Sema/gh87867.c b/clang/test/Sema/gh87867.c new file mode 100644 index 0000000000000..0568c734424ca --- /dev/null +++ b/clang/test/Sema/gh87867.c @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c23 %s + +// Compound literal doesn't need a constant expression inside a initializer-list if it is already inside a function +// see: https://github.com/llvm/llvm-project/issues/87867 +int foo(int *a, int b) { + return 0; +} + +int x; +struct{int t;} a = (struct { + typeof(foo(&(struct { int t; }){.t = x}.t, 0)) t; // expected-error {{initializer element is not a compile-time constant}} +}){0}; + +void inside_a_func(){ + int x; + (void)(struct { + typeof(foo(&(struct { int t; }){.t = x}.t, 0)) t; + }){0}; +} + +// see: https://github.com/llvm/llvm-project/issues/143613 +#define bitcast(type, value) \ + (((union{ typeof(value) src; type dst; }){ (value) }).dst) + +double placeholder = 10.0; +double bar = bitcast(double, placeholder); // expected-error {{initializer element is not a compile-time constant}} + +int main(void) +{ + int foo = 4; + foo = bitcast(int, bitcast(double, foo)); + return 0; +}