[cfe-commits] r144468 - in /cfe/trunk: include/clang/AST/APValue.h lib/AST/APValue.cpp lib/AST/ExprConstant.cpp lib/CodeGen/CGExprConstant.cpp lib/Sema/SemaType.cpp test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp test/CodeGenCXX/const-init.cpp test/SemaCXX/constant-expression-cxx11.cpp

Richard Smith richard-llvm at metafoo.co.uk
Sat Nov 12 14:28:04 PST 2011


Author: rsmith
Date: Sat Nov 12 16:28:03 2011
New Revision: 144468

URL: http://llvm.org/viewvc/llvm-project?rev=144468&view=rev
Log:
Represent an APValue based on a Decl as that Decl, rather than a DeclRefExpr
or MemberExpr which refers to it. As a side-effect, MemberExprs which refer to
static member functions and static data members are now emitted as constant
expressions.

Modified:
    cfe/trunk/include/clang/AST/APValue.h
    cfe/trunk/lib/AST/APValue.cpp
    cfe/trunk/lib/AST/ExprConstant.cpp
    cfe/trunk/lib/CodeGen/CGExprConstant.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp
    cfe/trunk/test/CodeGenCXX/const-init.cpp
    cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp

Modified: cfe/trunk/include/clang/AST/APValue.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/APValue.h?rev=144468&r1=144467&r2=144468&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/APValue.h (original)
+++ cfe/trunk/include/clang/AST/APValue.h Sat Nov 12 16:28:03 2011
@@ -18,6 +18,7 @@
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/PointerIntPair.h"
+#include "llvm/ADT/PointerUnion.h"
 
 namespace clang {
   class CharUnits;
@@ -25,6 +26,7 @@
   class Expr;
   class FieldDecl;
   class Decl;
+  class ValueDecl;
 
 /// APValue - This class implements a discriminated union of [uninitialized]
 /// [APSInt] [APFloat], [Complex APSInt] [Complex APFloat], [Expr + Offset],
@@ -45,6 +47,7 @@
     Struct,
     Union
   };
+  typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase;
   typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType;
   union LValuePathEntry {
     /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item
@@ -124,15 +127,14 @@
   APValue(const APValue &RHS) : Kind(Uninitialized) {
     *this = RHS;
   }
-  APValue(const Expr *B, const CharUnits &O, NoLValuePath N)
+  APValue(LValueBase B, const CharUnits &O, NoLValuePath N)
       : Kind(Uninitialized) {
     MakeLValue(); setLValue(B, O, N);
   }
-  APValue(const Expr *B, const CharUnits &O, ArrayRef<LValuePathEntry> Path)
+  APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path)
       : Kind(Uninitialized) {
     MakeLValue(); setLValue(B, O, Path);
   }
-  APValue(const Expr *B);
   APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) {
     MakeArray(InitElts, Size);
   }
@@ -211,7 +213,7 @@
     return const_cast<APValue*>(this)->getComplexFloatImag();
   }
 
-  const Expr* getLValueBase() const;
+  const LValueBase getLValueBase() const;
   CharUnits &getLValueOffset();
   const CharUnits &getLValueOffset() const {
     return const_cast<APValue*>(this)->getLValueOffset();
@@ -324,8 +326,8 @@
     ((ComplexAPFloat*)(char*)Data)->Real = R;
     ((ComplexAPFloat*)(char*)Data)->Imag = I;
   }
