diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-11-12 22:28:03 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2011-11-12 22:28:03 +0000 |
commit | 1bf9a9e6a5bdc0de7939908855dcddf46b661800 (patch) | |
tree | 81774dcc4e8eec6cbd2a95cf48e9236a1771bd30 | |
parent | 8213ecaa7ce2048f1e10b02f730aefb7fdda57fe (diff) |
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.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@144468 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/APValue.h | 14 | ||||
-rw-r--r-- | lib/AST/APValue.cpp | 13 | ||||
-rw-r--r-- | lib/AST/ExprConstant.cpp | 160 | ||||
-rw-r--r-- | lib/CodeGen/CGExprConstant.cpp | 45 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 1 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp | 8 | ||||
-rw-r--r-- | test/CodeGenCXX/const-init.cpp | 7 | ||||
-rw-r--r-- | test/SemaCXX/constant-expression-cxx11.cpp | 4 |
8 files changed, 126 insertions, 126 deletions
diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index 0d6af425e9..69b1d1b80d 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -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 @@ namespace clang { 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: ((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"); diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index e64bf7cbce..146ebad055 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -21,7 +21,7 @@ using namespace clang; namespace { struct LVBase { - const Expr *Base; + APValue::LValueBase Base; CharUnits Offset; unsigned PathLength; }; @@ -75,11 +75,6 @@ APValue::UnionData::~UnionData () { 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 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, 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 @@ ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { 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 @@ void APValue::setLValue(const Expr *B, const CharUnits &O, NoLValuePath) { 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); diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 7eb818d223..1451fd1119 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -47,6 +47,13 @@ namespace { 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 @@ namespace { 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 @@ namespace { 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 @@ namespace { }; 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 @@ namespace { 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 @@ static bool IsStringLiteralCall(const CallExpr *E) { 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 @@ static bool CheckConstantExpression(const CCValue &CCValue, APValue &Value) { } 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 IsWeakLValue(const LValue &Value) { } 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 @@ static bool ExtractMostDerivedObject(EvalInfo &Info, LValue &Result, 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 @@ static bool HandleLValueArrayAdjustment(EvalInfo &Info, LValue &LVal, } /// 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 @@ static bool EvaluateVarDeclInit(EvalInfo &Info, const Expr *E,const VarDecl *VD, 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 @@ static bool ExtractSubobject(EvalInfo &Info, CCValue &Obj, QualType ObjType, /// \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 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type, // 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 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type, !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 @@ static bool HandleLValueToRValueConversion(EvalInfo &Info, QualType Type, // 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 @@ static bool EvaluateObjectArgument(EvalInfo &Info, const Expr *Object, 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 @@ public: } 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 @@ public: // // 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 @@ public: // * 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 @@ class LValueExprEvaluator 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 @@ static bool EvaluateLValue(const Expr* E, LValue& Result, EvalInfo &Info) { } 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::VisitDeclRefExpr(const DeclRefExpr *E) { 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::VisitVarDecl(const Expr *E, const VarDecl *VD) { 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 @@ bool LValueExprEvaluator::VisitMemberExpr(const MemberExpr *E) { 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 @@ class PointerExprEvaluator LValue &Result; bool Success(const Expr *E) { - Result.setExpr(E); + Result.set(E); return true; } public: @@ -1802,7 +1789,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr* E) { 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 @@ public: 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 @@ static int EvaluateBuiltinClassifyType(const CallExpr *E) { /// 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 @@ bool IntExprEvaluator::TryEvaluateBuiltinObjectSize(const CallExpr *E) { 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 @@ static bool HasSameBase(const LValue &A, const LValue &B) { 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 @@ static bool Evaluate(CCValue &Result, EvalInfo &Info, const Expr *E) { 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]; diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index fc87873687..819fc3fa08 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -843,25 +843,8 @@ public: } 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 @@ public: } } } - 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 @@ llvm::Constant *CodeGenModule::EmitConstantExpr(const Expr *E, 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()) { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index fa002bba19..c0d910b428 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -2382,6 +2382,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // 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)) { diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp index f7da24dfc2..51a062d866 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p8.cpp @@ -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 { diff --git a/test/CodeGenCXX/const-init.cpp b/test/CodeGenCXX/const-init.cpp index f06e546ec9..1fc3deba41 100644 --- a/test/CodeGenCXX/const-init.cpp +++ b/test/CodeGenCXX/const-init.cpp @@ -29,12 +29,17 @@ namespace test2 { 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. diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp index 71a98a5fcf..d208362cbc 100644 --- a/test/SemaCXX/constant-expression-cxx11.cpp +++ b/test/SemaCXX/constant-expression-cxx11.cpp @@ -187,6 +187,10 @@ namespace StaticMemberFunction { 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 { |