aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-15 02:50:59 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-15 02:50:59 +0000
commitfe587201feaebc69e6d18858bea85c77926b6ecf (patch)
treeb05fd7a32038f1c0eeb066440f7a2a9cc2564a15 /lib/AST/ExprConstant.cpp
parent8590d86ea35d0dd04711edd6b8dc57fa9a528305 (diff)
PR12226: don't generate wrong code if a braced string literal is used to
initialize an array of unsigned char. Outside C++11 mode, this bug was benign, and just resulted in us emitting a constant which was double the required length, padded with 0s. In C++11, it resulted in us generating an array whose first element was something like i8 ptrtoint ([n x i8]* @str to i8). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154756 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r--lib/AST/ExprConstant.cpp15
1 files changed, 9 insertions, 6 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 01c9fe7cd8..98fc0e5cf3 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1491,15 +1491,19 @@ static unsigned getBaseIndex(const CXXRecordDecl *Derived,
llvm_unreachable("base class missing from derived class's bases list");
}
-/// Extract the value of a character from a string literal.
+/// Extract the value of a character from a string literal. CharType is used to
+/// determine the expected signedness of the result -- a string literal used to
+/// initialize an array of 'signed char' or 'unsigned char' might contain chars
+/// of the wrong signedness.
static APSInt ExtractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
- uint64_t Index) {
+ uint64_t Index, QualType CharType) {
// FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
const StringLiteral *S = dyn_cast<StringLiteral>(Lit);
assert(S && "unexpected string literal expression kind");
+ assert(CharType->isIntegerType() && "unexpected character type");
APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(),
- Lit->getType()->getArrayElementTypeNoTypeQual()->isUnsignedIntegerType());
+ CharType->isUnsignedIntegerType());
if (Index < S->getLength())
Value = S->getCodeUnit(Index);
return Value;
@@ -1546,7 +1550,7 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
assert(I == N - 1 && "extracting subobject of character?");
assert(!O->hasLValuePath() || O->getLValuePath().empty());
Obj = APValue(ExtractStringLiteralCharacter(
- Info, O->getLValueBase().get<const Expr*>(), Index));
+ Info, O->getLValueBase().get<const Expr*>(), Index, SubType));
return true;
} else if (O->getArrayInitializedElts() > Index)
O = &O->getArrayInitializedElt(Index);
@@ -3849,8 +3853,7 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
// C++11 [dcl.init.string]p1: A char array [...] can be initialized by [...]
// an appropriately-typed string literal enclosed in braces.
- if (E->getNumInits() == 1 && E->getInit(0)->isGLValue() &&
- Info.Ctx.hasSameUnqualifiedType(E->getType(), E->getInit(0)->getType())) {
+ if (E->isStringLiteralInit()) {
LValue LV;
if (!EvaluateLValue(E->getInit(0), LV, Info))
return false;