-  void setLValue(const Expr *B, const CharUnits &O, NoLValuePath);
-  void setLValue(const Expr *B, const CharUnits &O,
+  void setLValue(LValueBase B, const CharUnits &O, NoLValuePath);
+  void setLValue(LValueBase B, const CharUnits &O,
                  ArrayRef<LValuePathEntry> Path);
   void setUnion(const FieldDecl *Field, const APValue &Value) {
     assert(isUnion() && "Invalid accessor");

Modified: cfe/trunk/lib/AST/APValue.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/APValue.cpp?rev=144468&r1=144467&r2=144468&view=diff
==============================================================================
--- cfe/trunk/lib/AST/APValue.cpp (original)
+++ cfe/trunk/lib/AST/APValue.cpp Sat Nov 12 16:28:03 2011
@@ -21,7 +21,7 @@
 
 namespace {
   struct LVBase {
-    const Expr *Base;
+    APValue::LValueBase Base;
     CharUnits Offset;
     unsigned PathLength;
   };
@@ -75,11 +75,6 @@
   delete Value;
 }
 
-APValue::APValue(const Expr* B) : Kind(Uninitialized) {
-  MakeLValue();
-  setLValue(B, CharUnits::Zero(), ArrayRef<LValuePathEntry>());
-}
-
 const APValue &APValue::operator=(const APValue &RHS) {
   if (this == &RHS)
     return *this;
@@ -297,7 +292,7 @@
   return DB << Out.str();
 }
 
-const Expr* APValue::getLValueBase() const {
+const APValue::LValueBase APValue::getLValueBase() const {
   assert(isLValue() && "Invalid accessor");
   return ((const LV*)(const void*)Data)->Base;
 }
@@ -318,7 +313,7 @@
   return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength);
 }
 
-void APValue::setLValue(const Expr *B, const CharUnits &O, NoLValuePath) {
+void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath) {
   assert(isLValue() && "Invalid accessor");
   LV &LVal = *((LV*)(char*)Data);
   LVal.freePath();
@@ -327,7 +322,7 @@
   LVal.PathLength = (unsigned)-1;
 }
 
-void APValue::setLValue(const Expr *B, const CharUnits &O,
+void APValue::setLValue(LValueBase B, const CharUnits &O,
                         ArrayRef<LValuePathEntry> Path) {
   assert(isLValue() && "Invalid accessor");
   LV &LVal = *((LV*)(char*)Data);

Modified: cfe/trunk/lib/AST/ExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=144468&r1=144467&r2=144468&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprConstant.cpp (original)
+++ cfe/trunk/lib/AST/ExprConstant.cpp Sat Nov 12 16:28:03 2011
@@ -47,6 +47,13 @@
   struct CallStackFrame;
   struct EvalInfo;
 
+  QualType getType(APValue::LValueBase B) {
+    if (!B) return QualType();
+    if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>())
+      return D->getType();
+    return B.get<const Expr*>()->getType();
+  }
+
   /// Get an LValue path entry, which is known to not be an array index, as a
   /// field declaration.
   const FieldDecl *getAsField(APValue::LValuePathEntry E) {
@@ -115,7 +122,7 @@
         ArrayRef<PathEntry> VEntries = V.getLValuePath();
         Entries.insert(Entries.end(), VEntries.begin(), VEntries.end());
         if (V.getLValueBase())
-          ArrayElement = SubobjectIsArrayElement(V.getLValueBase()->getType(),
+          ArrayElement = SubobjectIsArrayElement(getType(V.getLValueBase()),
                                                  V.getLValuePath());
         else
           assert(V.getLValuePath().empty() &&"Null pointer with nonempty path");
@@ -190,7 +197,7 @@
     CCValue(const APSInt &R, const APSInt &I) : APValue(R, I) {}
     CCValue(const APFloat &R, const APFloat &I) : APValue(R, I) {}
     CCValue(const CCValue &V) : APValue(V), CallFrame(V.CallFrame) {}
-    CCValue(const Expr *B, const CharUnits &O, CallStackFrame *F,
+    CCValue(LValueBase B, const CharUnits &O, CallStackFrame *F,
             const SubobjectDesignator &D) :
       APValue(B, O, APValue::NoLValuePath()), CallFrame(F), Designator(D) {}
     CCValue(const APValue &V, GlobalValue) :
@@ -338,12 +345,12 @@
   };
 
   struct LValue {
-    const Expr *Base;
+    APValue::LValueBase Base;
     CharUnits Offset;
     CallStackFrame *Frame;
     SubobjectDesignator Designator;
 
-    const Expr *getLValueBase() const { return Base; }
+    const APValue::LValueBase getLValueBase() const { return Base; }
     CharUnits &getLValueOffset() { return Offset; }
     const CharUnits &getLValueOffset() const { return Offset; }
     CallStackFrame *getLValueFrame() const { return Frame; }
@@ -361,8 +368,8 @@
       Designator = V.getLValueDesignator();
     }
 
-    void setExpr(const Expr *E, CallStackFrame *F = 0) {
-      Base = E;
+    void set(APValue::LValueBase B, CallStackFrame *F = 0) {
+      Base = B;
       Offset = CharUnits::Zero();
       Frame = F;
       Designator = SubobjectDesignator();
@@ -392,27 +399,26 @@
           Builtin == Builtin::BI__builtin___NSStringMakeConstantString);
 }
 
-static bool IsGlobalLValue(const Expr* E) {
+static bool IsGlobalLValue(APValue::LValueBase B) {
   // C++11 [expr.const]p3 An address constant expression is a prvalue core
   // constant expression of pointer type that evaluates to...
 
   // ... a null pointer value, or a prvalue core constant expression of type
   // std::nullptr_t.
-  if (!E) return true;
+  if (!B) return true;
 
-  switch (E->getStmtClass()) {
-  default:
-    return false;
-  case Expr::DeclRefExprClass: {
-    const DeclRefExpr *DRE = cast<DeclRefExpr>(E);
+  if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) {
     // ... the address of an object with static storage duration,
-    if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+    if (const VarDecl *VD = dyn_cast<VarDecl>(D))
       return VD->hasGlobalStorage();
-    // ... to the address of a function,
-    if (isa<FunctionDecl>(DRE->getDecl()))
-      return true;
-    return false;
+    // ... the address of a function,
+    return isa<FunctionDecl>(D);
   }
+
+  const Expr *E = B.get<const Expr*>();
+  switch (E->getStmtClass()) {
+  default:
+    return false;
   case Expr::CompoundLiteralExprClass:
     return cast<CompoundLiteralExpr>(E)->isFileScope();
   // A string literal has static storage duration.
@@ -469,27 +475,11 @@
 }
 
 const ValueDecl *GetLValueBaseDecl(const LValue &LVal) {
-  if (!LVal.Base)
-    return 0;
-
-  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(LVal.Base))
-    return DRE->getDecl();
-
-  // FIXME: Static data members accessed via a MemberExpr are represented as
-  // that MemberExpr. We should use the Decl directly instead.
-  if (const MemberExpr *ME = dyn_cast<MemberExpr>(LVal.Base)) {
-    assert(!isa<FieldDecl>(ME->getMemberDecl()) && "shouldn't see fields here");
-    return ME->getMemberDecl();
-  }
-
-  return 0;
+  return LVal.Base.dyn_cast<const ValueDecl*>();
 }
 
 static bool IsLiteralLValue(const LValue &Value) {
-  return Value.Base &&
-         !isa<DeclRefExpr>(Value.Base) &&
-         !isa<MemberExpr>(Value.Base) &&
-         !isa<MaterializeTemporaryExpr>(Value.Base);
+  return Value.Base.dyn_cast<const Expr*>() && !Value.Frame;
 }
 
 static bool IsWeakDecl(const ValueDecl *Decl) {
@@ -504,18 +494,16 @@
 }
 
 static bool EvalPointerValueAsBool(const LValue &Value, bool &Result) {
-  const Expr* Base = Value.Base;
-
   // A null base expression indicates a null pointer.  These are always
   // evaluatable, and they are false unless the offset is zero.
-  if (!Base) {
+  if (!Value.Base) {
     Result = !Value.Offset.isZero();
     return true;
   }
 
   // Require the base expression to be a global l-value.
   // FIXME: C++11 requires such conversions. Remove this check.
-  if (!IsGlobalLValue(Base)) return false;
+  if (!IsGlobalLValue(Value.Base)) return false;
 
   // We have a non-null base expression.  These are generally known to
   // be true, but if it'a decl-ref to a weak symbol it can be null at
@@ -617,7 +605,7 @@
   if (D.Invalid || !Result.Base)
     return false;
 
-  const Type *T = Result.Base->getType().getTypePtr();
+  const Type *T = getType(Result.Base).getTypePtr();
 
   // Find path prefix which leads to the most-derived subobject.
   unsigned MostDerivedPathLength = 0;
@@ -743,7 +731,7 @@
 }
 
 /// Try to evaluate the initializer for a variable declaration.
-static bool EvaluateVarDeclInit(EvalInfo &Info, const Expr *E,const VarDecl *VD,
+static bool EvaluateVarDeclInit(EvalInfo &Info, const VarDecl *VD,
                                 CallStackFrame *Frame, CCValue &Result) {
   // If this is a parameter to an active constexpr function call, perform
   // argument substitution.
@@ -785,7 +773,7 @@
   APValue EvalResult;
   InitInfo.setEvaluatingDecl(VD, EvalResult);
   LValue LVal;
-  LVal.setExpr(E);
+  LVal.set(VD);
   // FIXME: The caller will need to know whether the value was a constant
   // expression. If not, we should propagate up a diagnostic.
   if (!EvaluateConstantExpression(EvalResult, InitInfo, LVal, Init)) {
@@ -888,14 +876,14 @@
 /// \param RVal - The produced value will be placed here.
 static bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type,
                                            const LValue &LVal, CCValue &RVal) {
-  const Expr *Base = LVal.Base;
+  const Expr *Base = LVal.Base.dyn_cast<const Expr*>();
   CallStackFrame *Frame = LVal.Frame;
 
   // FIXME: Indirection through a null pointer deserves a diagnostic.
-  if (!Base)
+  if (!LVal.Base)
     return false;
 
-  if (const ValueDecl *D = GetLValueBaseDecl(LVal)) {
+  if (const ValueDecl *D = LVal.Base.dyn_cast<const ValueDecl*>()) {
     // In C++98, const, non-volatile integers initialized with ICEs are ICEs.
     // In C++11, constexpr, non-volatile variables initialized with constant
     // expressions are constant expressions too. Inside constexpr functions,
@@ -908,9 +896,9 @@
     // objects in constant expressions), but lvalue-to-rvalue conversions on
     // them are not permitted.
     const VarDecl *VD = dyn_cast<VarDecl>(D);
-    QualType VT = VD->getType();
     if (!VD || VD->isInvalidDecl())
       return false;
+    QualType VT = VD->getType();
     if (!isa<ParmVarDecl>(VD)) {
       if (!IsConstNonVolatile(VT))
         return false;
@@ -919,7 +907,7 @@
           !VD->isConstexpr())
         return false;
     }
-    if (!EvaluateVarDeclInit(Info, LVal.Base, VD, Frame, RVal))
+    if (!EvaluateVarDeclInit(Info, VD, Frame, RVal))
       return false;
 
     if (isa<ParmVarDecl>(VD) || !VD->getAnyInitializer()->isLValue())
@@ -932,7 +920,7 @@
     // value we were originally given.
     assert(RVal.getLValueOffset().isZero() &&
            "offset for lvalue init of non-reference");
-    Base = RVal.getLValueBase();
+    Base = RVal.getLValueBase().get<const Expr*>();
     Frame = RVal.getLValueFrame();
   }
 
@@ -982,7 +970,7 @@
     return EvaluateLValue(Object, This, Info);
 
   // Implicitly promote a prvalue *this object to a glvalue.
-  This.setExpr(Object, Info.CurrentCall);
+  This.set(Object, Info.CurrentCall);
   return EvaluateConstantExpression(Info.CurrentCall->Temporaries[Object], Info,
                                     This, Object);
 }
@@ -1338,15 +1326,11 @@
     } else if (CalleeType->isFunctionPointerType()) {
       CCValue Call;
       if (!Evaluate(Call, Info, Callee) || !Call.isLValue() ||
-          !Call.getLValueBase() || !Call.getLValueOffset().isZero())
+          !Call.getLValueOffset().isZero())
         return DerivedError(Callee);
 
-      const Expr *Base = Call.getLValueBase();
-
-      if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base))
-        FD = dyn_cast<FunctionDecl>(DRE->getDecl());
-      else if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base))
-        FD = dyn_cast<FunctionDecl>(ME->getMemberDecl());
+      FD = dyn_cast_or_null<FunctionDecl>(
+                             Call.getLValueBase().dyn_cast<const ValueDecl*>());
       if (!FD)
         return DerivedError(Callee);
 
@@ -1462,8 +1446,10 @@
 //
 // LValue evaluation produces values comprising a base expression of one of the
 // following types:
-//  * DeclRefExpr
-//  * MemberExpr for a static member
+// - Declarations
+//  * VarDecl
+//  * FunctionDecl
+// - Literals
 //  * CompoundLiteralExpr in C
 //  * StringLiteral
 //  * PredefinedExpr
@@ -1472,9 +1458,10 @@
 //  * AddrLabelExpr
 //  * BlockExpr
 //  * CallExpr for a MakeStringConstant builtin
-// plus an offset in bytes. It can also produce lvalues referring to locals. In
-// that case, the Frame will point to a stack frame, and the Expr is used as a
-// key to find the relevant temporary's value.
+// - Locals and temporaries
+//  * Any Expr, with a Frame indicating the function in which the temporary was
+//    evaluated.
+// plus an offset in bytes.
 //===----------------------------------------------------------------------===//
 namespace {
 class LValueExprEvaluator
@@ -1482,8 +1469,8 @@
   LValue &Result;
   const Decl *PrevDecl;
 
-  bool Success(const Expr *E) {
-    Result.setExpr(E);
+  bool Success(APValue::LValueBase B) {
+    Result.set(B);
     return true;
   }
 public:
@@ -1561,9 +1548,9 @@
 }
 
 bool LValueExprEvaluator::VisitDeclRefExpr(const DeclRefExpr *E) {
-  if (isa<FunctionDecl>(E->getDecl()))
-    return Success(E);
-  if (const VarDecl* VD = dyn_cast<VarDecl>(E->getDecl()))
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl()))
+    return Success(FD);
+  if (const VarDecl *VD = dyn_cast<VarDecl>(E->getDecl()))
     return VisitVarDecl(E, VD);
   return Error(E);
 }
@@ -1571,14 +1558,14 @@
 bool LValueExprEvaluator::VisitVarDecl(const Expr *E, const VarDecl *VD) {
   if (!VD->getType()->isReferenceType()) {
     if (isa<ParmVarDecl>(VD)) {
-      Result.setExpr(E, Info.CurrentCall);
+      Result.set(VD, Info.CurrentCall);
       return true;
     }
-    return Success(E);
+    return Success(VD);
   }
 
   CCValue V;
-  if (EvaluateVarDeclInit(Info, E, VD, Info.CurrentCall, V))
+  if (EvaluateVarDeclInit(Info, VD, Info.CurrentCall, V))
     return Success(V, E);
 
   return Error(E);
@@ -1586,7 +1573,7 @@
 
 bool LValueExprEvaluator::VisitMaterializeTemporaryExpr(
     const MaterializeTemporaryExpr *E) {
-  Result.setExpr(E, Info.CurrentCall);
+  Result.set(E, Info.CurrentCall);
   return EvaluateConstantExpression(Info.CurrentCall->Temporaries[E], Info,
                                     Result, E->GetTemporaryExpr());
 }
@@ -1610,7 +1597,7 @@
   if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(E->getMemberDecl())) {
     if (MD->isStatic()) {
       VisitIgnoredValue(E->getBase());
-      return Success(E);
+      return Success(MD);
     }
   }
 
@@ -1675,7 +1662,7 @@
   LValue &Result;
 
   bool Success(const Expr *E) {
-    Result.setExpr(E);
+    Result.set(E);
     return true;
   }
 public:
@@ -1802,7 +1789,7 @@
     if (Value.isInt()) {
       unsigned Size = Info.Ctx.getTypeSize(E->getType());
       uint64_t N = Value.getInt().extOrTrunc(Size).getZExtValue();
-      Result.Base = 0;
+      Result.Base = (Expr*)0;
       Result.Offset = CharUnits::fromQuantity(N);
       Result.Frame = 0;
       Result.Designator.setInvalid();
@@ -2380,7 +2367,7 @@
 private:
   CharUnits GetAlignOfExpr(const Expr *E);
   CharUnits GetAlignOfType(QualType T);
-  static QualType GetObjectType(const Expr *E);
+  static QualType GetObjectType(APValue::LValueBase B);
   bool TryEvaluateBuiltinObjectSize(const CallExpr *E);
   // FIXME: Missing: array subscript of vector, member of vector
 };
@@ -2490,12 +2477,13 @@
 
 /// Retrieves the "underlying object type" of the given expression,
 /// as used by __builtin_object_size.
-QualType IntExprEvaluator::GetObjectType(const Expr *E) {
-  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
-    if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+QualType IntExprEvaluator::GetObjectType(APValue::LValueBase B) {
+  if (const ValueDecl *D = B.dyn_cast<const ValueDecl*>()) {
+    if (const VarDecl *VD = dyn_cast<VarDecl>(D))
       return VD->getType();
-  } else if (isa<CompoundLiteralExpr>(E)) {
-    return E->getType();
+  } else if (const Expr *E = B.get<const Expr*>()) {
+    if (isa<CompoundLiteralExpr>(E))
+      return E->getType();
   }
 
   return QualType();
@@ -2508,10 +2496,9 @@
     return false;
 
   // If we can prove the base is null, lower to zero now.
-  const Expr *LVBase = Base.getLValueBase();
-  if (!LVBase) return Success(0, E);
+  if (!Base.getLValueBase()) return Success(0, E);
 
-  QualType T = GetObjectType(LVBase);
+  QualType T = GetObjectType(Base.getLValueBase());
   if (T.isNull() ||
       T->isIncompleteType() ||
       T->isFunctionType() ||
@@ -2636,7 +2623,8 @@
   if (!B.getLValueBase())
     return false;
 
-  if (A.getLValueBase() != B.getLValueBase()) {
+  if (A.getLValueBase().getOpaqueValue() !=
+      B.getLValueBase().getOpaqueValue()) {
     const Decl *ADecl = GetLValueBaseDecl(A);
     if (!ADecl)
       return false;
@@ -3895,13 +3883,13 @@
     return false;
   } else if (E->getType()->isArrayType() && E->getType()->isLiteralType()) {
     LValue LV;
-    LV.setExpr(E, Info.CurrentCall);
+    LV.set(E, Info.CurrentCall);
     if (!EvaluateArray(E, LV, Info.CurrentCall->Temporaries[E], Info))
       return false;
     Result = Info.CurrentCall->Temporaries[E];
   } else if (E->getType()->isRecordType() && E->getType()->isLiteralType()) {
     LValue LV;
-    LV.setExpr(E, Info.CurrentCall);
+    LV.set(E, Info.CurrentCall);
     if (!EvaluateRecord(E, LV, Info.CurrentCall->Temporaries[E], Info))
       return false;
     Result = Info.CurrentCall->Temporaries[E];

Modified: cfe/trunk/lib/CodeGen/CGExprConstant.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprConstant.cpp?rev=144468&r1=144467&r2=144468&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprConstant.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprConstant.cpp Sat Nov 12 16:28:03 2011
@@ -843,25 +843,8 @@
   }
 
 public:
-  llvm::Constant *EmitLValue(Expr *E) {
-    switch (E->getStmtClass()) {
-    default: break;
-    case Expr::CompoundLiteralExprClass: {
-      // Note that due to the nature of compound literals, this is guaranteed
-      // to be the only use of the variable, so we just generate it here.
-      CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
-      llvm::Constant* C = Visit(CLE->getInitializer());
-      // FIXME: "Leaked" on failure.
-      if (C)
-        C = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
-                                     E->getType().isConstant(CGM.getContext()),
-                                     llvm::GlobalValue::InternalLinkage,
-                                     C, ".compoundliteral", 0, false,
-                          CGM.getContext().getTargetAddressSpace(E->getType()));
-      return C;
-    }
-    case Expr::DeclRefExprClass: {
-      ValueDecl *Decl = cast<DeclRefExpr>(E)->getDecl();
+  llvm::Constant *EmitLValue(APValue::LValueBase LVBase) {
+    if (const ValueDecl *Decl = LVBase.dyn_cast<const ValueDecl*>()) {
       if (Decl->hasAttr<WeakRefAttr>())
         return CGM.GetWeakRefReference(Decl);
       if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Decl))
@@ -877,7 +860,25 @@
           }
         }
       }
-      break;
+      return 0;
+    }
+
+    Expr *E = const_cast<Expr*>(LVBase.get<const Expr*>());
+    switch (E->getStmtClass()) {
+    default: break;
+    case Expr::CompoundLiteralExprClass: {
+      // Note that due to the nature of compound literals, this is guaranteed
+      // to be the only use of the variable, so we just generate it here.
+      CompoundLiteralExpr *CLE = cast<CompoundLiteralExpr>(E);
+      llvm::Constant* C = Visit(CLE->getInitializer());
+      // FIXME: "Leaked" on failure.
+      if (C)
+        C = new llvm::GlobalVariable(CGM.getModule(), C->getType(),
+                                     E->getType().isConstant(CGM.getContext()),
+                                     llvm::GlobalValue::InternalLinkage,
+                                     C, ".compoundliteral", 0, false,
+                          CGM.getContext().getTargetAddressSpace(E->getType()));
+      return C;
     }
     case Expr::StringLiteralClass:
       return CGM.GetAddrOfConstantStringFromLiteral(cast<StringLiteral>(E));
@@ -963,8 +964,8 @@
                                Result.Val.getLValueOffset().getQuantity());
 
       llvm::Constant *C;
-      if (const Expr *LVBase = Result.Val.getLValueBase()) {
-        C = ConstExprEmitter(*this, CGF).EmitLValue(const_cast<Expr*>(LVBase));
+      if (APValue::LValueBase LVBase = Result.Val.getLValueBase()) {
+        C = ConstExprEmitter(*this, CGF).EmitLValue(LVBase);
 
         // Apply offset if necessary.
         if (!Offset->isNullValue()) {

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=144468&r1=144467&r2=144468&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Nov 12 16:28:03 2011
@@ -2382,6 +2382,7 @@
     // C++0x [dcl.constexpr]p8: A constexpr specifier for a non-static member
     // function that is not a constructor declares that function to be const.
     if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction &&
+        D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
         D.getName().getKind() != UnqualifiedId::IK_ConstructorName &&
         D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId &&
         !(FnTy->getTypeQuals() & DeclSpec::TQ_const)) {

Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp?rev=144468&r1=144467&r2=144468&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp Sat Nov 12 16:28:03 2011
@@ -1,13 +1,17 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
 
 struct S {
-  constexpr void f();
-  constexpr void g() const;
+  constexpr int f();
+  constexpr int g() const;
+  static constexpr int Sf();
 };
 
 void f(const S &s) {
   s.f();
   s.g();
+
+  int (*f)() = &S::Sf;
+  int (S::*g)() const = &S::g;
 }
 
 namespace std_example {

Modified: cfe/trunk/test/CodeGenCXX/const-init.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/const-init.cpp?rev=144468&r1=144467&r2=144468&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/const-init.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/const-init.cpp Sat Nov 12 16:28:03 2011
@@ -29,12 +29,17 @@
   struct A {
     static const double d = 1.0;
     static const float f = d / 2;
-  };
+    static int g();
+  } a;
 
   // CHECK: @_ZN5test22t0E = global double {{1\.0+e\+0+}}, align 8
   // CHECK: @_ZN5test22t1E = global [2 x double] [double {{1\.0+e\+0+}}, double {{5\.0+e-0*}}1], align 16
+  // CHECK: @_ZN5test22t2E = global double* @_ZN5test21A1d
+  // CHECK: @_ZN5test22t3E = global {{.*}} @_ZN5test21A1g
   double t0 = A::d;
   double t1[] = { A::d, A::f };
+  const double *t2 = &a.d;
+  int (*t3)() = &a.g;
 }
 
 // We don't expect to fold this in the frontend, but make sure it doesn't crash.

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=144468&r1=144467&r2=144468&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp (original)
+++ cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp Sat Nov 12 16:28:03 2011
@@ -187,6 +187,10 @@
   static_assert_fold(S::f(19) == 800, "");
   static_assert_fold(s.f(19) == 800, "");
   static_assert_fold(n == 800, "");
+
+  constexpr int (*sf1)(int) = &S::f;
+  constexpr int (*sf2)(int) = &s.f;
+  constexpr const int *sk = &s.k;
 }
 
 namespace ParameterScopes {





More information about the cfe-commits mailing list