diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 58 | ||||
| -rw-r--r-- | clang/test/CodeGen/designated-initializers.c | 30 | ||||
| -rw-r--r-- | clang/test/CodeGenObjC/designated-initializers.m | 8 | 
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  | 

