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 201bf300bc6694..2cf14d8d6a15d9 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 @@ -82,4 +83,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 a7857641a2e8df..c51c02def7dfb5 100644 --- a/clang/test/Preprocessor/embed_constexpr.cpp +++ b/clang/test/Preprocessor/embed_constexpr.cpp @@ -96,3 +96,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');