aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-17 03:35:37 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-17 03:35:37 +0000
commitf3908f2ae111b1b12ade2524dda71c669ed6f121 (patch)
treeab98a6ebad3c79951933ae54de6dc8d40b62aff4
parentde5d3c717684f3821b8db58037bc7140acf134aa (diff)
Make sure all remaining parts of the constant evaluator are aware that an array
can be represented by an LValue, and use that to simplify the code a little. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150789 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/AST/ExprConstant.cpp81
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp8
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp6
3 files changed, 49 insertions, 46 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 0ef7111f97..6cbb69dae5 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -1499,6 +1499,20 @@ 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.
+static APSInt ExtractStringLiteralCharacter(EvalInfo &Info, const Expr *Lit,
+ uint64_t Index) {
+ // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
+ const StringLiteral *S = dyn_cast<StringLiteral>(Lit);
+ assert(S && "unexpected string literal expression kind");
+
+ APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(),
+ Lit->getType()->getArrayElementTypeNoTypeQual()->isUnsignedIntegerType());
+ if (Index < S->getLength())
+ Value = S->getCodeUnit(Index);
+ return Value;
+}
+
/// Extract the designated sub-object of an rvalue.
static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
CCValue &Obj, QualType ObjType,
@@ -1518,7 +1532,6 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
// This object might be initialized later.
return false;
- assert(!Obj.isLValue() && "extracting subobject of lvalue");
const APValue *O = &Obj;
// Walk the designator's path to find the subobject.
for (unsigned I = 0, N = Sub.Entries.size(); I != N; ++I) {
@@ -1535,7 +1548,15 @@ static bool ExtractSubobject(EvalInfo &Info, const Expr *E,
(unsigned)diag::note_invalid_subexpr_in_const_expr);
return false;
}
- if (O->getArrayInitializedElts() > Index)
+ // An array object is represented as either an Array APValue or as an
+ // LValue which refers to a string literal.
+ if (O->isLValue()) {
+ assert(I == N - 1 && "extracting subobject of character?");
+ assert(!O->hasLValuePath() || O->getLValuePath().empty());
+ Obj = CCValue(ExtractStringLiteralCharacter(
+ Info, O->getLValueBase().get<const Expr*>(), Index));
+ return true;
+ } else if (O->getArrayInitializedElts() > Index)
O = &O->getArrayInitializedElt(Index);
else
O = &O->getArrayFiller();
@@ -1800,33 +1821,6 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
return false;
}
- // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
- if (const StringLiteral *S = dyn_cast<StringLiteral>(Base)) {
- const SubobjectDesignator &Designator = LVal.Designator;
- if (Designator.Invalid || Designator.Entries.size() != 1) {
- Info.Diag(Conv->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
- return false;
- }
-
- assert(Type->isIntegerType() && "string element not integer type");
- uint64_t Index = Designator.Entries[0].ArrayIndex;
- const ConstantArrayType *CAT =
- Info.Ctx.getAsConstantArrayType(S->getType());
- if (Index >= CAT->getSize().getZExtValue()) {
- // Note, it should not be possible to form a pointer which points more
- // than one past the end of the array without producing a prior const expr
- // diagnostic.
- Info.Diag(Loc, diag::note_constexpr_read_past_end);
- return false;
- }
- APSInt Value(S->getCharByteWidth() * Info.Ctx.getCharWidth(),
- Type->isUnsignedIntegerType());
- if (Index < S->getLength())
- Value = S->getCodeUnit(Index);
- RVal = CCValue(Value);
- return true;
- }
-
if (Frame) {
// If this is a temporary expression with a nontrivial initializer, grab the
// value from the relevant stack frame.
@@ -1839,6 +1833,13 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, const Expr *Conv,
assert(!Info.getLangOpts().CPlusPlus && "lvalue compound literal in c++?");
if (!Evaluate(RVal, Info, CLE->getInitializer()))
return false;
+ } else if (isa<StringLiteral>(Base)) {
+ // We represent a string literal array as an lvalue pointing at the
+ // corresponding expression, rather than building an array of chars.
+ // FIXME: Support PredefinedExpr, ObjCEncodeExpr, MakeStringConstant
+ RVal = CCValue(Info.Ctx,
+ APValue(Base, CharUnits::Zero(), APValue::NoLValuePath(), 0),
+ CCValue::GlobalValue());
} else {
Info.Diag(Conv->getExprLoc(), diag::note_invalid_subexpr_in_const_expr);
return false;
@@ -3777,7 +3778,8 @@ namespace {
: ExprEvaluatorBaseTy(Info), This(This), Result(Result) {}
bool Success(const APValue &V, const Expr *E) {
- assert(V.isArray() && "Expected array type");
+ assert((V.isArray() || V.isLValue()) &&
+ "expected array or string literal");
Result = V;
return true;
}
@@ -3822,22 +3824,9 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) {
LValue LV;
if (!EvaluateLValue(E->getInit(0), LV, Info))
return false;
- uint64_t NumElements = CAT->getSize().getZExtValue();
- Result = APValue(APValue::UninitArray(), NumElements, NumElements);
-
- // Copy the string literal into the array. FIXME: Do this better.
- LV.addArray(Info, E, CAT);
- for (uint64_t I = 0; I < NumElements; ++I) {
- CCValue Char;
- if (!HandleLValueToRValueConversion(Info, E->getInit(0),
- CAT->getElementType(), LV, Char))
- return false;
- Result.getArrayInitializedElt(I) = Char.toAPValue();
- if (!HandleLValueArrayAdjustment(Info, E->getInit(0), LV,
- CAT->getElementType(), 1))
- return false;
- }
- return true;
+ CCValue Val;
+ LV.moveInto(Val);
+ return Success(Val, E);
}
bool Success = true;
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index fa56f59808..14a2f87717 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -94,6 +94,14 @@ namespace Array {
// CHECK: @_ZN5Array1dE = constant {{.*}} { [2 x i32] [i32 1, i32 2], [3 x i32] [i32 3, i32 4, i32 5] }
struct D { int n[2]; int m[3]; } extern constexpr d = { 1, 2, 3, 4, 5 };
+
+ struct E {
+ char c[4];
+ char d[4];
+ constexpr E() : c("foo"), d("x") {}
+ };
+ // CHECK: @_ZN5Array1eE = global {{.*}} { [4 x i8] c"foo\00", [4 x i8] c"x\00\00\00" }
+ extern constexpr E e = E();
}
namespace MemberPtr {
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index f5cc1b31ca..a048297bb5 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -408,6 +408,12 @@ struct U {
} constexpr u = { { L"test" }, 0 };
static_assert(u.chars[2] == L's', "");
+struct V {
+ char c[4];
+ constexpr V() : c("hi!") {}
+};
+static_assert(V().c[1] == "i"[0], "");
+
}
namespace Array {