diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2013-06-11 21:48:11 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2013-06-11 21:48:11 +0000 |
commit | 1f16b743d9255f5f75a85c52e3a02d04b4a1e590 (patch) | |
tree | 00a39a3abf5b3384cbc2925ec012597d6373860b /clang/lib/Sema/SemaInit.cpp | |
parent | bd9e549e218c1d47d3c7e44f668eae26418774bc (diff) | |
download | bcm5719-llvm-1f16b743d9255f5f75a85c52e3a02d04b4a1e590.tar.gz bcm5719-llvm-1f16b743d9255f5f75a85c52e3a02d04b4a1e590.zip |
Correctly handle designated initializers which modify an array initialized
with a string. This case is sort of tricky because we can't modify the
StringLiteral used to represent such initializers.
We are forced to decompose the string into individual characters.
Fixes <rdar://problem/10465114>.
llvm-svn: 183791
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 58 |
1 files changed, 58 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 && |