summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authored <ed@FreeBSD.org>2009-06-23 14:50:21 +0000
committered <ed@FreeBSD.org>2009-06-23 14:50:21 +0000
commitda468bf93e74598f985f4988936ee5ca2dc9a38c (patch)
tree64b43af65e97f7659637c9ac028e39af2e26b841 /lib
parent8927c19a5ed03bef55dac4b623688387bcc794dc (diff)
downloadFreeBSD-src-da468bf93e74598f985f4988936ee5ca2dc9a38c.zip
FreeBSD-src-da468bf93e74598f985f4988936ee5ca2dc9a38c.tar.gz
Import Clang r73954.
Diffstat (limited to 'lib')
-rw-r--r--lib/AST/Decl.cpp7
-rw-r--r--lib/AST/DeclCXX.cpp22
-rw-r--r--lib/AST/DeclTemplate.cpp126
-rw-r--r--lib/Analysis/BasicStore.cpp28
-rw-r--r--lib/Analysis/CFRefCount.cpp10
-rw-r--r--lib/Analysis/Environment.cpp15
-rw-r--r--lib/Analysis/GRExprEngine.cpp40
-rw-r--r--lib/Analysis/GRExprEngineInternalChecks.cpp4
-rw-r--r--lib/Analysis/GRSimpleVals.cpp23
-rw-r--r--lib/Analysis/MemRegion.cpp254
-rw-r--r--lib/Analysis/RegionStore.cpp99
-rw-r--r--lib/Analysis/SVals.cpp174
-rw-r--r--lib/Analysis/ValueManager.cpp125
-rw-r--r--lib/Basic/SourceManager.cpp5
-rw-r--r--lib/Basic/Targets.cpp1
-rw-r--r--lib/CodeGen/CGCall.cpp3
-rw-r--r--lib/Frontend/InitPreprocessor.cpp1
-rw-r--r--lib/Frontend/Warnings.cpp4
-rw-r--r--lib/Lex/Lexer.cpp5
-rw-r--r--lib/Parse/ParseDecl.cpp2
-rw-r--r--lib/Parse/ParseExpr.cpp9
-rw-r--r--lib/Parse/ParseExprCXX.cpp7
-rw-r--r--lib/Parse/ParseTemplate.cpp4
-rw-r--r--lib/Sema/Sema.cpp14
-rw-r--r--lib/Sema/Sema.h58
-rw-r--r--lib/Sema/SemaDecl.cpp5
-rw-r--r--lib/Sema/SemaDeclCXX.cpp98
-rw-r--r--lib/Sema/SemaExpr.cpp96
-rw-r--r--lib/Sema/SemaExprCXX.cpp25
-rw-r--r--lib/Sema/SemaTemplate.cpp92
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp8
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp11
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp30
-rw-r--r--lib/Sema/SemaTemplateInstantiateExpr.cpp20
-rw-r--r--lib/Sema/SemaTemplateInstantiateStmt.cpp3
35 files changed, 785 insertions, 643 deletions
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index bf63932..71e88a9 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -379,7 +379,7 @@ Stmt *FunctionDecl::getBodyIfAvailable() const {
void FunctionDecl::setBody(Stmt *B) {
Body = B;
- if (B && EndRangeLoc < B->getLocEnd())
+ if (B)
EndRangeLoc = B->getLocEnd();
}
@@ -494,8 +494,9 @@ void FunctionDecl::setParams(ASTContext& C, ParmVarDecl **NewParamInfo,
ParamInfo = new (Mem) ParmVarDecl*[NumParams];
memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams);
- // Update source range.
- if (EndRangeLoc < NewParamInfo[NumParams-1]->getLocEnd())
+ // Update source range. The check below allows us to set EndRangeLoc before
+ // setting the parameters.
+ if (EndRangeLoc.isInvalid() || EndRangeLoc == getLocation())
EndRangeLoc = NewParamInfo[NumParams-1]->getLocEnd();
}
}
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 7a930d7..25e4d19 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -66,21 +66,29 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases,
}
bool CXXRecordDecl::hasConstCopyConstructor(ASTContext &Context) const {
+ return getCopyConstructor(Context, QualType::Const) != 0;
+}
+
+CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context,
+ unsigned TypeQuals) const{
QualType ClassType
= Context.getTypeDeclType(const_cast<CXXRecordDecl*>(this));
DeclarationName ConstructorName
= Context.DeclarationNames.getCXXConstructorName(
- Context.getCanonicalType(ClassType));
- unsigned TypeQuals;
+ Context.getCanonicalType(ClassType));
+ unsigned FoundTQs;
DeclContext::lookup_const_iterator Con, ConEnd;
for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName);
Con != ConEnd; ++Con) {
- if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, TypeQuals) &&
- (TypeQuals & QualType::Const) != 0)
- return true;
+ if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context,
+ FoundTQs)) {
+ if (((TypeQuals & QualType::Const) == (FoundTQs & QualType::Const)) ||
+ (!(TypeQuals & QualType::Const) && (FoundTQs & QualType::Const)))
+ return cast<CXXConstructorDecl>(*Con);
+
+ }
}
-
- return false;
+ return 0;
}
bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const {
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index 23c2637..165672d 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -239,79 +239,103 @@ TemplateArgument::TemplateArgument(Expr *E) : Kind(Expression) {
}
/// \brief Construct a template argument pack.
-TemplateArgument::TemplateArgument(SourceLocation Loc, TemplateArgument *args,
- unsigned NumArgs, bool CopyArgs)
- : Kind(Pack) {
- Args.NumArgs = NumArgs;
- Args.CopyArgs = CopyArgs;
- if (!Args.CopyArgs) {
- Args.Args = args;
- return;
- }
-
- Args.Args = new TemplateArgument[NumArgs];
- for (unsigned I = 0; I != NumArgs; ++I)
- Args.Args[I] = args[I];
+void TemplateArgument::setArgumentPack(TemplateArgument *args, unsigned NumArgs,
+ bool CopyArgs) {
+ assert(isNull() && "Must call setArgumentPack on a null argument");
+
+ Kind = Pack;
+ Args.NumArgs = NumArgs;
+ Args.CopyArgs = CopyArgs;
+ if (!Args.CopyArgs) {
+ Args.Args = args;
+ return;
+ }
+
+ Args.Args = new TemplateArgument[NumArgs];
+ for (unsigned I = 0; I != Args.NumArgs; ++I)
+ Args.Args[I] = args[I];
}
//===----------------------------------------------------------------------===//
// TemplateArgumentListBuilder Implementation
//===----------------------------------------------------------------------===//
-void TemplateArgumentListBuilder::push_back(const TemplateArgument& Arg) {
+
+void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) {
switch (Arg.getKind()) {
- default: break;
- case TemplateArgument::Type:
- assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
- break;
+ default: break;
+ case TemplateArgument::Type:
+ assert(Arg.getAsType()->isCanonical() && "Type must be canonical!");
+ break;
}
- FlatArgs.push_back(Arg);
+ assert(NumFlatArgs < MaxFlatArgs && "Argument list builder is full!");
+ assert(!StructuredArgs &&
+ "Can't append arguments when an argument pack has been added!");
+
+ if (!FlatArgs)
+ FlatArgs = new TemplateArgument[MaxFlatArgs];
- if (!isAddingFromParameterPack())
- StructuredArgs.push_back(Arg);
+ FlatArgs[NumFlatArgs++] = Arg;
}
-void TemplateArgumentListBuilder::BeginParameterPack() {
- assert(!isAddingFromParameterPack() && "Already adding to parameter pack!");
-
- PackBeginIndex = FlatArgs.size();
+void TemplateArgumentListBuilder::BeginPack() {
+ assert(!AddingToPack && "Already adding to pack!");
+ assert(!StructuredArgs && "Argument list already contains a pack!");
+
+ AddingToPack = true;
+ PackBeginIndex = NumFlatArgs;
}
-void TemplateArgumentListBuilder::EndParameterPack() {
- assert(isAddingFromParameterPack() && "Not adding to parameter pack!");
+void TemplateArgumentListBuilder::EndPack() {
+ assert(AddingToPack && "Not adding to pack!");
+ assert(!StructuredArgs && "Argument list already contains a pack!");
+
+ AddingToPack = false;
- unsigned NumArgs = FlatArgs.size() - PackBeginIndex;
- TemplateArgument *Args = NumArgs ? &FlatArgs[PackBeginIndex] : 0;
+ StructuredArgs = new TemplateArgument[MaxStructuredArgs];
+
+ // First copy the flat entries over to the list (if any)
+ for (unsigned I = 0; I != PackBeginIndex; ++I) {
+ NumStructuredArgs++;
+ StructuredArgs[I] = FlatArgs[I];
+ }
- StructuredArgs.push_back(TemplateArgument(SourceLocation(), Args, NumArgs,
- /*CopyArgs=*/false));
+ // Next, set the pack.
+ TemplateArgument *PackArgs = 0;
+ unsigned NumPackArgs = NumFlatArgs - PackBeginIndex;
+ if (NumPackArgs)
+ PackArgs = &FlatArgs[PackBeginIndex];
- PackBeginIndex = std::numeric_limits<unsigned>::max();
-}
+ StructuredArgs[NumStructuredArgs++].setArgumentPack(PackArgs, NumPackArgs,
+ /*CopyArgs=*/false);
+}
+
+void TemplateArgumentListBuilder::ReleaseArgs() {
+ FlatArgs = 0;
+ NumFlatArgs = 0;
+ MaxFlatArgs = 0;
+ StructuredArgs = 0;
+ NumStructuredArgs = 0;
+ MaxStructuredArgs = 0;
+}
//===----------------------------------------------------------------------===//
// TemplateArgumentList Implementation
//===----------------------------------------------------------------------===//
TemplateArgumentList::TemplateArgumentList(ASTContext &Context,
TemplateArgumentListBuilder &Builder,
- bool CopyArgs, bool FlattenArgs)
- : NumArguments(Builder.flatSize()) {
- if (!CopyArgs) {
- Arguments.setPointer(Builder.getFlatArgumentList());
- Arguments.setInt(1);
- return;
- }
-
+ bool TakeArgs)
+ : FlatArguments(Builder.getFlatArguments(), TakeArgs),
+ NumFlatArguments(Builder.flatSize()),
+ StructuredArguments(Builder.getStructuredArguments(), TakeArgs),
+ NumStructuredArguments(Builder.structuredSize()) {
- unsigned Size = sizeof(TemplateArgument) * Builder.flatSize();
- unsigned Align = llvm::AlignOf<TemplateArgument>::Alignment;
- void *Mem = Context.Allocate(Size, Align);
- Arguments.setPointer((TemplateArgument *)Mem);
- Arguments.setInt(0);
-
- TemplateArgument *Args = (TemplateArgument *)Mem;
- for (unsigned I = 0; I != NumArguments; ++I)
- new (Args + I) TemplateArgument(Builder.getFlatArgumentList()[I]);
+ if (!TakeArgs)
+ return;
+
+ if (Builder.getStructuredArguments() == Builder.getFlatArguments())
+ StructuredArguments.setInt(0);
+ Builder.ReleaseArgs();
}
TemplateArgumentList::~TemplateArgumentList() {
@@ -333,7 +357,7 @@ ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK,
// class template specializations?
SpecializedTemplate->getIdentifier()),
SpecializedTemplate(SpecializedTemplate),
- TemplateArgs(Context, Builder, /*CopyArgs=*/true, /*FlattenArgs=*/true),
+ TemplateArgs(Context, Builder, /*TakeArgs=*/true),
SpecializationKind(TSK_Undeclared) {
}
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index fcb405d..6b346cd 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -63,7 +63,7 @@ public:
// FIXME: Investigate what is using this. This method should be removed.
virtual Loc getLoc(const VarDecl* VD) {
- return Loc::MakeVal(MRMgr.getVarRegion(VD));
+ return ValMgr.makeLoc(MRMgr.getVarRegion(VD));
}
const GRState *BindCompoundLiteral(const GRState *state,
@@ -126,17 +126,17 @@ StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
}
SVal BasicStoreManager::getLValueVar(const GRState *state, const VarDecl* VD) {
- return Loc::MakeVal(MRMgr.getVarRegion(VD));
+ return ValMgr.makeLoc(MRMgr.getVarRegion(VD));
}
SVal BasicStoreManager::getLValueString(const GRState *state,
const StringLiteral* S) {
- return Loc::MakeVal(MRMgr.getStringRegion(S));
+ return ValMgr.makeLoc(MRMgr.getStringRegion(S));
}
SVal BasicStoreManager::getLValueCompoundLiteral(const GRState *state,
const CompoundLiteralExpr* CL){
- return Loc::MakeVal(MRMgr.getCompoundLiteralRegion(CL));
+ return ValMgr.makeLoc(MRMgr.getCompoundLiteralRegion(CL));
}
SVal BasicStoreManager::getLValueIvar(const GRState *state, const ObjCIvarDecl* D,
@@ -151,7 +151,7 @@ SVal BasicStoreManager::getLValueIvar(const GRState *state, const ObjCIvarDecl*
const MemRegion *BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
if (BaseR == SelfRegion)
- return loc::MemRegionVal(MRMgr.getObjCIvarRegion(D, BaseR));
+ return ValMgr.makeLoc(MRMgr.getObjCIvarRegion(D, BaseR));
}
return UnknownVal();
@@ -186,7 +186,7 @@ SVal BasicStoreManager::getLValueField(const GRState *state, SVal Base,
return Base;
}
- return Loc::MakeVal(MRMgr.getFieldRegion(D, BaseR));
+ return ValMgr.makeLoc(MRMgr.getFieldRegion(D, BaseR));
}
SVal BasicStoreManager::getLValueElement(const GRState *state,
@@ -242,8 +242,8 @@ SVal BasicStoreManager::getLValueElement(const GRState *state,
}
if (BaseR)
- return Loc::MakeVal(MRMgr.getElementRegion(elementType, UnknownVal(),
- BaseR, getContext()));
+ return ValMgr.makeLoc(MRMgr.getElementRegion(elementType, UnknownVal(),
+ BaseR, getContext()));
else
return UnknownVal();
}
@@ -351,7 +351,7 @@ Store BasicStoreManager::BindInternal(Store store, Loc loc, SVal V) {
// are incompatible. This may also cause lots of breakage
// elsewhere. Food for thought.
if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) {
- if (TyR->isBoundable(C) &&
+ if (TyR->isBoundable() &&
Loc::IsLocType(TyR->getValueType(C)))
V = X->getLoc();
}
@@ -456,7 +456,7 @@ BasicStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
const MemRegion* R = I.getKey();
if (!Marked.count(R)) {
- store = Remove(store, Loc::MakeVal(R));
+ store = Remove(store, ValMgr.makeLoc(R));
SVal X = I.getData();
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
@@ -483,7 +483,7 @@ Store BasicStoreManager::scanForIvars(Stmt *B, const Decl* SelfDecl, Store St) {
const MemRegion *IVR = MRMgr.getObjCIvarRegion(IV->getDecl(),
SelfRegion);
SVal X = ValMgr.getRegionValueSymbolVal(IVR);
- St = BindInternal(St, Loc::MakeVal(IVR), X);
+ St = BindInternal(St, ValMgr.makeLoc(IVR), X);
}
}
}
@@ -515,8 +515,8 @@ Store BasicStoreManager::getInitialStore() {
SelfRegion = MRMgr.getObjCObjectRegion(MD->getClassInterface(),
MRMgr.getHeapRegion());
- St = BindInternal(St, Loc::MakeVal(MRMgr.getVarRegion(PD)),
- Loc::MakeVal(SelfRegion));
+ St = BindInternal(St, ValMgr.makeLoc(MRMgr.getVarRegion(PD)),
+ ValMgr.makeLoc(SelfRegion));
// Scan the method for ivar references. While this requires an
// entire AST scan, the cost should not be high in practice.
@@ -541,7 +541,7 @@ Store BasicStoreManager::getInitialStore() {
? ValMgr.getRegionValueSymbolVal(R)
: UndefinedVal();
- St = BindInternal(St, Loc::MakeVal(R), X);
+ St = BindInternal(St, ValMgr.makeLoc(R), X);
}
}
return St;
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index c58ceb4..1ccd092 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -2835,7 +2835,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
// Remove any existing reference-count binding.
if (Sym) state = state->remove<RefBindings>(Sym);
- if (R->isBoundable(Ctx)) {
+ if (R->isBoundable()) {
// Set the value of the variable to be a conjured symbol.
unsigned Count = Builder.getCurrentBlockCount();
QualType T = R->getValueType(Ctx);
@@ -2843,7 +2843,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())){
ValueManager &ValMgr = Eng.getValueManager();
SVal V = ValMgr.getConjuredSymbolVal(*I, T, Count);
- state = state->bindLoc(Loc::MakeVal(R), V);
+ state = state->bindLoc(ValMgr.makeLoc(R), V);
}
else if (const RecordType *RT = T->getAsStructureType()) {
// Handle structs in a not so awesome way. Here we just
@@ -2873,7 +2873,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
const FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count);
- state = state->bindLoc(Loc::MakeVal(FR), V);
+ state = state->bindLoc(ValMgr.makeLoc(FR), V);
}
}
} else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
@@ -2987,7 +2987,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
state = state->set<RefBindings>(Sym, RefVal::makeOwned(RE.getObjKind(),
RetT));
- state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
+ state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), false);
// FIXME: Add a flag to the checker where allocations are assumed to
// *not fail.
@@ -3010,7 +3010,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
QualType RetT = GetReturnType(Ex, ValMgr.getContext());
state = state->set<RefBindings>(Sym, RefVal::makeNotOwned(RE.getObjKind(),
RetT));
- state = state->bindExpr(Ex, ValMgr.makeRegionVal(Sym), false);
+ state = state->bindExpr(Ex, ValMgr.makeLoc(Sym), false);
break;
}
}
diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp
index 7ada6d8..2b751df 100644
--- a/lib/Analysis/Environment.cpp
+++ b/lib/Analysis/Environment.cpp
@@ -18,14 +18,14 @@
using namespace clang;
-SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
+SVal Environment::GetSVal(const Stmt *E, ValueManager& ValMgr) const {
for (;;) {
switch (E->getStmtClass()) {
case Stmt::AddrLabelExprClass:
- return Loc::MakeVal(cast<AddrLabelExpr>(E));
+ return ValMgr.makeLoc(cast<AddrLabelExpr>(E));
// ParenExprs are no-ops.
@@ -35,11 +35,11 @@ SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
case Stmt::CharacterLiteralClass: {
const CharacterLiteral* C = cast<CharacterLiteral>(E);
- return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
+ return ValMgr.makeIntVal(C->getValue(), C->getType());
}
case Stmt::IntegerLiteralClass: {
- return NonLoc::MakeVal(BasicVals, cast<IntegerLiteral>(E));
+ return ValMgr.makeIntVal(cast<IntegerLiteral>(E));
}
// Casts where the source and target type are the same
@@ -69,8 +69,7 @@ SVal Environment::GetSVal(const Stmt *E, BasicValueFactory& BasicVals) const {
return LookupExpr(E);
}
-SVal Environment::GetBlkExprSVal(const Stmt *E,
- BasicValueFactory& BasicVals) const {
+SVal Environment::GetBlkExprSVal(const Stmt *E, ValueManager& ValMgr) const {
while (1) {
switch (E->getStmtClass()) {
@@ -80,11 +79,11 @@ SVal Environment::GetBlkExprSVal(const Stmt *E,
case Stmt::CharacterLiteralClass: {
const CharacterLiteral* C = cast<CharacterLiteral>(E);
- return NonLoc::MakeVal(BasicVals, C->getValue(), C->getType());
+ return ValMgr.makeIntVal(C->getValue(), C->getType());
}
case Stmt::IntegerLiteralClass: {
- return NonLoc::MakeVal(BasicVals, cast<IntegerLiteral>(E));
+ return ValMgr.makeIntVal(cast<IntegerLiteral>(E));
}
default:
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 87432d4..d5f0e40 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -905,16 +905,19 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred,
// this right now, and since most logical expressions are used for branches,
// the payoff is not likely to be large. Instead, we do eager evaluation.
if (const GRState *newState = state->assume(X, true))
- MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(1U, B)));
+ MakeNode(Dst, B, Pred,
+ newState->bindBlkExpr(B, ValMgr.makeIntVal(1U, B->getType())));
if (const GRState *newState = state->assume(X, false))
- MakeNode(Dst, B, Pred, newState->bindBlkExpr(B, MakeConstantVal(0U, B)));
+ MakeNode(Dst, B, Pred,
+ newState->bindBlkExpr(B, ValMgr.makeIntVal(0U, B->getType())));
}
else {
// We took the LHS expression. Depending on whether we are '&&' or
// '||' we know what the value of the expression is via properties of
// the short-circuiting.
- X = MakeConstantVal( B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U, B);
+ X = ValMgr.makeIntVal(B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U,
+ B->getType());
MakeNode(Dst, B, Pred, state->bindBlkExpr(B, X));
}
}
@@ -944,8 +947,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* Ex, NodeTy* Pred, NodeSet& Dst,
} else if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
assert(!asLValue && "EnumConstantDecl does not have lvalue.");
- BasicValueFactory& BasicVals = StateMgr.getBasicVals();
- SVal V = nonloc::ConcreteInt(BasicVals.getValue(ED->getInitVal()));
+ SVal V = ValMgr.makeIntVal(ED->getInitVal());
MakeNode(Dst, Ex, Pred, state->bindExpr(Ex, V));
return;
@@ -1615,14 +1617,16 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) {
if (isa<nonloc::SymExprVal>(V)) {
// First assume that the condition is true.
if (const GRState *stateTrue = state->assume(V, true)) {
- stateTrue = stateTrue->bindExpr(Ex, MakeConstantVal(1U, Ex));
+ stateTrue = stateTrue->bindExpr(Ex,
+ ValMgr.makeIntVal(1U, Ex->getType()));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag),
stateTrue, Pred));
}
// Next, assume that the condition is false.
if (const GRState *stateFalse = state->assume(V, false)) {
- stateFalse = stateFalse->bindExpr(Ex, MakeConstantVal(0U, Ex));
+ stateFalse = stateFalse->bindExpr(Ex,
+ ValMgr.makeIntVal(0U, Ex->getType()));
Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag),
stateFalse, Pred));
}
@@ -1725,12 +1729,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
const GRState *state = GetState(Pred);
// Handle the case where the container still has elements.
- QualType IntTy = getContext().IntTy;
- SVal TrueV = NonLoc::MakeVal(getBasicVals(), 1, IntTy);
+ SVal TrueV = ValMgr.makeTruthVal(1);
const GRState *hasElems = state->bindExpr(S, TrueV);
// Handle the case where the container has no elements.
- SVal FalseV = NonLoc::MakeVal(getBasicVals(), 0, IntTy);
+ SVal FalseV = ValMgr.makeTruthVal(0);
const GRState *noElems = state->bindExpr(S, FalseV);
if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
@@ -1742,11 +1745,11 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
assert (Loc::IsLocType(T));
unsigned Count = Builder->getCurrentBlockCount();
SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
- SVal V = Loc::MakeVal(getStoreManager().getRegionManager().getSymbolicRegion(Sym));
+ SVal V = ValMgr.makeLoc(Sym);
hasElems = hasElems->bindLoc(ElementV, V);
// Bind the location to 'nil' on the false branch.
- SVal nilV = loc::ConcreteInt(getBasicVals().getValue(0, T));
+ SVal nilV = ValMgr.makeIntVal(0, T);
noElems = noElems->bindLoc(ElementV, nilV);
}
@@ -2290,7 +2293,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
// Handle base case where the initializer has no elements.
// e.g: static int* myArray[] = {};
if (NumInitElements == 0) {
- SVal V = NonLoc::MakeCompoundVal(T, StartVals, getBasicVals());
+ SVal V = ValMgr.makeCompoundVal(T, StartVals);
MakeNode(Dst, E, Pred, state->bindExpr(E, V));
return;
}
@@ -2323,7 +2326,7 @@ void GRExprEngine::VisitInitListExpr(InitListExpr* E, NodeTy* Pred,
if (NewItr == ItrEnd) {
// Now we have a list holding all init values. Make CompoundValData.
- SVal V = NonLoc::MakeCompoundVal(T, NewVals, getBasicVals());
+ SVal V = ValMgr.makeCompoundVal(T, NewVals);
// Make final state and node.
MakeNode(Dst, E, *NI, state->bindExpr(E, V));
@@ -2393,8 +2396,7 @@ void GRExprEngine::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr* Ex,
amt = getContext().getTypeAlign(T) / 8;
MakeNode(Dst, Ex, Pred,
- GetState(Pred)->bindExpr(Ex, NonLoc::MakeVal(getBasicVals(), amt,
- Ex->getType())));
+ GetState(Pred)->bindExpr(Ex, ValMgr.makeIntVal(amt, Ex->getType())));
}
@@ -2468,7 +2470,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
// For all other types, UnaryOperator::Float returns 0.
assert (Ex->getType()->isIntegerType());
const GRState* state = GetState(*I);
- SVal X = NonLoc::MakeVal(getBasicVals(), 0, Ex->getType());
+ SVal X = ValMgr.makeZeroVal(Ex->getType());
MakeNode(Dst, U, *I, state->bindExpr(U, X));
}
@@ -2571,7 +2573,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
// transfer functions as "0 == E".
if (isa<Loc>(V)) {
- Loc X = Loc::MakeNull(getBasicVals());
+ Loc X = ValMgr.makeNull();
SVal Result = EvalBinOp(state,BinaryOperator::EQ, cast<Loc>(V), X,
U->getType());
state = state->bindExpr(U, Result);
@@ -2629,7 +2631,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred,
BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
: BinaryOperator::Sub;
- SVal Result = EvalBinOp(state, Op, V2, MakeConstantVal(1U, U),
+ SVal Result = EvalBinOp(state, Op, V2, ValMgr.makeIntVal(1U,U->getType()),
U->getType());
// Conjure a new symbol if necessary to recover precision.
diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp
index 7f7270d..13df89e 100644
--- a/lib/Analysis/GRExprEngineInternalChecks.cpp
+++ b/lib/Analysis/GRExprEngineInternalChecks.cpp
@@ -717,7 +717,7 @@ public:
if (isa<loc::ConcreteInt>(V)) {
bool b = false;
ASTContext &C = BRC.getASTContext();
- if (R->isBoundable(C)) {
+ if (R->isBoundable()) {
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
if (C.isObjCObjectPointerType(TR->getValueType(C))) {
os << "initialized to nil";
@@ -748,7 +748,7 @@ public:
if (isa<loc::ConcreteInt>(V)) {
bool b = false;
ASTContext &C = BRC.getASTContext();
- if (R->isBoundable(C)) {
+ if (R->isBoundable()) {
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
if (C.isObjCObjectPointerType(TR->getValueType(C))) {
os << "nil object reference stored to ";
diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp
index 7e54f1a..4806121 100644
--- a/lib/Analysis/GRSimpleVals.cpp
+++ b/lib/Analysis/GRSimpleVals.cpp
@@ -84,7 +84,7 @@ SVal GRSimpleVals::EvalCast(GRExprEngine& Eng, Loc X, QualType T) {
unsigned BitWidth = Eng.getContext().getTypeSize(T);
if (!isa<loc::ConcreteInt>(X))
- return nonloc::LocAsInteger::Make(BasicVals, X, BitWidth);
+ return Eng.getValueManager().makeLocAsInteger(X, BitWidth);
llvm::APSInt V = cast<loc::ConcreteInt>(X).getValue();
V.setIsUnsigned(T->isUnsignedIntegerType() || Loc::IsLocType(T));
@@ -133,8 +133,8 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
BinaryOperator::Opcode Op,
NonLoc L, NonLoc R,
QualType T) {
-
BasicValueFactory& BasicVals = Eng.getBasicVals();
+ ValueManager& ValMgr = Eng.getValueManager();
unsigned subkind = L.getSubKind();
while (1) {
@@ -157,16 +157,15 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng,
llvm::APSInt V = cast<nonloc::ConcreteInt>(R).getValue();
V.setIsUnsigned(true);
V.extOrTrunc(Ctx.getTypeSize(Ctx.VoidPtrTy));
- return EvalBinOp(Eng, Op, LL,
- loc::ConcreteInt(BasicVals.getValue(V)));
+ return EvalBinOp(Eng, Op, LL, ValMgr.makeLoc(V));
}
default:
switch (Op) {
case BinaryOperator::EQ:
- return NonLoc::MakeIntTruthVal(BasicVals, false);
+ return ValMgr.makeTruthVal(false);
case BinaryOperator::NE:
- return NonLoc::MakeIntTruthVal(BasicVals, true);
+ return ValMgr.makeTruthVal(true);
default:
// This case also handles pointer arithmetic.
return UnknownVal();
@@ -289,7 +288,7 @@ SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, const GRState *state,
SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) {
- BasicValueFactory& BasicVals = Eng.getBasicVals();
+ ValueManager& ValMgr = Eng.getValueManager();
switch (L.getSubKind()) {
@@ -307,7 +306,7 @@ SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) {
if (!isEqual)
b = !b;
- return NonLoc::MakeIntTruthVal(BasicVals, b);
+ return ValMgr.makeTruthVal(b);
}
else if (SymbolRef Sym = R.getAsSymbol()) {
const SymIntExpr * SE =
@@ -339,10 +338,10 @@ SVal GRSimpleVals::EvalEquality(GRExprEngine& Eng, Loc L, Loc R, bool isEqual) {
// Fall-through.
case loc::GotoLabelKind:
- return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? L == R : L != R);
+ return ValMgr.makeTruthVal(isEqual ? L == R : L != R);
}
- return NonLoc::MakeIntTruthVal(BasicVals, isEqual ? false : true);
+ return ValMgr.makeTruthVal(isEqual ? false : true);
}
//===----------------------------------------------------------------------===//
@@ -367,8 +366,8 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<GRState>& Dst,
if (isa<loc::MemRegionVal>(V)) {
const MemRegion *R = cast<loc::MemRegionVal>(V).getRegion();
- if (R->isBoundable(Eng.getContext()))
- St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
+ if (R->isBoundable())
+ St = StateMgr.BindLoc(St, cast<Loc>(V), UnknownVal());
} else if (isa<nonloc::LocAsInteger>(V))
St = StateMgr.BindLoc(St, cast<nonloc::LocAsInteger>(V).getLoc(),
UnknownVal());
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 9e11a26..9bd93cd 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -18,6 +18,9 @@
using namespace clang;
+//===----------------------------------------------------------------------===//
+// Basic methods.
+//===----------------------------------------------------------------------===//
MemRegion::~MemRegion() {}
@@ -34,6 +37,19 @@ bool SubRegion::isSubRegionOf(const MemRegion* R) const {
return false;
}
+
+MemRegionManager* SubRegion::getMemRegionManager() const {
+ const SubRegion* r = this;
+ do {
+ const MemRegion *superRegion = r->getSuperRegion();
+ if (const SubRegion *sr = dyn_cast<SubRegion>(superRegion)) {
+ r = sr;
+ continue;
+ }
+ return superRegion->getMemRegionManager();
+ } while (1);
+}
+
void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ID.AddInteger((unsigned)getKind());
}
@@ -47,14 +63,15 @@ void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
}
void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const Expr* Ex, unsigned cnt) {
+ const Expr* Ex, unsigned cnt,
+ const MemRegion *) {
ID.AddInteger((unsigned) AllocaRegionKind);
ID.AddPointer(Ex);
ID.AddInteger(cnt);
}
void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- ProfileRegion(ID, Ex, Cnt);
+ ProfileRegion(ID, Ex, Cnt, superRegion);
}
void TypedViewRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
@@ -87,13 +104,15 @@ void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
}
-void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym) {
+void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
+ const MemRegion *sreg) {
ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
ID.Add(sym);
+ ID.AddPointer(sreg);
}
void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- SymbolicRegion::ProfileRegion(ID, sym);
+ SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
}
void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
@@ -110,14 +129,14 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
}
void CodeTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const void* data,
- QualType t) {
+ QualType t, const MemRegion*) {
ID.AddInteger(MemRegion::CodeTextRegionKind);
ID.AddPointer(data);
ID.Add(t);
}
void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- CodeTextRegion::ProfileRegion(ID, Data, LocationType);
+ CodeTextRegion::ProfileRegion(ID, Data, LocationType, superRegion);
}
//===----------------------------------------------------------------------===//
@@ -186,13 +205,12 @@ void VarRegion::print(llvm::raw_ostream& os) const {
// MemRegionManager methods.
//===----------------------------------------------------------------------===//
-MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
-
+MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
if (!region) {
region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
- new (region) MemSpaceRegion();
+ new (region) MemSpaceRegion(this);
}
-
+
return region;
}
@@ -216,82 +234,21 @@ MemSpaceRegion* MemRegionManager::getCodeRegion() {
return LazyAllocate(code);
}
-bool MemRegionManager::onStack(const MemRegion* R) {
- while (const SubRegion* SR = dyn_cast<SubRegion>(R))
- R = SR->getSuperRegion();
-
- return (R != 0) && (R == stack);
-}
-
-bool MemRegionManager::onHeap(const MemRegion* R) {
- while (const SubRegion* SR = dyn_cast<SubRegion>(R))
- R = SR->getSuperRegion();
-
- return (R != 0) && (R == heap);
-}
+//===----------------------------------------------------------------------===//
+// Constructing regions.
+//===----------------------------------------------------------------------===//
StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) {
- llvm::FoldingSetNodeID ID;
- MemSpaceRegion* GlobalsR = getGlobalsRegion();
-
- StringRegion::ProfileRegion(ID, Str, GlobalsR);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- StringRegion* R = cast_or_null<StringRegion>(data);
-
- if (!R) {
- R = (StringRegion*) A.Allocate<StringRegion>();
- new (R) StringRegion(Str, GlobalsR);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<StringRegion>(Str);
}
VarRegion* MemRegionManager::getVarRegion(const VarDecl* d) {
-
- const MemRegion* superRegion = d->hasLocalStorage() ? getStackRegion()
- : getGlobalsRegion();
-
- llvm::FoldingSetNodeID ID;
- DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- VarRegion* R = cast_or_null<VarRegion>(data);
-
- if (!R) {
- R = (VarRegion*) A.Allocate<VarRegion>();
- new (R) VarRegion(d, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<VarRegion>(d);
}
CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
- // Is this compound literal allocated on the stack or is part of the
- // global constant pool?
- const MemRegion* superRegion = CL->isFileScope() ?
- getGlobalsRegion() : getStackRegion();
-
- // Profile the compound literal.
- llvm::FoldingSetNodeID ID;
- CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- CompoundLiteralRegion* R = cast_or_null<CompoundLiteralRegion>(data);
-
- if (!R) {
- R = (CompoundLiteralRegion*) A.Allocate<CompoundLiteralRegion>();
- new (R) CompoundLiteralRegion(CL, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<CompoundLiteralRegion>(CL);
}
ElementRegion*
@@ -318,149 +275,45 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx,
CodeTextRegion* MemRegionManager::getCodeTextRegion(const FunctionDecl* fd,
QualType t) {
- llvm::FoldingSetNodeID ID;
- CodeTextRegion::ProfileRegion(ID, fd, t);
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);
-
- if (!R) {
- R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
- new (R) CodeTextRegion(fd, t, getCodeRegion());
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<CodeTextRegion>(fd, t);
}
CodeTextRegion* MemRegionManager::getCodeTextRegion(SymbolRef sym, QualType t) {
- llvm::FoldingSetNodeID ID;
- CodeTextRegion::ProfileRegion(ID, sym, t);
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- CodeTextRegion* R = cast_or_null<CodeTextRegion>(data);
-
- if (!R) {
- R = (CodeTextRegion*) A.Allocate<CodeTextRegion>();
- new (R) CodeTextRegion(sym, t, getCodeRegion());
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<CodeTextRegion>(sym, t);
}
/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) {
- llvm::FoldingSetNodeID ID;
- SymbolicRegion::ProfileRegion(ID, sym);
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
-
- if (!R) {
- R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
- // SymbolicRegion's storage class is usually unknown.
- new (R) SymbolicRegion(sym, getUnknownRegion());
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<SymbolicRegion>(sym);
}
FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
const MemRegion* superRegion) {
- llvm::FoldingSetNodeID ID;
- DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- FieldRegion* R = cast_or_null<FieldRegion>(data);
-
- if (!R) {
- R = (FieldRegion*) A.Allocate<FieldRegion>();
- new (R) FieldRegion(d, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<FieldRegion>(d, superRegion);
}
ObjCIvarRegion*
MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
const MemRegion* superRegion) {
- llvm::FoldingSetNodeID ID;
- DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data);
-
- if (!R) {
- R = (ObjCIvarRegion*) A.Allocate<ObjCIvarRegion>();
- new (R) ObjCIvarRegion(d, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<ObjCIvarRegion>(d, superRegion);
}
ObjCObjectRegion*
MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
- const MemRegion* superRegion) {
- llvm::FoldingSetNodeID ID;
- DeclRegion::ProfileRegion(ID, d, superRegion,
- MemRegion::ObjCObjectRegionKind);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data);
-
- if (!R) {
- R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>();
- new (R) ObjCObjectRegion(d, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ const MemRegion* superRegion) {
+ return getRegion<ObjCObjectRegion>(d, superRegion);
}
TypedViewRegion*
MemRegionManager::getTypedViewRegion(QualType t, const MemRegion* superRegion) {
- llvm::FoldingSetNodeID ID;
- TypedViewRegion::ProfileRegion(ID, t, superRegion);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- TypedViewRegion* R = cast_or_null<TypedViewRegion>(data);
-
- if (!R) {
- R = (TypedViewRegion*) A.Allocate<TypedViewRegion>();
- new (R) TypedViewRegion(t, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<TypedViewRegion>(t, superRegion);
}
AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
- llvm::FoldingSetNodeID ID;
- AllocaRegion::ProfileRegion(ID, E, cnt);
-
- void* InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- AllocaRegion* R = cast_or_null<AllocaRegion>(data);
-
- if (!R) {
- R = (AllocaRegion*) A.Allocate<AllocaRegion>();
- new (R) AllocaRegion(E, cnt, getStackRegion());
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
+ return getRegion<AllocaRegion>(E, cnt);
}
bool MemRegionManager::hasStackStorage(const MemRegion* R) {
-
// Only subregions can have stack storage.
const SubRegion* SR = dyn_cast<SubRegion>(R);
@@ -476,10 +329,29 @@ bool MemRegionManager::hasStackStorage(const MemRegion* R) {
SR = dyn_cast<SubRegion>(R);
}
-
+
return false;
}
+bool MemRegionManager::hasHeapStorage(const MemRegion* R) {
+ // Only subregions can have stack storage.
+ const SubRegion* SR = dyn_cast<SubRegion>(R);
+
+ if (!SR)
+ return false;
+
+ MemSpaceRegion* H = getHeapRegion();
+
+ while (SR) {
+ R = SR->getSuperRegion();
+ if (R == H)
+ return true;
+
+ SR = dyn_cast<SubRegion>(R);
+ }
+
+ return false;
+}
//===----------------------------------------------------------------------===//
// View handling.
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 5f2b8f8..f76807b 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -513,7 +513,7 @@ SVal RegionStoreManager::getLValueElement(const GRState *St,
if (OffI.isUnsigned()) {
llvm::APSInt Tmp = OffI;
Tmp.setIsSigned(true);
- Offset = NonLoc::MakeVal(getBasicVals(), Tmp);
+ Offset = ValMgr.makeIntVal(Tmp);
}
}
return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
@@ -547,7 +547,7 @@ SVal RegionStoreManager::getLValueElement(const GRState *St,
Tmp.setIsSigned(true);
Tmp += BaseIdxI; // Compute the new offset.
- NewIdx = NonLoc::MakeVal(getBasicVals(), Tmp);
+ NewIdx = ValMgr.makeIntVal(Tmp);
}
else
NewIdx = nonloc::ConcreteInt(getBasicVals().getValue(BaseIdxI + OffI));
@@ -572,7 +572,7 @@ SVal RegionStoreManager::getSizeInElements(const GRState *state,
if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(T)) {
// return the size as signed integer.
- return NonLoc::MakeVal(getBasicVals(), CAT->getSize(), false);
+ return ValMgr.makeIntVal(CAT->getSize(), false);
}
const QualType* CastTy = state->get<RegionCasts>(VR);
@@ -585,19 +585,19 @@ SVal RegionStoreManager::getSizeInElements(const GRState *state,
uint64_t EleSize = getContext().getTypeSize(EleTy);
uint64_t VarSize = getContext().getTypeSize(VarTy);
assert(VarSize != 0);
- return NonLoc::MakeIntVal(getBasicVals(), VarSize / EleSize, false);
+ return ValMgr.makeIntVal(VarSize/EleSize, false);
}
// Clients can use ordinary variables as if they were arrays. These
// essentially are arrays of size 1.
- return NonLoc::MakeIntVal(getBasicVals(), 1, false);
+ return ValMgr.makeIntVal(1, false);
}
if (const StringRegion* SR = dyn_cast<StringRegion>(R)) {
const StringLiteral* Str = SR->getStringLiteral();
// We intentionally made the size value signed because it participates in
// operations with signed indices.
- return NonLoc::MakeIntVal(getBasicVals(), Str->getByteLength()+1, false);
+ return ValMgr.makeIntVal(Str->getByteLength()+1, false);
}
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) {
@@ -676,7 +676,9 @@ RegionStoreManager::CastRegion(const GRState *state, const MemRegion* R,
// CodeTextRegion should be cast to only function pointer type.
if (isa<CodeTextRegion>(R)) {
- assert(CastToTy->isFunctionPointerType() || CastToTy->isBlockPointerType());
+ assert(CastToTy->isFunctionPointerType() || CastToTy->isBlockPointerType()
+ || (CastToTy->isPointerType()
+ && CastToTy->getAsPointerType()->getPointeeType()->isVoidType()));
return CastResult(state, R);
}
@@ -800,7 +802,7 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
const MemRegion* NewER =
MRMgr.getElementRegion(ER->getElementType(), NewIdx,ER->getSuperRegion(),
getContext());
- return Loc::MakeVal(NewER);
+ return ValMgr.makeLoc(NewER);
}
@@ -937,7 +939,7 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
}
}
- if (MRMgr.onStack(R) || MRMgr.onHeap(R)) {
+ if (MRMgr.hasStackStorage(R) || MRMgr.hasHeapStorage(R)) {
// All stack variables are considered to have undefined values
// upon creation. All heap allocated blocks are considered to
// have undefined values as well unless they are explicitly bound
@@ -984,7 +986,7 @@ SVal RegionStoreManager::RetrieveStruct(const GRState *state,
StructVal = getBasicVals().consVals(FieldValue, StructVal);
}
- return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals());
+ return ValMgr.makeCompoundVal(T, StructVal);
}
SVal RegionStoreManager::RetrieveArray(const GRState *state,
@@ -998,7 +1000,7 @@ SVal RegionStoreManager::RetrieveArray(const GRState *state,
llvm::APSInt i = getBasicVals().getZeroWithPtrWidth(false);
for (; i < Size; ++i) {
- SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
+ SVal Idx = ValMgr.makeIntVal(i);
ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R,
getContext());
QualType ETy = ER->getElementType();
@@ -1006,7 +1008,7 @@ SVal RegionStoreManager::RetrieveArray(const GRState *state,
ArrayVal = getBasicVals().consVals(ElementVal, ArrayVal);
}
- return NonLoc::MakeCompoundVal(T, ArrayVal, getBasicVals());
+ return ValMgr.makeCompoundVal(T, ArrayVal);
}
//===----------------------------------------------------------------------===//
@@ -1059,7 +1061,7 @@ const GRState *RegionStoreManager::BindDecl(const GRState *state,
if (T->isStructureType())
return BindStruct(state, VR, InitVal);
- return Bind(state, Loc::MakeVal(VR), InitVal);
+ return Bind(state, ValMgr.makeLoc(VR), InitVal);
}
// FIXME: this method should be merged into Bind().
@@ -1077,17 +1079,11 @@ const GRState *RegionStoreManager::BindArray(const GRState *state,
SVal Init) {
QualType T = R->getValueType(getContext());
- assert(T->isArrayType());
-
- // When we are binding the whole array, it always has default value 0.
- state = state->set<RegionDefaultValue>(R, NonLoc::MakeIntVal(getBasicVals(),
- 0, false));
-
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
+ QualType ElementTy = CAT->getElementType();
llvm::APSInt Size(CAT->getSize(), false);
- llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
- Size.isUnsigned());
+ llvm::APSInt i(llvm::APInt::getNullValue(Size.getBitWidth()), false);
// Check if the init expr is a StringLiteral.
if (isa<loc::MemRegionVal>(Init)) {
@@ -1104,12 +1100,10 @@ const GRState *RegionStoreManager::BindArray(const GRState *state,
if (j >= len)
break;
- SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
- ElementRegion* ER =
- MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
- Idx, R, getContext());
+ SVal Idx = ValMgr.makeIntVal(i);
+ ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx,R,getContext());
- SVal V = NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true);
+ SVal V = ValMgr.makeIntVal(str[j], sizeof(char)*8, true);
state = Bind(state, loc::MemRegionVal(ER), V);
}
@@ -1120,19 +1114,29 @@ const GRState *RegionStoreManager::BindArray(const GRState *state,
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
for (; i < Size; ++i, ++VI) {
- // The init list might be shorter than the array decl.
+ // The init list might be shorter than the array length.
if (VI == VE)
break;
- SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
- ElementRegion* ER =
- MRMgr.getElementRegion(cast<ArrayType>(T)->getElementType(),
- Idx, R, getContext());
+ SVal Idx = ValMgr.makeIntVal(i);
+ ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx, R, getContext());
if (CAT->getElementType()->isStructureType())
state = BindStruct(state, ER, *VI);
else
- state = Bind(state, Loc::MakeVal(ER), *VI);
+ state = Bind(state, ValMgr.makeLoc(ER), *VI);
+ }
+
+ // If the init list is shorter than the array length, bind the rest elements
+ // to 0.
+ if (ElementTy->isIntegerType()) {
+ while (i < Size) {
+ SVal Idx = ValMgr.makeIntVal(i);
+ ElementRegion* ER = MRMgr.getElementRegion(ElementTy, Idx,R,getContext());
+ SVal V = ValMgr.makeZeroVal(ElementTy);
+ state = Bind(state, ValMgr.makeLoc(ER), V);
+ ++i;
+ }
}
return state;
@@ -1161,30 +1165,37 @@ RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R,
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
-
- for (RecordDecl::field_iterator FI = RD->field_begin(getContext()),
- FE = RD->field_end(getContext());
+
+ RecordDecl::field_iterator FI, FE;
+
+ for (FI = RD->field_begin(getContext()), FE = RD->field_end(getContext());
FI != FE; ++FI, ++VI) {
- // There may be fewer values than fields only when we are initializing a
- // struct decl. In this case, mark the region as having default value.
- if (VI == VE) {
- const NonLoc& Idx = NonLoc::MakeIntVal(getBasicVals(), 0, false);
- state = state->set<RegionDefaultValue>(R, Idx);
+ if (VI == VE)
break;
- }
QualType FTy = (*FI)->getType();
FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
if (Loc::IsLocType(FTy) || FTy->isIntegerType())
- state = Bind(state, Loc::MakeVal(FR), *VI);
+ state = Bind(state, ValMgr.makeLoc(FR), *VI);
else if (FTy->isArrayType())
state = BindArray(state, FR, *VI);
else if (FTy->isStructureType())
state = BindStruct(state, FR, *VI);
}
+ // There may be fewer values in the initialize list than the fields of struct.
+ while (FI != FE) {
+ QualType FTy = (*FI)->getType();
+ if (FTy->isIntegerType()) {
+ FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
+ state = Bind(state, ValMgr.makeLoc(FR), ValMgr.makeZeroVal(FTy));
+ }
+
+ ++FI;
+ }
+
return state;
}
@@ -1202,7 +1213,7 @@ const GRState *RegionStoreManager::KillStruct(const GRState *state,
const MemRegion* R = I.getKey();
if (const SubRegion* subRegion = dyn_cast<SubRegion>(R))
if (subRegion->isSubRegionOf(R))
- store = Remove(store, Loc::MakeVal(subRegion));
+ store = Remove(store, ValMgr.makeLoc(subRegion));
// FIXME: Maybe we should also remove the bindings for the "views" of the
// subregions.
}
@@ -1398,7 +1409,7 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc,
continue;
// Remove this dead region from the store.
- store = Remove(store, Loc::MakeVal(R));
+ store = Remove(store, ValMgr.makeLoc(R));
// Mark all non-live symbols that this region references as dead.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp
index 77c3c8f..dd9490b 100644
--- a/lib/Analysis/SVals.cpp
+++ b/lib/Analysis/SVals.cpp
@@ -237,180 +237,6 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
}
//===----------------------------------------------------------------------===//
-// Utility methods for constructing SVals.
-//===----------------------------------------------------------------------===//
-
-SVal ValueManager::makeZeroVal(QualType T) {
- if (Loc::IsLocType(T))
- return Loc::MakeNull(BasicVals);
-
- if (T->isIntegerType())
- return NonLoc::MakeVal(BasicVals, 0, T);
-
- // FIXME: Handle floats.
- // FIXME: Handle structs.
- return UnknownVal();
-}
-
-SVal ValueManager::makeZeroArrayIndex() {
- return nonloc::ConcreteInt(BasicVals.getZeroWithPtrWidth(false));
-}
-
-//===----------------------------------------------------------------------===//
-// Utility methods for constructing Non-Locs.
-//===----------------------------------------------------------------------===//
-
-NonLoc ValueManager::makeNonLoc(SymbolRef sym) {
- return nonloc::SymbolVal(sym);
-}
-
-NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
- const APSInt& v, QualType T) {
- // The Environment ensures we always get a persistent APSInt in
- // BasicValueFactory, so we don't need to get the APSInt from
- // BasicValueFactory again.
- assert(!Loc::IsLocType(T));
- return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
-}
-
-NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
- const SymExpr *rhs, QualType T) {
- assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
- assert(!Loc::IsLocType(T));
- return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
-}
-
-NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
- bool isUnsigned) {
- return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned));
-}
-
-NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X,
- unsigned BitWidth, bool isUnsigned) {
- return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned));
-}
-
-NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T) {
- return nonloc::ConcreteInt(BasicVals.getValue(X, T));
-}
-
-NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral* I) {
-
- return nonloc::ConcreteInt(BasicVals.getValue(APSInt(I->getValue(),
- I->getType()->isUnsignedIntegerType())));
-}
-
-NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I,
- bool isUnsigned) {
- return nonloc::ConcreteInt(BasicVals.getValue(I, isUnsigned));
-}
-
-NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const llvm::APSInt& I) {
- return nonloc::ConcreteInt(BasicVals.getValue(I));
-}
-
-NonLoc NonLoc::MakeIntTruthVal(BasicValueFactory& BasicVals, bool b) {
- return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
-}
-
-NonLoc ValueManager::makeTruthVal(bool b, QualType T) {
- return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T));
-}
-
-NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
- BasicValueFactory& BasicVals) {
- return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
-}
-
-SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
- SymbolRef sym = SymMgr.getRegionValueSymbol(R, T);
-
- if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
- if (T.isNull())
- T = TR->getValueType(SymMgr.getContext());
-
- // If T is of function pointer type, create a CodeTextRegion wrapping a
- // symbol.
- if (T->isFunctionPointerType()) {
- return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
- }
-
- if (Loc::IsLocType(T))
- return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
-
- // Only handle integers for now.
- if (T->isIntegerType() && T->isScalarType())
- return makeNonLoc(sym);
- }
-
- return UnknownVal();
-}
-
-SVal ValueManager::getConjuredSymbolVal(const Expr* E, unsigned Count) {
- QualType T = E->getType();
- SymbolRef sym = SymMgr.getConjuredSymbol(E, Count);
-
- // If T is of function pointer type, create a CodeTextRegion wrapping a
- // symbol.
- if (T->isFunctionPointerType()) {
- return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
- }
-
- if (Loc::IsLocType(T))
- return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
-
- if (T->isIntegerType() && T->isScalarType())
- return makeNonLoc(sym);
-
- return UnknownVal();
-}
-
-SVal ValueManager::getConjuredSymbolVal(const Expr* E, QualType T,
- unsigned Count) {
-
- SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count);
-
- // If T is of function pointer type, create a CodeTextRegion wrapping a
- // symbol.
- if (T->isFunctionPointerType()) {
- return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
- }
-
- if (Loc::IsLocType(T))
- return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
-
- if (T->isIntegerType() && T->isScalarType())
- return makeNonLoc(sym);
-
- return UnknownVal();
-}
-
-SVal ValueManager::getFunctionPointer(const FunctionDecl* FD) {
- CodeTextRegion* R
- = MemMgr.getCodeTextRegion(FD, Context.getPointerType(FD->getType()));
- return loc::MemRegionVal(R);
-}
-
-nonloc::LocAsInteger nonloc::LocAsInteger::Make(BasicValueFactory& Vals, Loc V,
- unsigned Bits) {
- return LocAsInteger(Vals.getPersistentSValWithData(V, Bits));
-}
-
-//===----------------------------------------------------------------------===//
-// Utility methods for constructing Locs.
-//===----------------------------------------------------------------------===//
-
-Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); }
-
-Loc Loc::MakeVal(const AddrLabelExpr *E) {
- return loc::GotoLabel(E->getLabel());
-}
-
-Loc Loc::MakeNull(BasicValueFactory &BasicVals) {
- return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
-}
-
-//===----------------------------------------------------------------------===//
// Pretty-Printing.
//===----------------------------------------------------------------------===//
diff --git a/lib/Analysis/ValueManager.cpp b/lib/Analysis/ValueManager.cpp
new file mode 100644
index 0000000..724a2e9
--- /dev/null
+++ b/lib/Analysis/ValueManager.cpp
@@ -0,0 +1,125 @@
+//== ValueManager.cpp - Aggregate manager of symbols and SVals --*- C++ -*--==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines ValueManager, a class that manages symbolic values
+// and SVals created for use by GRExprEngine and related classes. It
+// wraps and owns SymbolManager, MemRegionManager, and BasicValueFactory.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/ValueManager.h"
+
+using namespace clang;
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Utility methods for constructing SVals.
+//===----------------------------------------------------------------------===//
+
+SVal ValueManager::makeZeroVal(QualType T) {
+ if (Loc::IsLocType(T))
+ return makeNull();
+
+ if (T->isIntegerType())
+ return makeIntVal(0, T);
+
+ // FIXME: Handle floats.
+ // FIXME: Handle structs.
+ return UnknownVal();
+}
+
+//===----------------------------------------------------------------------===//
+// Utility methods for constructing Non-Locs.
+//===----------------------------------------------------------------------===//
+
+NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const APSInt& v, QualType T) {
+ // The Environment ensures we always get a persistent APSInt in
+ // BasicValueFactory, so we don't need to get the APSInt from
+ // BasicValueFactory again.
+ assert(!Loc::IsLocType(T));
+ return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
+}
+
+NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
+ const SymExpr *rhs, QualType T) {
+ assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
+ assert(!Loc::IsLocType(T));
+ return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
+}
+
+
+SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
+ SymbolRef sym = SymMgr.getRegionValueSymbol(R, T);
+
+ if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
+ if (T.isNull())
+ T = TR->getValueType(SymMgr.getContext());
+
+ // If T is of function pointer type, create a CodeTextRegion wrapping a
+ // symbol.
+ if (T->isFunctionPointerType()) {
+ return loc::MemRegionVal(MemMgr.getCodeTextRegion(sym, T));
+ }
+
+ if (Loc::IsLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ // Only handle integers for now.
+ if (T->isIntegerType() && T->isScalarType())
+ return nonloc::SymbolVal(sym);
+ }
+
+ return UnknownVal();
+}
+
+SVal ValueManager::getConjuredSymbolVal(const Expr* E, unsigned Count) {
+ QualType T = E->getType();
+ SymbolRef sym = SymMgr.getConjuredSymbol(E, Count);
+
+ // If T is of function pointer type, create a CodeTextRegion wrapping a
+ // symbol.
+ if (T->isFunctionPointerType()) {
+ return loc::MemRegionVal(MemMgr.getCodeTextRegion(sym, T));
+ }
+
+ if (Loc::IsLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ if (T->isIntegerType() && T->isScalarType())
+ return nonloc::SymbolVal(sym);
+
+ return UnknownVal();
+}
+
+SVal ValueManager::getConjuredSymbolVal(const Expr* E, QualType T,
+ unsigned Count) {
+
+ SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count);
+
+ // If T is of function pointer type, create a CodeTextRegion wrapping a
+ // symbol.
+ if (T->isFunctionPointerType()) {
+ return loc::MemRegionVal(MemMgr.getCodeTextRegion(sym, T));
+ }
+
+ if (Loc::IsLocType(T))
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym));
+
+ if (T->isIntegerType() && T->isScalarType())
+ return nonloc::SymbolVal(sym);
+
+ return UnknownVal();
+}
+
+SVal ValueManager::getFunctionPointer(const FunctionDecl* FD) {
+ CodeTextRegion* R
+ = MemMgr.getCodeTextRegion(FD, Context.getPointerType(FD->getType()));
+ return loc::MemRegionVal(R);
+}
diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp
index 8dfc5d1..23a01c9 100644
--- a/lib/Basic/SourceManager.cpp
+++ b/lib/Basic/SourceManager.cpp
@@ -373,7 +373,10 @@ FileID SourceManager::createFileID(const ContentCache *File,
// Set LastFileIDLookup to the newly created file. The next getFileID call is
// almost guaranteed to be from that file.
- return LastFileIDLookup = FileID::get(SLocEntryTable.size()-1);
+ FileID FID = FileID::get(SLocEntryTable.size()-1);
+ if (File->FirstFID.isInvalid())
+ File->FirstFID = FID;
+ return LastFileIDLookup = FID;
}
/// createInstantiationLoc - Return a new SourceLocation that encodes the fact
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 13758ad..1d69e4e 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -169,6 +169,7 @@ static bool getDarwinNumber(const char *Triple, unsigned &Maj, unsigned &Min, un
}
static void getDarwinDefines(std::vector<char> &Defs, const LangOptions &Opts) {
+ Define(Defs, "__APPLE_CC__", "5621");
Define(Defs, "__APPLE__");
Define(Defs, "__MACH__");
Define(Defs, "OBJC_NEW_PROPERTIES");
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index ec6058a..30c5d28 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -763,7 +763,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
if (CE->getOpcode() == llvm::Instruction::BitCast &&
ActualFT->getReturnType() == CurFT->getReturnType() &&
- ActualFT->getNumParams() == CurFT->getNumParams()) {
+ ActualFT->getNumParams() == CurFT->getNumParams() &&
+ ActualFT->getNumParams() == Args.size()) {
bool ArgsMatch = true;
for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i)
if (ActualFT->getParamType(i) != CurFT->getParamType(i)) {
diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp
index 41908ad..730414e 100644
--- a/lib/Frontend/InitPreprocessor.cpp
+++ b/lib/Frontend/InitPreprocessor.cpp
@@ -232,7 +232,6 @@ static void InitializePredefinedMacros(const TargetInfo &TI,
DefineBuiltinMacro(Buf, "__clang__=1"); // Clang Frontend
// Currently claim to be compatible with GCC 4.2.1-5621.
- DefineBuiltinMacro(Buf, "__APPLE_CC__=5621");
DefineBuiltinMacro(Buf, "__GNUC_MINOR__=2");
DefineBuiltinMacro(Buf, "__GNUC_PATCHLEVEL__=1");
DefineBuiltinMacro(Buf, "__GNUC__=4");
diff --git a/lib/Frontend/Warnings.cpp b/lib/Frontend/Warnings.cpp
index 81f75bd..c8fd5f6 100644
--- a/lib/Frontend/Warnings.cpp
+++ b/lib/Frontend/Warnings.cpp
@@ -24,6 +24,7 @@
#include "clang/Basic/Diagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
#include <cstdio>
#include <cstring>
#include <utility>
@@ -99,7 +100,8 @@ bool clang::ProcessWarningOptions(Diagnostic &Diags,
}
if (Diags.setDiagnosticGroupMapping(OptStart, Mapping))
- fprintf(stderr, "warning: unknown warning option: -W%s\n", Opt.c_str());
+ Diags.Report(FullSourceLoc(), diag::warn_unknown_warning_option)
+ << ("-W" + Opt);
}
return false;
diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp
index c2ffd6d..81ea606 100644
--- a/lib/Lex/Lexer.cpp
+++ b/lib/Lex/Lexer.cpp
@@ -473,13 +473,14 @@ Slash:
// Common case, backslash-char where the char is not whitespace.
if (!isWhitespace(Ptr[0])) return '\\';
- // See if we have optional whitespace characters followed by a newline.
+ // See if we have optional whitespace characters between the slash and
+ // newline.
if (unsigned EscapedNewLineSize = getEscapedNewLineSize(Ptr)) {
// Remember that this token needs to be cleaned.
if (Tok) Tok->setFlag(Token::NeedsCleaning);
// Warn if there was whitespace between the backslash and newline.
- if (EscapedNewLineSize != 1 && Tok && !isLexingRawMode())
+ if (Ptr[0] != '\n' && Ptr[0] != '\r' && Tok && !isLexingRawMode())
Diag(Ptr, diag::backslash_newline_space);
// Found backslash<whitespace><newline>. Parse the char after it.
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 6915252..426f56f 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -273,7 +273,7 @@ AttributeList* Parser::ParseMicrosoftTypeAttributes(AttributeList *CurrAttr) {
/// [C++] template-declaration
/// [C++] namespace-definition
/// [C++] using-directive
-/// [C++] using-declaration [TODO]
+/// [C++] using-declaration
/// [C++0x] static_assert-declaration
/// others... [FIXME]
///
diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp
index 4a07d05..13b32ac 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -279,7 +279,8 @@ Parser::OwningExprResult Parser::ParseConstantExpression() {
// C++ [basic.def.odr]p2:
// An expression is potentially evaluated unless it appears where an
// integral constant expression is required (see 5.19) [...].
- EnterUnevaluatedOperand Unevaluated(Actions);
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Action::Unevaluated);
OwningExprResult LHS(ParseCastExpression(false));
if (LHS.isInvalid()) return move(LHS);
@@ -983,7 +984,8 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
//
// The GNU typeof and alignof extensions also behave as unevaluated
// operands.
- EnterUnevaluatedOperand Unevaluated(Actions);
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Action::Unevaluated);
Operand = ParseCastExpression(true/*isUnaryExpression*/);
} else {
// If it starts with a '(', we know that it is either a parenthesized
@@ -999,7 +1001,8 @@ Parser::ParseExprAfterTypeofSizeofAlignof(const Token &OpTok,
//
// The GNU typeof and alignof extensions also behave as unevaluated
// operands.
- EnterUnevaluatedOperand Unevaluated(Actions);
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Action::Unevaluated);
Operand = ParseParenExpression(ExprType, true/*stopIfCastExpr*/,
CastTy, RParenLoc);
CastRange = SourceRange(LParenLoc, RParenLoc);
diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp
index 87aa5dc..2be44a4 100644
--- a/lib/Parse/ParseExprCXX.cpp
+++ b/lib/Parse/ParseExprCXX.cpp
@@ -384,10 +384,9 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
//
// Note that we can't tell whether the expression is an lvalue of a
// polymorphic class type until after we've parsed the expression, so
- // we treat the expression as an unevaluated operand and let semantic
- // analysis cope with case where the expression is not an unevaluated
- // operand.
- EnterUnevaluatedOperand Unevaluated(Actions);
+ // we the expression is potentially potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(Actions,
+ Action::PotentiallyPotentiallyEvaluated);
Result = ParseExpression();
// Match the ')'.
diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp
index a9f75d8..eabe10f 100644
--- a/lib/Parse/ParseTemplate.cpp
+++ b/lib/Parse/ParseTemplate.cpp
@@ -750,7 +750,7 @@ void Parser::AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS) {
/// ParseTemplateArgument - Parse a C++ template argument (C++ [temp.names]).
///
/// template-argument: [C++ 14.2]
-/// assignment-expression
+/// constant-expression
/// type-id
/// id-expression
void *Parser::ParseTemplateArgument(bool &ArgIsType) {
@@ -768,7 +768,7 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) {
return TypeArg.get();
}
- OwningExprResult ExprArg = ParseAssignmentExpression();
+ OwningExprResult ExprArg = ParseConstantExpression();
if (ExprArg.isInvalid() || !ExprArg.get())
return 0;
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index e756b41..c37f66d 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -182,7 +182,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer,
Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()),
ExternalSource(0), CurContext(0), PreDeclaratorDC(0),
CurBlock(0), PackContext(0), IdResolver(pp.getLangOptions()),
- GlobalNewDeleteDeclared(false), InUnevaluatedOperand(false),
+ GlobalNewDeleteDeclared(false), ExprEvalContext(PotentiallyEvaluated),
CompleteTranslationUnit(CompleteTranslationUnit),
NumSFINAEErrors(0), CurrentInstantiationScope(0) {
@@ -235,6 +235,18 @@ void Sema::DeleteStmt(StmtTy *S) {
/// translation unit when EOF is reached and all but the top-level scope is
/// popped.
void Sema::ActOnEndOfTranslationUnit() {
+ // C++: Perform implicit template instantiations.
+ //
+ // FIXME: When we perform these implicit instantiations, we do not carefully
+ // keep track of the point of instantiation (C++ [temp.point]). This means
+ // that name lookup that occurs within the template instantiation will
+ // always happen at the end of the translation unit, so it will find
+ // some names that should not be found. Although this is common behavior
+ // for C++ compilers, it is technically wrong. In the future, we either need
+ // to be able to filter the results of name lookup or we need to perform
+ // template instantiations earlier.
+ PerformPendingImplicitInstantiations();
+
if (!CompleteTranslationUnit)
return;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 560f952..8604fe5 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -29,7 +29,9 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/OwningPtr.h"
+#include <list>
#include <string>
+#include <queue>
#include <vector>
namespace llvm {
@@ -247,11 +249,18 @@ public:
/// have been declared.
bool GlobalNewDeleteDeclared;
- /// A flag that indicates when we are processing an unevaluated operand
- /// (C++0x [expr]). C99 has the same notion of declarations being
- /// "used" and C++03 has the notion of "potentially evaluated", but we
- /// adopt the C++0x terminology since it is most precise.
- bool InUnevaluatedOperand;
+ /// The current expression evaluation context.
+ ExpressionEvaluationContext ExprEvalContext;
+
+ typedef std::vector<std::pair<SourceLocation, Decl *> >
+ PotentiallyReferencedDecls;
+
+ /// A stack of declarations, each element of which is a set of declarations
+ /// that will be marked as referenced if the corresponding potentially
+ /// potentially evaluated expression is potentially evaluated. Each element
+ /// in the stack corresponds to a PotentiallyPotentiallyEvaluated expression
+ /// evaluation context.
+ std::list<PotentiallyReferencedDecls> PotentiallyReferencedDeclStack;
/// \brief Whether the code handled by Sema should be considered a
/// complete translation unit or not.
@@ -1334,12 +1343,13 @@ public:
void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc,
Expr **Args, unsigned NumArgs);
- virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) {
- bool Result = InUnevaluatedOperand;
- InUnevaluatedOperand = UnevaluatedOperand;
- return Result;
- }
-
+ virtual ExpressionEvaluationContext
+ PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext);
+
+ virtual void
+ PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
+ ExpressionEvaluationContext NewContext);
+
void MarkDeclarationReferenced(SourceLocation Loc, Decl *D);
// Primary Expressions.
@@ -1572,10 +1582,16 @@ public:
QualType DeclInitType,
Expr **Exprs, unsigned NumExprs);
- /// DefineImplicitDefaultConstructor - Checks for feasibilityt of
+ /// DefineImplicitDefaultConstructor - Checks for feasibility of
/// defining this constructor as the default constructor.
void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor);
+
+ /// DefineImplicitCopyConstructor - Checks for feasibility of
+ /// defining this constructor as the copy constructor.
+ void DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *Constructor,
+ unsigned TypeQuals);
/// MaybeBindToTemporary - If the passed in expression has a record type with
/// a non-trivial destructor, this will return CXXBindTemporaryExpr. Otherwise
@@ -2495,6 +2511,22 @@ public:
/// variables.
LocalInstantiationScope *CurrentInstantiationScope;
+ /// \brief An entity for which implicit template instantiation is required.
+ ///
+ /// The source location associated with the declaration is the first place in
+ /// the source code where the declaration was "used". It is not necessarily
+ /// the point of instantiation (which will be either before or after the
+ /// namespace-scope declaration that triggered this implicit instantiation),
+ /// However, it is the location that diagnostics should generally refer to,
+ /// because users will need to know what code triggered the instantiation.
+ typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation;
+
+ /// \brief The queue of implicit template instantiations that are required
+ /// but have not yet been performed.
+ std::queue<PendingImplicitInstantiation> PendingImplicitInstantiations;
+
+ void PerformPendingImplicitInstantiations();
+
QualType InstantiateType(QualType T, const TemplateArgumentList &TemplateArgs,
SourceLocation Loc, DeclarationName Entity);
@@ -2550,7 +2582,7 @@ public:
void InstantiateVariableDefinition(VarDecl *Var);
NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D);
-
+
// Simple function for cloning expressions.
template<typename T>
OwningExprResult Clone(T *E) {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 06fd1a1..eba1d58 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2733,12 +2733,9 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) {
IK_Default);
if (!Constructor)
Var->setInvalidDecl();
- else {
+ else
if (!RD->hasTrivialConstructor())
InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0);
- // Check for valid construction.
- DefineImplicitDefaultConstructor(Var->getLocation(), Constructor);
- }
}
}
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 6d740eb..c9c6626 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -107,6 +107,9 @@ namespace {
void
Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
ExprArg defarg) {
+ if (!param || !defarg.get())
+ return;
+
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
UnparsedDefaultArgLocs.erase(Param);
@@ -161,6 +164,9 @@ Sema::ActOnParamDefaultArgument(DeclPtrTy param, SourceLocation EqualLoc,
void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
SourceLocation EqualLoc,
SourceLocation ArgLoc) {
+ if (!param)
+ return;
+
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
if (Param)
Param->setUnparsedDefaultArg();
@@ -171,6 +177,9 @@ void Sema::ActOnParamUnparsedDefaultArgument(DeclPtrTy param,
/// ActOnParamDefaultArgumentError - Parsing or semantic analysis of
/// the default argument for the parameter param failed.
void Sema::ActOnParamDefaultArgumentError(DeclPtrTy param) {
+ if (!param)
+ return;
+
ParmVarDecl *Param = cast<ParmVarDecl>(param.getAs<Decl>());
Param->setInvalidDecl();
@@ -415,6 +424,9 @@ Sema::BaseResult
Sema::ActOnBaseSpecifier(DeclPtrTy classdecl, SourceRange SpecifierRange,
bool Virtual, AccessSpecifier Access,
TypeTy *basetype, SourceLocation BaseLoc) {
+ if (!classdecl)
+ return true;
+
AdjustDeclIfTemplate(classdecl);
CXXRecordDecl *Class = cast<CXXRecordDecl>(classdecl.getAs<Decl>());
QualType BaseType = QualType::getFromOpaquePtr(basetype);
@@ -640,6 +652,9 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
ExprTy **Args, unsigned NumArgs,
SourceLocation *CommaLocs,
SourceLocation RParenLoc) {
+ if (!ConstructorD)
+ return true;
+
CXXConstructorDecl *Constructor
= dyn_cast<CXXConstructorDecl>(ConstructorD.getAs<Decl>());
if (!Constructor) {
@@ -741,8 +756,11 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD,
void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
SourceLocation ColonLoc,
MemInitTy **MemInits, unsigned NumMemInits) {
- CXXConstructorDecl *Constructor =
- dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
+ if (!ConstructorDecl)
+ return;
+
+ CXXConstructorDecl *Constructor
+ = dyn_cast<CXXConstructorDecl>(ConstructorDecl.getAs<Decl>());
if (!Constructor) {
Diag(ColonLoc, diag::err_only_constructors_take_base_inits);
@@ -957,6 +975,9 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,
DeclPtrTy TagDecl,
SourceLocation LBrac,
SourceLocation RBrac) {
+ if (!TagDecl)
+ return;
+
AdjustDeclIfTemplate(TagDecl);
ActOnFields(S, RLoc, TagDecl,
(DeclPtrTy*)FieldCollector->getCurFields(),
@@ -1238,6 +1259,9 @@ void Sema::ActOnReenterTemplateScope(Scope *S, DeclPtrTy TemplateD) {
/// name. However, it should not bring the parameters into scope;
/// that will be performed by ActOnDelayedCXXMethodParameter.
void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
+ if (!MethodD)
+ return;
+
CXXScopeSpec SS;
FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
QualType ClassTy
@@ -1253,6 +1277,9 @@ void Sema::ActOnStartDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
/// the method declaration. For example, we could see an
/// ActOnParamDefaultArgument event for this parameter.
void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
+ if (!ParamD)
+ return;
+
ParmVarDecl *Param = cast<ParmVarDecl>(ParamD.getAs<Decl>());
// If this parameter has an unparsed default argument, clear it out
@@ -1272,6 +1299,9 @@ void Sema::ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy ParamD) {
/// immediately!) for this method, if it was also defined inside the
/// class body.
void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, DeclPtrTy MethodD) {
+ if (!MethodD)
+ return;
+
FunctionDecl *Method = cast<FunctionDecl>(MethodD.getAs<Decl>());
CXXScopeSpec SS;
QualType ClassTy
@@ -1842,13 +1872,13 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S,
void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
CXXConstructorDecl *Constructor) {
- if (!Constructor->isDefaultConstructor() ||
- !Constructor->isImplicit() || Constructor->isImplicitMustBeDefined())
- return;
+ assert((Constructor->isImplicit() && Constructor->isDefaultConstructor() &&
+ !Constructor->isUsed()) &&
+ "DefineImplicitDefaultConstructor - call it for implicit default ctor");
CXXRecordDecl *ClassDecl
= cast<CXXRecordDecl>(Constructor->getDeclContext());
- assert(ClassDecl && "InitializeVarWithConstructor - invalid constructor");
+ assert(ClassDecl && "DefineImplicitDefaultConstructor - invalid constructor");
// Before the implicitly-declared default constructor for a class is
// implicitly defined, all the implicitly-declared default constructors
// for its base class and its non-static data members shall have been
@@ -1861,8 +1891,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
if (!BaseClassDecl->hasTrivialConstructor()) {
if (CXXConstructorDecl *BaseCtor =
BaseClassDecl->getDefaultConstructor(Context)) {
- if (BaseCtor->isImplicit())
- BaseCtor->setImplicitMustBeDefined();
+ if (BaseCtor->isImplicit() && !BaseCtor->isUsed())
+ MarkDeclarationReferenced(CurrentLocation, BaseCtor);
}
else {
Diag(CurrentLocation, diag::err_defining_default_ctor)
@@ -1886,8 +1916,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
if (!FieldClassDecl->hasTrivialConstructor())
if (CXXConstructorDecl *FieldCtor =
FieldClassDecl->getDefaultConstructor(Context)) {
- if (FieldCtor->isImplicit())
- FieldCtor->setImplicitMustBeDefined();
+ if (FieldCtor->isImplicit() && !FieldCtor->isUsed())
+ MarkDeclarationReferenced(CurrentLocation, FieldCtor);
}
else {
Diag(CurrentLocation, diag::err_defining_default_ctor)
@@ -1912,7 +1942,49 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation,
}
}
if (!err)
- Constructor->setImplicitMustBeDefined();
+ Constructor->setUsed();
+}
+
+void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation,
+ CXXConstructorDecl *CopyConstructor,
+ unsigned TypeQuals) {
+ assert((CopyConstructor->isImplicit() &&
+ CopyConstructor->isCopyConstructor(Context, TypeQuals) &&
+ !CopyConstructor->isUsed()) &&
+ "DefineImplicitCopyConstructor - call it for implicit copy ctor");
+
+ CXXRecordDecl *ClassDecl
+ = cast<CXXRecordDecl>(CopyConstructor->getDeclContext());
+ assert(ClassDecl && "DefineImplicitCopyConstructor - invalid constructor");
+ // Before the implicitly-declared copy constructor for a class is
+ // implicitly defined, all the implicitly-declared copy constructors
+ // for its base class and its non-static data members shall have been
+ // implicitly defined.
+ for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin();
+ Base != ClassDecl->bases_end(); ++Base) {
+ CXXRecordDecl *BaseClassDecl
+ = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl());
+ if (CXXConstructorDecl *BaseCopyCtor =
+ BaseClassDecl->getCopyConstructor(Context, TypeQuals))
+ if (BaseCopyCtor->isImplicit() && !BaseCopyCtor->isUsed())
+ MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor);
+ }
+ for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context);
+ Field != ClassDecl->field_end(Context);
+ ++Field) {
+ QualType FieldType = Context.getCanonicalType((*Field)->getType());
+ if (const ArrayType *Array = Context.getAsArrayType(FieldType))
+ FieldType = Array->getElementType();
+ if (const RecordType *FieldClassType = FieldType->getAsRecordType()) {
+ CXXRecordDecl *FieldClassDecl
+ = cast<CXXRecordDecl>(FieldClassType->getDecl());
+ if (CXXConstructorDecl *FieldCopyCtor =
+ FieldClassDecl->getCopyConstructor(Context, TypeQuals))
+ if (FieldCopyCtor->isImplicit() && !FieldCopyCtor->isUsed())
+ MarkDeclarationReferenced(CurrentLocation, FieldCopyCtor);
+ }
+ }
+ CopyConstructor->setUsed();
}
void Sema::InitializeVarWithConstructor(VarDecl *VD,
@@ -1921,6 +1993,7 @@ void Sema::InitializeVarWithConstructor(VarDecl *VD,
Expr **Exprs, unsigned NumExprs) {
Expr *Temp = CXXConstructExpr::Create(Context, DeclInitType, Constructor,
false, Exprs, NumExprs);
+ MarkDeclarationReferenced(VD->getLocation(), Constructor);
VD->setInit(Context, Temp);
}
@@ -1990,9 +2063,6 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl,
VDecl->setCXXDirectInitializer(true);
InitializeVarWithConstructor(VDecl, Constructor, DeclInitType,
(Expr**)Exprs.release(), NumExprs);
- // An implicitly-declared default constructor for a class is implicitly
- // defined when it is used to creat an object of its class type.
- DefineImplicitDefaultConstructor(VDecl->getLocation(), Constructor);
}
return;
}
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 692502b..56d3bfe 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2134,25 +2134,32 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
MemberType = MemberType.getQualifiedType(combinedQualifiers);
}
+ MarkDeclarationReferenced(MemberLoc, FD);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, FD,
MemberLoc, MemberType));
}
- if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl))
+ if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
Var, MemberLoc,
Var->getType().getNonReferenceType()));
- if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl))
+ }
+ if (FunctionDecl *MemberFn = dyn_cast<FunctionDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
MemberFn, MemberLoc,
MemberFn->getType()));
+ }
if (OverloadedFunctionDecl *Ovl
= dyn_cast<OverloadedFunctionDecl>(MemberDecl))
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow, Ovl,
MemberLoc, Context.OverloadTy));
- if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl))
+ if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) {
+ MarkDeclarationReferenced(MemberLoc, MemberDecl);
return Owned(new (Context) MemberExpr(BaseExpr, OpKind == tok::arrow,
Enum, MemberLoc, Enum->getType()));
+ }
if (isa<TypeDecl>(MemberDecl))
return ExprError(Diag(MemberLoc,diag::err_typecheck_member_reference_type)
<< DeclarationName(&Member) << int(OpKind == tok::arrow));
@@ -5432,6 +5439,35 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
return false;
}
+Sema::ExpressionEvaluationContext
+Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
+ // Introduce a new set of potentially referenced declarations to the stack.
+ if (NewContext == PotentiallyPotentiallyEvaluated)
+ PotentiallyReferencedDeclStack.push_back(PotentiallyReferencedDecls());
+
+ std::swap(ExprEvalContext, NewContext);
+ return NewContext;
+}
+
+void
+Sema::PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
+ ExpressionEvaluationContext NewContext) {
+ ExprEvalContext = NewContext;
+
+ if (OldContext == PotentiallyPotentiallyEvaluated) {
+ // Mark any remaining declarations in the current position of the stack
+ // as "referenced". If they were not meant to be referenced, semantic
+ // analysis would have eliminated them (e.g., in ActOnCXXTypeId).
+ PotentiallyReferencedDecls RemainingDecls;
+ RemainingDecls.swap(PotentiallyReferencedDeclStack.back());
+ PotentiallyReferencedDeclStack.pop_back();
+
+ for (PotentiallyReferencedDecls::iterator I = RemainingDecls.begin(),
+ IEnd = RemainingDecls.end();
+ I != IEnd; ++I)
+ MarkDeclarationReferenced(I->first, I->second);
+ }
+}
/// \brief Note that the given declaration was referenced in the source code.
///
@@ -5446,6 +5482,9 @@ bool Sema::VerifyIntegerConstantExpression(const Expr *E, llvm::APSInt *Result){
void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
assert(D && "No declaration?");
+ if (D->isUsed())
+ return;
+
// Mark a parameter declaration "used", regardless of whether we're in a
// template or not.
if (isa<ParmVarDecl>(D))
@@ -5456,18 +5495,55 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) {
if (CurContext->isDependentContext())
return;
- // If we are in an unevaluated operand, don't mark any definitions as used.
- if (InUnevaluatedOperand)
- return;
-
+ switch (ExprEvalContext) {
+ case Unevaluated:
+ // We are in an expression that is not potentially evaluated; do nothing.
+ return;
+
+ case PotentiallyEvaluated:
+ // We are in a potentially-evaluated expression, so this declaration is
+ // "used"; handle this below.
+ break;
+
+ case PotentiallyPotentiallyEvaluated:
+ // We are in an expression that may be potentially evaluated; queue this
+ // declaration reference until we know whether the expression is
+ // potentially evaluated.
+ PotentiallyReferencedDeclStack.back().push_back(std::make_pair(Loc, D));
+ return;
+ }
+
// Note that this declaration has been used.
+ if (CXXConstructorDecl *Constructor = dyn_cast<CXXConstructorDecl>(D)) {
+ unsigned TypeQuals;
+ if (Constructor->isImplicit() && Constructor->isDefaultConstructor()) {
+ if (!Constructor->isUsed())
+ DefineImplicitDefaultConstructor(Loc, Constructor);
+ }
+ else if (Constructor->isImplicit() &&
+ Constructor->isCopyConstructor(Context, TypeQuals)) {
+ if (!Constructor->isUsed())
+ DefineImplicitCopyConstructor(Loc, Constructor, TypeQuals);
+ }
+ // FIXME: more checking for other implicits go here.
+ else
+ Constructor->setUsed(true);
+ }
+
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
- // FIXME: implicit template instantiation
+ // Implicit instantiation of function templates
+ if (!Function->getBody(Context)) {
+ if (Function->getInstantiatedFromMemberFunction())
+ PendingImplicitInstantiations.push(std::make_pair(Function, Loc));
+
+ // FIXME: check for function template specializations.
+ }
+
+
// FIXME: keep track of references to static functions
- (void)Function;
Function->setUsed(true);
return;
- }
+ }
if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
(void)Var;
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index bec595c..a567218 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -71,6 +71,31 @@ Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
QualType TypeInfoType = Context.getTypeDeclType(TypeInfoRecordDecl);
+ if (!isType) {
+ // C++0x [expr.typeid]p3:
+ // When typeid is applied to an expression other than an lvalue of a
+ // polymorphic class type [...] [the] expression is an unevaluated
+ // operand.
+
+ // FIXME: if the type of the expression is a class type, the class
+ // shall be completely defined.
+ bool isUnevaluatedOperand = true;
+ Expr *E = static_cast<Expr *>(TyOrExpr);
+ if (E && !E->isTypeDependent() && E->isLvalue(Context) == Expr::LV_Valid) {
+ QualType T = E->getType();
+ if (const RecordType *RecordT = T->getAsRecordType()) {
+ CXXRecordDecl *RecordD = cast<CXXRecordDecl>(RecordT->getDecl());
+ if (RecordD->isPolymorphic())
+ isUnevaluatedOperand = false;
+ }
+ }
+
+ // If this is an unevaluated operand, clear out the set of declaration
+ // references we have been computing.
+ if (isUnevaluatedOperand)
+ PotentiallyReferencedDeclStack.back().clear();
+ }
+
return Owned(new (Context) CXXTypeidExpr(isType, TyOrExpr,
TypeInfoType.withConst(),
SourceRange(OpLoc, RParenLoc)));
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index fb41b2b..e98ebb1 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -847,13 +847,14 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// Check that the template argument list is well-formed for this
// template.
- TemplateArgumentListBuilder ConvertedTemplateArgs(Context);
+ TemplateArgumentListBuilder Converted(Template->getTemplateParameters(),
+ NumTemplateArgs);
if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc,
TemplateArgs, NumTemplateArgs, RAngleLoc,
- ConvertedTemplateArgs))
+ Converted))
return QualType();
- assert((ConvertedTemplateArgs.structuredSize() ==
+ assert((Converted.structuredSize() ==
Template->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@@ -871,16 +872,16 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
// template<typename T, typename U = T> struct A;
TemplateName CanonName = Context.getCanonicalTemplateName(Name);
CanonType = Context.getTemplateSpecializationType(CanonName,
- ConvertedTemplateArgs.getFlatArgumentList(),
- ConvertedTemplateArgs.flatSize());
+ Converted.getFlatArguments(),
+ Converted.flatSize());
} else if (ClassTemplateDecl *ClassTemplate
= dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID,
- ConvertedTemplateArgs.getFlatArgumentList(),
- ConvertedTemplateArgs.flatSize());
+ Converted.getFlatArguments(),
+ Converted.flatSize());
void *InsertPos = 0;
ClassTemplateSpecializationDecl *Decl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
@@ -892,7 +893,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ClassTemplate->getDeclContext(),
TemplateLoc,
ClassTemplate,
- ConvertedTemplateArgs, 0);
+ Converted, 0);
ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
Decl->setLexicalDeclContext(CurContext);
}
@@ -1003,7 +1004,7 @@ bool Sema::CheckTemplateTypeArgument(TemplateTypeParmDecl *Param,
return true;
// Add the converted template type argument.
- Converted.push_back(
+ Converted.Append(
TemplateArgument(Arg.getLocation(),
Context.getCanonicalType(Arg.getAsType())));
return false;
@@ -1061,9 +1062,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// parameter.
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
if (TTP->isParameterPack()) {
- // We have an empty parameter pack.
- Converted.BeginParameterPack();
- Converted.EndParameterPack();
+ // We have an empty argument pack.
+ Converted.BeginPack();
+ Converted.EndPack();
break;
}
@@ -1076,13 +1077,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// on the previously-computed template arguments.
if (ArgType->isDependentType()) {
InstantiatingTemplate Inst(*this, TemplateLoc,
- Template, Converted.getFlatArgumentList(),
+ Template, Converted.getFlatArguments(),
Converted.flatSize(),
SourceRange(TemplateLoc, RAngleLoc));
TemplateArgumentList TemplateArgs(Context, Converted,
- /*CopyArgs=*/false,
- /*FlattenArgs=*/false);
+ /*TakeArgs=*/false);
ArgType = InstantiateType(ArgType, TemplateArgs,
TTP->getDefaultArgumentLoc(),
TTP->getDeclName());
@@ -1098,13 +1098,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
break;
InstantiatingTemplate Inst(*this, TemplateLoc,
- Template, Converted.getFlatArgumentList(),
+ Template, Converted.getFlatArguments(),
Converted.flatSize(),
SourceRange(TemplateLoc, RAngleLoc));
TemplateArgumentList TemplateArgs(Context, Converted,
- /*CopyArgs=*/false,
- /*FlattenArgs=*/false);
+ /*TakeArgs=*/false);
Sema::OwningExprResult E = InstantiateExpr(NTTP->getDefaultArgument(),
TemplateArgs);
@@ -1130,14 +1129,14 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*Param)) {
if (TTP->isParameterPack()) {
- Converted.BeginParameterPack();
+ Converted.BeginPack();
// Check all the remaining arguments (if any).
for (; ArgIdx < NumArgs; ++ArgIdx) {
if (CheckTemplateTypeArgument(TTP, TemplateArgs[ArgIdx], Converted))
Invalid = true;
}
- Converted.EndParameterPack();
+ Converted.EndPack();
} else {
if (CheckTemplateTypeArgument(TTP, Arg, Converted))
Invalid = true;
@@ -1152,13 +1151,12 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (NTTPType->isDependentType()) {
// Instantiate the type of the non-type template parameter.
InstantiatingTemplate Inst(*this, TemplateLoc,
- Template, Converted.getFlatArgumentList(),
+ Template, Converted.getFlatArguments(),
Converted.flatSize(),
SourceRange(TemplateLoc, RAngleLoc));
TemplateArgumentList TemplateArgs(Context, Converted,
- /*CopyArgs=*/false,
- /*FlattenArgs=*/false);
+ /*TakeArgs=*/false);
NTTPType = InstantiateType(NTTPType, TemplateArgs,
NTTP->getLocation(),
NTTP->getDeclName());
@@ -1167,7 +1165,6 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (!NTTPType.isNull())
NTTPType = CheckNonTypeTemplateParameterType(NTTPType,
NTTP->getLocation());
-
if (NTTPType.isNull()) {
Invalid = true;
break;
@@ -1185,7 +1182,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
if (CheckTemplateArgument(NTTP, NTTPType, E, Result))
Invalid = true;
else
- Converted.push_back(Result);
+ Converted.Append(Result);
break;
}
@@ -1193,7 +1190,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Integral:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
- Converted.push_back(Arg);
+ Converted.Append(Arg);
break;
case TemplateArgument::Type:
@@ -1240,7 +1237,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
// Add the converted template argument.
Decl *D
= Context.getCanonicalDecl(cast<DeclRefExpr>(ArgExpr)->getDecl());
- Converted.push_back(TemplateArgument(Arg.getLocation(), D));
+ Converted.Append(TemplateArgument(Arg.getLocation(), D));
continue;
}
}
@@ -1257,7 +1254,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template,
case TemplateArgument::Declaration:
// We've already checked this template argument, so just copy
// it to the list of converted arguments.
- Converted.push_back(Arg);
+ Converted.Append(Arg);
break;
case TemplateArgument::Integral:
@@ -2102,7 +2099,7 @@ bool Sema::CheckClassTemplatePartialSpecializationArgs(
// accommodate variadic templates.
MirrorsPrimaryTemplate = true;
- const TemplateArgument *ArgList = TemplateArgs.getFlatArgumentList();
+ const TemplateArgument *ArgList = TemplateArgs.getFlatArguments();
for (unsigned I = 0, N = TemplateParams->size(); I != N; ++I) {
// Determine whether the template argument list of the partial
@@ -2298,13 +2295,14 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
// Check that the template argument list is well-formed for this
// template.
- TemplateArgumentListBuilder ConvertedTemplateArgs(Context);
+ TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(),
+ TemplateArgs.size());
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc,
TemplateArgs.data(), TemplateArgs.size(),
- RAngleLoc, ConvertedTemplateArgs))
+ RAngleLoc, Converted))
return true;
- assert((ConvertedTemplateArgs.structuredSize() ==
+ assert((Converted.structuredSize() ==
ClassTemplate->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@@ -2315,8 +2313,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
bool MirrorsPrimaryTemplate;
if (CheckClassTemplatePartialSpecializationArgs(
ClassTemplate->getTemplateParameters(),
- ConvertedTemplateArgs,
- MirrorsPrimaryTemplate))
+ Converted, MirrorsPrimaryTemplate))
return true;
if (MirrorsPrimaryTemplate) {
@@ -2338,13 +2335,13 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
// FIXME: Template parameter list matters, too
ClassTemplatePartialSpecializationDecl::Profile(ID,
- ConvertedTemplateArgs.getFlatArgumentList(),
- ConvertedTemplateArgs.flatSize());
+ Converted.getFlatArguments(),
+ Converted.flatSize());
}
else
ClassTemplateSpecializationDecl::Profile(ID,
- ConvertedTemplateArgs.getFlatArgumentList(),
- ConvertedTemplateArgs.flatSize());
+ Converted.getFlatArguments(),
+ Converted.flatSize());
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl = 0;
@@ -2387,7 +2384,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
TemplateNameLoc,
TemplateParams,
ClassTemplate,
- ConvertedTemplateArgs,
+ Converted,
PrevPartial);
if (PrevPartial) {
@@ -2437,7 +2434,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK,
ClassTemplate->getDeclContext(),
TemplateNameLoc,
ClassTemplate,
- ConvertedTemplateArgs,
+ Converted,
PrevDecl);
if (PrevDecl) {
@@ -2559,13 +2556,14 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
// Check that the template argument list is well-formed for this
// template.
- TemplateArgumentListBuilder ConvertedTemplateArgs(Context);
+ TemplateArgumentListBuilder Converted(ClassTemplate->getTemplateParameters(),
+ TemplateArgs.size());
if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc,
TemplateArgs.data(), TemplateArgs.size(),
- RAngleLoc, ConvertedTemplateArgs))
+ RAngleLoc, Converted))
return true;
- assert((ConvertedTemplateArgs.structuredSize() ==
+ assert((Converted.structuredSize() ==
ClassTemplate->getTemplateParameters()->size()) &&
"Converted template argument list is too short!");
@@ -2573,8 +2571,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID,
- ConvertedTemplateArgs.getFlatArgumentList(),
- ConvertedTemplateArgs.flatSize());
+ Converted.getFlatArguments(),
+ Converted.flatSize());
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
@@ -2617,7 +2615,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
ClassTemplate->getDeclContext(),
TemplateNameLoc,
ClassTemplate,
- ConvertedTemplateArgs, 0);
+ Converted, 0);
Specialization->setLexicalDeclContext(CurContext);
CurContext->addDecl(Context, Specialization);
return DeclPtrTy::make(Specialization);
@@ -2643,7 +2641,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc,
ClassTemplate->getDeclContext(),
TemplateNameLoc,
ClassTemplate,
- ConvertedTemplateArgs, 0);
+ Converted, 0);
ClassTemplate->getSpecializations().InsertNode(Specialization,
InsertPos);
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 784e451..de3e52d 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -654,7 +654,8 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
// C++ [temp.deduct.type]p2:
// [...] or if any template argument remains neither deduced nor
// explicitly specified, template argument deduction fails.
- TemplateArgumentListBuilder Builder(Context);
+ TemplateArgumentListBuilder Builder(Partial->getTemplateParameters(),
+ Deduced.size());
for (unsigned I = 0, N = Deduced.size(); I != N; ++I) {
if (Deduced[I].isNull()) {
Decl *Param
@@ -669,13 +670,12 @@ Sema::DeduceTemplateArguments(ClassTemplatePartialSpecializationDecl *Partial,
return TDK_Incomplete;
}
- Builder.push_back(Deduced[I]);
+ Builder.Append(Deduced[I]);
}
// Form the template argument list from the deduced template arguments.
TemplateArgumentList *DeducedArgumentList
- = new (Context) TemplateArgumentList(Context, Builder, /*CopyArgs=*/true,
- /*FlattenArgs=*/true);
+ = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true);
Info.reset(DeducedArgumentList);
// Substitute the deduced template arguments into the template
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 3992f8c..1c4e907 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -420,6 +420,7 @@ InstantiateDependentSizedArrayType(const DependentSizedArrayType *T,
}
// Instantiate the size expression
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
Sema::OwningExprResult InstantiatedArraySize =
SemaRef.InstantiateExpr(ArraySize, TemplateArgs);
if (InstantiatedArraySize.isInvalid())
@@ -443,6 +444,10 @@ InstantiateDependentSizedExtVectorType(const DependentSizedExtVectorType *T,
return QualType();
}
+ // The expression in a dependent-sized extended vector type is not
+ // potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
// Instantiate the size expression.
const Expr *SizeExpr = T->getSizeExpr();
Sema::OwningExprResult InstantiatedArraySize =
@@ -520,6 +525,9 @@ TemplateTypeInstantiator::InstantiateTypedefType(const TypedefType *T,
QualType
TemplateTypeInstantiator::InstantiateTypeOfExprType(const TypeOfExprType *T,
unsigned Quals) const {
+ // The expression in a typeof is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
Sema::OwningExprResult E
= SemaRef.InstantiateExpr(T->getUnderlyingExpr(), TemplateArgs);
if (E.isInvalid())
@@ -1175,6 +1183,9 @@ TemplateArgument Sema::Instantiate(TemplateArgument Arg,
return Arg;
case TemplateArgument::Expression: {
+ // Template argument expressions are not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(*this, Action::Unevaluated);
+
Sema::OwningExprResult E = InstantiateExpr(Arg.getAsExpr(), TemplateArgs);
if (E.isInvalid())
return TemplateArgument();
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6d7dc2e..ece71bc 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -163,6 +163,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
if (Invalid)
BitWidth = 0;
else if (BitWidth) {
+ // The bit-width expression is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
OwningExprResult InstantiatedBitWidth
= SemaRef.InstantiateExpr(BitWidth, TemplateArgs);
if (InstantiatedBitWidth.isInvalid()) {
@@ -192,6 +195,9 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {
Decl *TemplateDeclInstantiator::VisitStaticAssertDecl(StaticAssertDecl *D) {
Expr *AssertExpr = D->getAssertExpr();
+ // The expression in a static assertion is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
OwningExprResult InstantiatedAssertExpr
= SemaRef.InstantiateExpr(AssertExpr, TemplateArgs);
if (InstantiatedAssertExpr.isInvalid())
@@ -222,8 +228,13 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) {
EC != ECEnd; ++EC) {
// The specified value for the enumerator.
OwningExprResult Value = SemaRef.Owned((Expr *)0);
- if (Expr *UninstValue = EC->getInitExpr())
+ if (Expr *UninstValue = EC->getInitExpr()) {
+ // The enumerator's value expression is not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef,
+ Action::Unevaluated);
+
Value = SemaRef.InstantiateExpr(UninstValue, TemplateArgs);
+ }
// Drop the initial value and continue.
bool isInvalid = false;
@@ -586,6 +597,8 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (Function->isInvalidDecl())
return;
+ assert(!Function->getBody(Context) && "Already instantiated!");
+
// Find the function body that we'll be substituting.
const FunctionDecl *PatternDecl
= Function->getInstantiatedFromMemberFunction();
@@ -765,3 +778,18 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) {
return D;
}
+
+/// \brief Performs template instantiation for all implicit template
+/// instantiations we have seen until this point.
+void Sema::PerformPendingImplicitInstantiations() {
+ while (!PendingImplicitInstantiations.empty()) {
+ PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front();
+ PendingImplicitInstantiations.pop();
+
+ if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first))
+ if (!Function->getBody(Context))
+ InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function);
+
+ // FIXME: instantiation static member variables
+ }
+}
diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp
index bf19701..749fb58 100644
--- a/lib/Sema/SemaTemplateInstantiateExpr.cpp
+++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp
@@ -714,9 +714,17 @@ TemplateExprInstantiator::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
E->getSourceRange());
}
- Sema::OwningExprResult Arg = Visit(E->getArgumentExpr());
- if (Arg.isInvalid())
- return SemaRef.ExprError();
+ Sema::OwningExprResult Arg(SemaRef);
+ {
+ // C++0x [expr.sizeof]p1:
+ // The operand is either an expression, which is an unevaluated operand
+ // [...]
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
+ Arg = Visit(E->getArgumentExpr());
+ if (Arg.isInvalid())
+ return SemaRef.ExprError();
+ }
Sema::OwningExprResult Result
= SemaRef.CreateSizeOfAlignOfExpr((Expr *)Arg.get(), E->getOperatorLoc(),
@@ -949,6 +957,12 @@ TemplateExprInstantiator::VisitCXXTypeidExpr(CXXTypeidExpr *E) {
E->getSourceRange().getEnd());
}
+ // We don't know whether the expression is potentially evaluated until
+ // after we perform semantic analysis, so the expression is potentially
+ // potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef,
+ Action::PotentiallyPotentiallyEvaluated);
+
OwningExprResult Operand = Visit(E->getExprOperand());
if (Operand.isInvalid())
return SemaRef.ExprError();
diff --git a/lib/Sema/SemaTemplateInstantiateStmt.cpp b/lib/Sema/SemaTemplateInstantiateStmt.cpp
index efdcec8..565b95b 100644
--- a/lib/Sema/SemaTemplateInstantiateStmt.cpp
+++ b/lib/Sema/SemaTemplateInstantiateStmt.cpp
@@ -145,6 +145,9 @@ TemplateStmtInstantiator::VisitSwitchCase(SwitchCase *S) {
}
Sema::OwningStmtResult TemplateStmtInstantiator::VisitCaseStmt(CaseStmt *S) {
+ // The case value expressions are not potentially evaluated.
+ EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated);
+
// Instantiate left-hand case value.
OwningExprResult LHS = SemaRef.InstantiateExpr(S->getLHS(), TemplateArgs);
if (LHS.isInvalid())
OpenPOWER on IntegriCloud