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.

llvm-svn: 144468
This commit is contained in:
Richard Smith 2011-11-12 22:28:03 +00:00
parent f9d0f4744e
commit ce40ad677e
8 changed files with 126 additions and 126 deletions

View File

@ -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");

View File

@ -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);

View File

@ -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;
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>(D))
return VD->hasGlobalStorage();
// ... the address of a function,
return isa<FunctionDecl>(D);
}
const Expr *E = B.get<const Expr*>();
switch (E->getStmtClass()) {
default:
return false;
case Expr::DeclRefExprClass: {
const DeclRefExpr *DRE = cast<DeclRefExpr>(E);
// ... the address of an object with static storage duration,
if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()))
return VD->hasGlobalStorage();
// ... to the address of a function,
if (isa<FunctionDecl>(DRE->getDecl()))
return true;
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];

View File

@ -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()) {

View File

@ -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)) {

View File

@ -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 {

View File

@ -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.

View File

@ -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 {