summaryrefslogtreecommitdiffstats
path: root/lib
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
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')
-rw-r--r--lib/AST/Expr.cpp10
-rw-r--r--lib/AST/ExprConstant.cpp15
-rw-r--r--lib/CodeGen/CGExprAgg.cpp10
-rw-r--r--lib/CodeGen/CGExprConstant.cpp8
4 files changed, 23 insertions, 20 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 868109e3d5..9556b1acb9 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1590,6 +1590,16 @@ void InitListExpr::setArrayFiller(Expr *filler) {
inits[i] = filler;
}
+bool InitListExpr::isStringLiteralInit() const {
+ if (getNumInits() != 1)
+ return false;
+ const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(getType());
+ if (!CAT || !CAT->getElementType()->isIntegerType())
+ return false;
+ const Expr *Init = getInit(0)->IgnoreParenImpCasts();
+ return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);
+}
+
SourceRange InitListExpr::getSourceRange() const {
if (SyntacticForm)
return SyntacticForm->getSourceRange();
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;
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index b6efc1cafa..975f572c0d 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -916,14 +916,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
// Handle initialization of an array.
if (E->getType()->isArrayType()) {
- if (E->getNumInits() > 0) {
- QualType T1 = E->getType();
- QualType T2 = E->getInit(0)->getType();
- if (CGF.getContext().hasSameUnqualifiedType(T1, T2)) {
- EmitAggLoadOfLValue(E->getInit(0));
- return;
- }
- }
+ if (E->isStringLiteralInit())
+ return Visit(E->getInit(0));
QualType elementType =
CGF.getContext().getAsArrayType(E->getType())->getElementType();
diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp
index d528e0c4b7..bc9f9ef07b 100644
--- a/lib/CodeGen/CGExprConstant.cpp
+++ b/lib/CodeGen/CGExprConstant.cpp
@@ -758,17 +758,13 @@ public:
}
llvm::Constant *EmitArrayInitialization(InitListExpr *ILE) {
- unsigned NumInitElements = ILE->getNumInits();
- if (NumInitElements == 1 &&
- CGM.getContext().hasSameUnqualifiedType(ILE->getType(),
- ILE->getInit(0)->getType()) &&
- (isa<StringLiteral>(ILE->getInit(0)) ||
- isa<ObjCEncodeExpr>(ILE->getInit(0))))
+ if (ILE->isStringLiteralInit())
return Visit(ILE->getInit(0));
llvm::ArrayType *AType =
cast<llvm::ArrayType>(ConvertType(ILE->getType()));
llvm::Type *ElemTy = AType->getElementType();
+ unsigned NumInitElements = ILE->getNumInits();
unsigned NumElements = AType->getNumElements();
// Initialising an array requires us to automatically