Skip to content

Commit 3acb9fa

Browse files
Fznamznonyuxuanchen1997
authored andcommitted
[clang] Be careful when choosing "fast path" for initialization with #embed (#99023)
Summary: When #embed appears in an initializer list, we may choose a "fast path" if the target declaration is a char array. We simply initialize it with string literal that contains embedded data. However we need to be careful when checking that we actually can use this "fast path" since char array may be nested in a struct. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251665
1 parent 97ba18b commit 3acb9fa

File tree

3 files changed

+29
-4
lines changed

3 files changed

+29
-4
lines changed

clang/lib/Sema/SemaInit.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1993,9 +1993,18 @@ static bool checkDestructorReference(QualType ElementType, SourceLocation Loc,
19931993
return SemaRef.DiagnoseUseOfDecl(Destructor, Loc);
19941994
}
19951995

1996-
static bool canInitializeArrayWithEmbedDataString(ArrayRef<Expr *> ExprList,
1997-
QualType InitType,
1998-
ASTContext &Context) {
1996+
static bool
1997+
canInitializeArrayWithEmbedDataString(ArrayRef<Expr *> ExprList,
1998+
const InitializedEntity &Entity,
1999+
ASTContext &Context) {
2000+
QualType InitType = Entity.getType();
2001+
const InitializedEntity *Parent = &Entity;
2002+
2003+
while (Parent) {
2004+
InitType = Parent->getType();
2005+
Parent = Parent->getParent();
2006+
}
2007+
19992008
// Only one initializer, it's an embed and the types match;
20002009
EmbedExpr *EE =
20012010
ExprList.size() == 1
@@ -2034,7 +2043,7 @@ void InitListChecker::CheckArrayType(const InitializedEntity &Entity,
20342043
}
20352044
}
20362045

2037-
if (canInitializeArrayWithEmbedDataString(IList->inits(), DeclType,
2046+
if (canInitializeArrayWithEmbedDataString(IList->inits(), Entity,
20382047
SemaRef.Context)) {
20392048
EmbedExpr *Embed = cast<EmbedExpr>(IList->inits()[0]);
20402049
IList->setInit(0, Embed->getDataStringLiteral());

clang/test/Preprocessor/embed_codegen.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// CHECK: @__const._Z3fooi.ca = private unnamed_addr constant [3 x i32] [i32 0, i32 106, i32 107], align 4
44
// CHECK: @__const._Z3fooi.sc = private unnamed_addr constant %struct.S1 { i32 106, i32 107, i32 0 }, align 4
55
// 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
6+
// CHECK: @__const._Z3fooi.W = private unnamed_addr constant %struct.Wrapper { i32 48, %struct.HasCharArray { [10 x i8] c"123456789\0A" } }, align 4
67
void foo(int a) {
78
// CHECK: %a.addr = alloca i32, align 4
89
// CHECK: store i32 %a, ptr %a.addr, align 4
@@ -82,4 +83,11 @@ struct T tnonc[] = {
8283
#embed <jk.txt> prefix(,)
8384
};
8485

86+
87+
struct HasCharArray { unsigned char h[10]; };
88+
struct Wrapper { int a; struct HasCharArray d; };
89+
constexpr struct Wrapper W = {
90+
#embed "numbers.txt"
91+
};
92+
8593
}

clang/test/Preprocessor/embed_constexpr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,3 +96,11 @@ struct ST {};
9696
ST<
9797
#embed <jk.txt> limit(1)
9898
> st;
99+
100+
struct HasCharArray { unsigned char h[10]; };
101+
struct Wrapper { int a; struct HasCharArray d; };
102+
constexpr struct Wrapper W = {
103+
#embed "numbers.txt"
104+
};
105+
106+
static_assert(W.d.h[2] == '3');

0 commit comments

Comments
 (0)