summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Sema/SemaInit.cpp58
-rw-r--r--clang/test/CodeGen/designated-initializers.c30
-rw-r--r--clang/test/CodeGenObjC/designated-initializers.m8
3 files changed, 96 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index 7d73e0890ec..4d6eaa45c41 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -2075,6 +2075,64 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity,
DesignatedEndIndex.setIsUnsigned(true);
}
+ if (!VerifyOnly && StructuredList->isStringLiteralInit()) {
+ // We're modifying a string literal init; we have to decompose the string
+ // so we can modify the individual characters.
+ ASTContext &Context = SemaRef.Context;
+ Expr *SubExpr = StructuredList->getInit(0)->IgnoreParens();
+
+ // Compute the character type
+ QualType CharTy = AT->getElementType();
+
+ // Compute the type of the integer literals.
+ QualType PromotedCharTy = CharTy;
+ if (CharTy->isPromotableIntegerType())
+ PromotedCharTy = Context.getPromotedIntegerType(CharTy);
+ unsigned PromotedCharTyWidth = Context.getTypeSize(PromotedCharTy);
+
+ if (StringLiteral *SL = dyn_cast<StringLiteral>(SubExpr)) {
+ // Get the length of the string.
+ uint64_t StrLen = SL->getLength();
+ if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen))
+ StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue();
+ StructuredList->resizeInits(Context, StrLen);
+
+ // Build a literal for each character in the string, and put them into
+ // the init list.
+ for (unsigned i = 0, e = StrLen; i != e; ++i) {
+ llvm::APInt CodeUnit(PromotedCharTyWidth, SL->getCodeUnit(i));
+ Expr *Init = new (Context) IntegerLiteral(
+ Context, CodeUnit, PromotedCharTy, SourceLocation());
+ if (CharTy != PromotedCharTy)
+ Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
+ Init, 0, VK_RValue);
+ StructuredList->updateInit(Context, i, Init);
+ }
+ } else {
+ ObjCEncodeExpr *E = cast<ObjCEncodeExpr>(SubExpr);
+ std::string Str;
+ Context.getObjCEncodingForType(E->getEncodedType(), Str);
+
+ // Get the length of the string.
+ uint64_t StrLen = Str.size();
+ if (cast<ConstantArrayType>(AT)->getSize().ult(StrLen))
+ StrLen = cast<ConstantArrayType>(AT)->getSize().getZExtValue();
+ StructuredList->resizeInits(Context, StrLen);
+
+ // Build a literal for each character in the string, and put them into
+ // the init list.
+ for (unsigned i = 0, e = StrLen; i != e; ++i) {
+ llvm::APInt CodeUnit(PromotedCharTyWidth, Str[i]);
+ Expr *Init = new (Context) IntegerLiteral(
+ Context, CodeUnit, PromotedCharTy, SourceLocation());
+ if (CharTy != PromotedCharTy)
+ Init = ImplicitCastExpr::Create(Context, CharTy, CK_IntegralCast,
+ Init, 0, VK_RValue);
+ StructuredList->updateInit(Context, i, Init);
+ }
+ }
+ }
+
// Make sure that our non-designated initializer list has space
// for a subobject corresponding to this array element.
if (!VerifyOnly &&
diff --git a/clang/test/CodeGen/designated-initializers.c b/clang/test/CodeGen/designated-initializers.c
index 6561ce56d82..b41898600b2 100644
--- a/clang/test/CodeGen/designated-initializers.c
+++ b/clang/test/CodeGen/designated-initializers.c
@@ -52,6 +52,36 @@ struct ds ds7 = {
.b = 3
};
+
+// <rdar://problem/10465114>
+struct overwrite_string_struct1 {
+ __typeof(L"foo"[0]) L[6];
+ int M;
+} overwrite_string1[] = { { { L"foo" }, 1 }, [0].L[2] = L'x'};
+// CHECK: [6 x i32] [i32 102, i32 111, i32 120, i32 0, i32 0, i32 0], i32 1
+struct overwrite_string_struct2 {
+ char L[6];
+ int M;
+} overwrite_string2[] = { { { "foo" }, 1 }, [0].L[2] = 'x'};
+// CHECK: [6 x i8] c"fox\00\00\00", i32 1
+struct overwrite_string_struct3 {
+ char L[3];
+ int M;
+} overwrite_string3[] = { { { "foo" }, 1 }, [0].L[2] = 'x'};
+// CHECK: [3 x i8] c"fox", i32 1
+struct overwrite_string_struct4 {
+ char L[3];
+ int M;
+} overwrite_string4[] = { { { "foobar" }, 1 }, [0].L[2] = 'x'};
+// CHECK: [3 x i8] c"fox", i32 1
+struct overwrite_string_struct5 {
+ char L[6];
+ int M;
+} overwrite_string5[] = { { { "foo" }, 1 }, [0].L[4] = 'y'};
+// CHECK: [6 x i8] c"foo\00y\00", i32 1
+
+
+
void test1(int argc, char **argv)
{
// CHECK: internal global %struct.foo { i8* null, i32 1024 }
diff --git a/clang/test/CodeGenObjC/designated-initializers.m b/clang/test/CodeGenObjC/designated-initializers.m
new file mode 100644
index 00000000000..80dfdf3602c
--- /dev/null
+++ b/clang/test/CodeGenObjC/designated-initializers.m
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s
+
+// <rdar://problem/10465114>
+struct overwrite_string_struct {
+ char L[3];
+ int M;
+} overwrite_string[] = { { { @encode(void**) }, 1 }, [0].L[1] = 'x'};
+// CHECK: [3 x i8] c"^xv", i32 1
OpenPOWER on IntegriCloud