diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-12-22 01:07:19 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-12-22 01:07:19 +0000 |
commit | 974c5f93d0ce4f0699a6f0a4402f6b367da495e3 (patch) | |
tree | cc58c77ff4dc41f3446ec9398e2aa62ef5af63c5 | |
parent | 280cf1451b4f02093e47ce956a0688407aa595b9 (diff) |
PR11637: implement special-case constant evaluation for char arrays initialized
by string literals.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147120 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/AST/ExprConstant.cpp | 26 | ||||
-rw-r--r-- | test/SemaCXX/constant-expression-cxx11.cpp | 14 |
2 files changed, 40 insertions, 0 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index d4828e3418..8e6682bcde 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -3084,6 +3084,32 @@ bool ArrayExprEvaluator::VisitInitListExpr(const InitListExpr *E) { if (!CAT) return Error(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 && CAT->getElementType()->isAnyCharacterType() && + Info.Ctx.hasSameUnqualifiedType(E->getType(), E->getInit(0)->getType())) { + 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.Designator.addIndex(0); + for (uint64_t I = 0; I < NumElements; ++I) { + CCValue Char; + if (!HandleLValueToRValueConversion(Info, E->getInit(0), + CAT->getElementType(), LV, Char)) + return false; + if (!CheckConstantExpression(Info, E->getInit(0), Char, + Result.getArrayInitializedElt(I))) + return false; + if (!HandleLValueArrayAdjustment(Info, LV, CAT->getElementType(), 1)) + return false; + } + return true; + } + Result = APValue(APValue::UninitArray(), E->getNumInits(), CAT->getSize().getZExtValue()); LValue Subobject = This; diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index af0d5f3e1c..995cd2ffec 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -391,6 +391,20 @@ struct S { int n : "foo"[4]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}} }; +struct T { + char c[6]; + constexpr T() : c{"foo"} {} +}; +constexpr T t; + +static_assert(t.c[0] == 'f', ""); +static_assert(t.c[1] == 'o', ""); +static_assert(t.c[2] == 'o', ""); +static_assert(t.c[3] == 0, ""); +static_assert(t.c[4] == 0, ""); +static_assert(t.c[5] == 0, ""); +static_assert(t.c[6] == 0, ""); // expected-error {{constant expression}} expected-note {{one-past-the-end}} + } namespace Array { |