[cfe-commits] r150789 - in /cfe/trunk: lib/AST/ExprConstant.cpp test/CodeGenCXX/const-init-cxx11.cpp test/SemaCXX/constant-expression-cxx11.cpp

Richard Smith richard-llvm at metafoo.co.uk
Thu Feb 16 19:35:37 PST 2012


Author: rsmith
Date: Thu Feb 16 21:35:37 2012
New Revision: 150789

URL: http://llvm.org/viewvc/llvm-project?rev=150789&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=150789&r1=150788&r2=150789&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Thu Feb 16 21:35:37 2012
@@ -1499,6 +1499,20 @@
   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 @@
     // 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 @@
                     (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 @@
     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 @@
     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 @@
       : 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 @@
     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;

Modified: cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp?rev=150789&r1=150788&r2=150789&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init-cxx11.cpp Thu Feb 16 21:35:37 2012
@@ -94,6 +94,14 @@
 
   // 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 {

Modified: cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp?rev=150789&r1=150788&r2=150789&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Thu Feb 16 21:35:37 2012
@@ -408,6 +408,12 @@
 } 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 {





More information about the cfe-commits mailing list