diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index a27ed02fc73b86..d97a5c8988840a 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1993,9 +1993,18 @@ static bool checkDestructorReference(QualType ElementType, SourceLocation Loc, return SemaRef.DiagnoseUseOfDecl(Destructor, Loc); } -static bool canInitializeArrayWithEmbedDataString(ArrayRef ExprList, - QualType InitType, - ASTContext &Context) { +static bool +canInitializeArrayWithEmbedDataString(ArrayRef ExprList, + const InitializedEntity &Entity, + ASTContext &Context) { + QualType InitType = Entity.getType(); + const InitializedEntity *Parent = &Entity; + + while (Parent) { + InitType = Parent->getType(); + Parent = Parent->getParent(); + } + // Only one initializer, it's an embed and the types match; EmbedExpr *EE = ExprList.size() == 1 @@ -2034,7 +2043,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity, } } - if (canInitializeArrayWithEmbedDataString(IList->inits(), DeclType, + if (canInitializeArrayWithEmbedDataString(IList->inits(), Entity, SemaRef.Context)) { EmbedExpr *Embed = cast(IList->inits()[0]); IList->setInit(0, Embed->getDataStringLiteral()); diff --git a/clang/test/Preprocessor/embed_codegen.cpp b/clang/test/Preprocessor/embed_codegen.cpp index 64110afc162d72..c73a265ac7494a 100644 --- a/clang/test/Preprocessor/embed_codegen.cpp +++ b/clang/test/Preprocessor/embed_codegen.cpp @@ -3,6 +3,7 @@ // CHECK: @__const._Z3fooi.ca = private unnamed_addr constant [3 x i32] [i32 0, i32 106, i32 107], align 4 // CHECK: @__const._Z3fooi.sc = private unnamed_addr constant %struct.S1 { i32 106, i32 107, i32 0 }, align 4 // CHECK: @__const._Z3fooi.t = private unnamed_addr constant [3 x %struct.T] [%struct.T { [2 x i32] [i32 48, i32 49], %struct.S1 { i32 50, i32 51, i32 52 } }, %struct.T { [2 x i32] [i32 53, i32 54], %struct.S1 { i32 55, i32 56, i32 57 } }, %struct.T { [2 x i32] [i32 10, i32 0], %struct.S1 zeroinitializer }], align 16 +// CHECK: @__const._Z3fooi.W = private unnamed_addr constant %struct.Wrapper { i32 48, %struct.HasCharArray { [10 x i8] c"123456789\0A" } }, align 4 void foo(int a) { // CHECK: %a.addr = alloca i32, align 4 // CHECK: store i32 %a, ptr %a.addr, align 4 @@ -81,4 +82,11 @@ struct T tnonc[] = { #embed prefix(,) }; + +struct HasCharArray { unsigned char h[10]; }; +struct Wrapper { int a; struct HasCharArray d; }; +constexpr struct Wrapper W = { +#embed "numbers.txt" +}; + } diff --git a/clang/test/Preprocessor/embed_constexpr.cpp b/clang/test/Preprocessor/embed_constexpr.cpp index 1cadff76b4890a..9b6470fcc7182d 100644 --- a/clang/test/Preprocessor/embed_constexpr.cpp +++ b/clang/test/Preprocessor/embed_constexpr.cpp @@ -95,3 +95,11 @@ struct ST {}; ST< #embed limit(1) > st; + +struct HasCharArray { unsigned char h[10]; }; +struct Wrapper { int a; struct HasCharArray d; }; +constexpr struct Wrapper W = { +#embed "numbers.txt" +}; + +static_assert(W.d.h[2] == '3');