]> granicus.if.org Git - clang/commitdiff
PR11637: implement special-case constant evaluation for char arrays initialized
authorRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 22 Dec 2011 01:07:19 +0000 (01:07 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Thu, 22 Dec 2011 01:07:19 +0000 (01:07 +0000)
by string literals.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147120 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ExprConstant.cpp
test/SemaCXX/constant-expression-cxx11.cpp

index d4828e341838aec892d7c0e1134d84be4f5233cb..8e6682bcdee3c5cd40b4fb36c8125a5b765e2826 100644 (file)
@@ -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;
index af0d5f3e1c37905c54860d16ac5cd224e5f5a9f3..995cd2ffece2a1602556e9bbe8db345e1564b2f2 100644 (file)
@@ -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 {