[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