diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -3158,6 +3158,13 @@ switch (getStmtClass()) { default: break; + case DeclRefExprClass: + if (!Ctx.getLangOpts().CPlusPlus && Ctx.getLangOpts().GNUMode) { + const QualType &QT = cast(this)->getDecl()->getType(); + if (QT->isStructureType() && QT.isConstQualified()) + return true; + } + break; case StringLiteralClass: case ObjCEncodeExprClass: return true; diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1007,6 +1007,13 @@ return Visit(PE->getSubExpr(), T); } + llvm::Constant *VisitDeclRefExpr(DeclRefExpr *DRE, QualType T) { + if (VarDecl *V = dyn_cast(DRE->getDecl())) + if (V->hasInit()) + return Visit(V->getInit(), V->getType()); + return nullptr; + } + llvm::Constant * VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *PE, QualType T) { diff --git a/clang/test/CodeGen/const-init.c b/clang/test/CodeGen/const-init.c --- a/clang/test/CodeGen/const-init.c +++ b/clang/test/CodeGen/const-init.c @@ -181,3 +181,18 @@ #pragma pack() // CHECK: @g31.a = internal global %struct.anon.2 { i16 23122, i32 -12312731, i16 -312 }, align 4 } + +struct PR4517_foo { + int x; +}; +struct PR4517_bar { + struct PR4517_foo foo; +}; +const struct PR4517_foo my_foo = {.x = 42}; +struct PR4517_bar my_bar = {.foo = my_foo}; +struct PR4517_bar my_bar2 = (struct PR4517_bar){.foo = my_foo}; +struct PR4517_bar my_bar3 = {my_foo}; +struct PR4517_bar my_bar4 = (struct PR4517_bar){my_foo}; +// CHECK: @my_foo = constant %struct.PR4517_foo { i32 42 }, align 4 +// CHECK: @my_bar = global %struct.PR4517_bar { %struct.PR4517_foo { i32 42 } }, align 4 +// CHECK: @my_bar2 = global %struct.PR4517_bar { %struct.PR4517_foo { i32 42 } }, align 4 diff --git a/clang/test/Sema/init.c b/clang/test/Sema/init.c --- a/clang/test/Sema/init.c +++ b/clang/test/Sema/init.c @@ -160,3 +160,22 @@ typedef struct { uintptr_t x : 2; } StructWithBitfield; StructWithBitfield bitfieldvar = { (uintptr_t)&bitfieldvar }; // expected-error {{initializer element is not a compile-time constant}} + +// PR45157 +struct PR4517_foo {}; +struct PR4517_bar { + struct PR4517_foo foo; +}; +const struct PR4517_foo my_foo = {}; +struct PR4517_bar my_bar = { + .foo = my_foo, // no-warning +}; +struct PR4517_bar my_bar2 = (struct PR4517_bar){ + .foo = my_foo, // no-warning +}; +struct PR4517_bar my_bar3 = { + my_foo, // no-warning +}; +struct PR4517_bar my_bar4 = (struct PR4517_bar){ + my_foo // no-warning +};