summaryrefslogtreecommitdiffstats
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
parent8927c19a5ed03bef55dac4b623688387bcc794dc (diff)
downloadFreeBSD-src-da468bf93e74598f985f4988936ee5ca2dc9a38c.zip
FreeBSD-src-da468bf93e74598f985f4988936ee5ca2dc9a38c.tar.gz
Import Clang r73954.
-rw-r--r--include/clang/AST/Decl.h8
-rw-r--r--include/clang/AST/DeclCXX.h22
-rw-r--r--include/clang/AST/DeclTemplate.h92
-rw-r--r--include/clang/Analysis/PathSensitive/Environment.h6
-rw-r--r--include/clang/Analysis/PathSensitive/GRExprEngine.h5
-rw-r--r--include/clang/Analysis/PathSensitive/GRState.h6
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h226
-rw-r--r--include/clang/Analysis/PathSensitive/SVals.h35
-rw-r--r--include/clang/Analysis/PathSensitive/ValueManager.h82
-rw-r--r--include/clang/Basic/DiagnosticFrontendKinds.td3
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td7
-rw-r--r--include/clang/Basic/SourceLocation.h4
-rw-r--r--include/clang/Parse/Action.h71
-rw-r--r--include/clang/Parse/Parser.h18
-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
-rw-r--r--test/CodeGen/functions.c4
-rw-r--r--test/CodeGenCXX/implicit-instantiation-1.cpp29
-rw-r--r--test/SemaCXX/default-constructor-initializers.cpp4
-rw-r--r--test/SemaTemplate/class-template-decl.cpp6
-rw-r--r--test/SemaTemplate/example-dynarray.cpp28
-rw-r--r--test/SemaTemplate/implicit-instantiation-1.cpp16
55 files changed, 1265 insertions, 835 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 77b7bf6..f594db2 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -647,6 +647,13 @@ private:
// Move to DeclGroup when it is implemented.
SourceLocation TypeSpecStartLoc;
+ /// \brief End part of this FunctionDecl's source range.
+ ///
+ /// We could compute the full range in getSourceRange(). However, when we're
+ /// dealing with a function definition deserialized from a PCH/AST file,
+ /// we can only compute the full range once the function body has been
+ /// de-serialized, so it's far better to have the (sometimes-redundant)
+ /// EndRangeLoc.
SourceLocation EndRangeLoc;
/// \brief The template or declaration that this declaration
@@ -687,7 +694,6 @@ public:
return SourceRange(getLocation(), EndRangeLoc);
}
void setLocEnd(SourceLocation E) {
- assert(getLocation() <= E && "Invalid end location");
EndRangeLoc = E;
}
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index 9ca1823..52ed0ec 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -283,6 +283,10 @@ public:
/// copy constructor that accepts a const-qualified argument.
bool hasConstCopyConstructor(ASTContext &Context) const;
+ /// getCopyConstructor - Returns the copy constructor for this class
+ CXXConstructorDecl *getCopyConstructor(ASTContext &Context,
+ unsigned TypeQuals) const;
+
/// hasConstCopyAssignment - Determines whether this class has a
/// copy assignment operator that accepts a const-qualified argument.
bool hasConstCopyAssignment(ASTContext &Context) const;
@@ -642,18 +646,13 @@ class CXXConstructorDecl : public CXXMethodDecl {
/// @c !Implicit && ImplicitlyDefined.
bool ImplicitlyDefined : 1;
- /// ImplicitMustBeDefined - Implicit constructor was used to create an
- /// object of its class type. It must be defined.
- bool ImplicitMustBeDefined : 1;
-
/// FIXME: Add support for base and member initializers.
CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L,
DeclarationName N, QualType T,
bool isExplicit, bool isInline, bool isImplicitlyDeclared)
: CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline),
- Explicit(isExplicit), ImplicitlyDefined(false),
- ImplicitMustBeDefined(false) {
+ Explicit(isExplicit), ImplicitlyDefined(false) {
setImplicit(isImplicitlyDeclared);
}
@@ -683,17 +682,6 @@ public:
"Can only set the implicit-definition flag once the constructor has been defined");
ImplicitlyDefined = ID;
}
-
- /// isImplicitMustBeDefined - Whether a definition must be synthesized for
- /// the implicit constructor.
- bool isImplicitMustBeDefined() const {
- return isImplicit() && ImplicitMustBeDefined;
- }
-
- /// setImplicitMustBeDefined - constructor must be implicitly defined.
- void setImplicitMustBeDefined() {
- ImplicitMustBeDefined = true;
- }
/// isDefaultConstructor - Whether this constructor is a default
/// constructor (C++ [class.ctor]p5), which can be used to
diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h
index af06965f..2608dd9 100644
--- a/include/clang/AST/DeclTemplate.h
+++ b/include/clang/AST/DeclTemplate.h
@@ -469,10 +469,6 @@ public:
/// occur in a non-dependent, canonical template argument list.
TemplateArgument(Expr *E);
- /// \brief Construct a template argument pack.
- TemplateArgument(SourceLocation Loc, TemplateArgument *Args,
- unsigned NumArgs, bool CopyArgs);
-
/// \brief Copy constructor for a template argument.
TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) {
if (Kind == Integral) {
@@ -587,6 +583,9 @@ public:
/// \brief Retrieve the location where the template argument starts.
SourceLocation getLocation() const { return StartLoc; }
+ /// \brief Construct a template argument pack.
+ void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs);
+
/// \brief Used to insert TemplateArguments into FoldingSets.
void Profile(llvm::FoldingSetNodeID &ID) const {
ID.AddInteger(Kind);
@@ -622,47 +621,51 @@ public:
/// \brief A helper class for making template argument lists.
class TemplateArgumentListBuilder {
- /// FlatArgs - contains the template arguments in flat form.
- llvm::SmallVector<TemplateArgument, 16> FlatArgs;
-
- llvm::SmallVector<TemplateArgument, 16> StructuredArgs;
-
- ASTContext &Context;
+ TemplateArgument *StructuredArgs;
+ unsigned MaxStructuredArgs;
+ unsigned NumStructuredArgs;
+
+ TemplateArgument *FlatArgs;
+ unsigned MaxFlatArgs;
+ unsigned NumFlatArgs;
+ bool AddingToPack;
unsigned PackBeginIndex;
-
- /// isAddingFromParameterPack - Returns whether we're adding arguments from
- /// a parameter pack.
- bool isAddingFromParameterPack() const {
- return PackBeginIndex != std::numeric_limits<unsigned>::max();
- }
public:
- TemplateArgumentListBuilder(ASTContext &Context) : Context(Context),
- PackBeginIndex(std::numeric_limits<unsigned>::max()) { }
+ TemplateArgumentListBuilder(const TemplateParameterList *Parameters,
+ unsigned NumTemplateArgs)
+ : StructuredArgs(0), MaxStructuredArgs(Parameters->size()),
+ NumStructuredArgs(0), FlatArgs(0),
+ MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0),
+ AddingToPack(false), PackBeginIndex(0) { }
- size_t structuredSize() const {
- assert(!isAddingFromParameterPack() &&
- "Size is not valid when adding from a parameter pack");
-
- return StructuredArgs.size();
- }
-
- size_t flatSize() const { return FlatArgs.size(); }
+ void Append(const TemplateArgument& Arg);
+ void BeginPack();
+ void EndPack();
- void push_back(const TemplateArgument& Arg);
-
- /// BeginParameterPack - Start adding arguments from a parameter pack.
- void BeginParameterPack();
+ void ReleaseArgs();
- /// EndParameterPack - Finish adding arguments from a parameter pack.
- void EndParameterPack();
+ unsigned flatSize() const {
+ return NumFlatArgs;
+ }
+ const TemplateArgument *getFlatArguments() const {
+ return FlatArgs;
+ }
- const TemplateArgument *getFlatArgumentList() const {
- return FlatArgs.data();
+ unsigned structuredSize() const {
+ // If we don't have any structured args, just reuse the flat size.
+ if (!StructuredArgs)
+ return flatSize();
+
+ return NumStructuredArgs;
}
- TemplateArgument *getFlatArgumentList() {
- return FlatArgs.data();
+ const TemplateArgument *getStructuredArguments() const {
+ // If we don't have any structured args, just reuse the flat args.
+ if (!StructuredArgs)
+ return getFlatArguments();
+
+ return StructuredArgs;
}
};
@@ -676,22 +679,25 @@ class TemplateArgumentList {
///
/// The integer value will be non-zero to indicate that this
/// template argument list does not own the pointer.
- llvm::PointerIntPair<TemplateArgument *, 1> Arguments;
+ llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments;
/// \brief The number of template arguments in this template
/// argument list.
- unsigned NumArguments;
+ unsigned NumFlatArguments;
+ llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments;
+ unsigned NumStructuredArguments;
+
public:
TemplateArgumentList(ASTContext &Context,
TemplateArgumentListBuilder &Builder,
- bool CopyArgs, bool FlattenArgs);
+ bool TakeArgs);
~TemplateArgumentList();
/// \brief Retrieve the template argument at a given index.
const TemplateArgument &get(unsigned Idx) const {
- assert(Idx < NumArguments && "Invalid template argument index");
+ assert(Idx < NumFlatArguments && "Invalid template argument index");
return getFlatArgumentList()[Idx];
}
@@ -700,15 +706,15 @@ public:
/// \brief Retrieve the number of template arguments in this
/// template argument list.
- unsigned size() const { return NumArguments; }
+ unsigned size() const { return NumFlatArguments; }
/// \brief Retrieve the number of template arguments in the
/// flattened template argument list.
- unsigned flat_size() const { return NumArguments; }
+ unsigned flat_size() const { return NumFlatArguments; }
/// \brief Retrieve the flattened template argument list.
const TemplateArgument *getFlatArgumentList() const {
- return Arguments.getPointer();
+ return FlatArguments.getPointer();
}
};
diff --git a/include/clang/Analysis/PathSensitive/Environment.h b/include/clang/Analysis/PathSensitive/Environment.h
index 0fc49f5..6f8a126 100644
--- a/include/clang/Analysis/PathSensitive/Environment.h
+++ b/include/clang/Analysis/PathSensitive/Environment.h
@@ -27,7 +27,7 @@
namespace clang {
class EnvironmentManager;
-class BasicValueFactory;
+class ValueManager;
class LiveVariables;
class Environment {
@@ -71,8 +71,8 @@ public:
return X ? *X : UnknownVal();
}
- SVal GetSVal(const Stmt* Ex, BasicValueFactory& BasicVals) const;
- SVal GetBlkExprSVal(const Stmt* Ex, BasicValueFactory& BasicVals) const;
+ SVal GetSVal(const Stmt* Ex, ValueManager& ValMgr) const;
+ SVal GetBlkExprSVal(const Stmt* Ex, ValueManager& ValMgr) const;
/// Profile - Profile the contents of an Environment object for use
/// in a FoldingSet.
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h
index 4af8a7c..5db666c 100644
--- a/include/clang/Analysis/PathSensitive/GRExprEngine.h
+++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h
@@ -481,11 +481,6 @@ protected:
return N == EntryNode ? CleanedState : N->getState();
}
-public:
- inline NonLoc MakeConstantVal(uint64_t X, Expr* Ex) {
- return NonLoc::MakeVal(getBasicVals(), X, Ex->getType());
- }
-
public:
NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, const GRState* St,
ProgramPoint::Kind K = ProgramPoint::PostStmtKind,
diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h
index 6f95c6f..2cb3f94 100644
--- a/include/clang/Analysis/PathSensitive/GRState.h
+++ b/include/clang/Analysis/PathSensitive/GRState.h
@@ -532,7 +532,7 @@ private:
// Methods that query & manipulate the Environment.
SVal GetSVal(const GRState* St, const Stmt* Ex) {
- return St->getEnvironment().GetSVal(Ex, getBasicVals());
+ return St->getEnvironment().GetSVal(Ex, ValueMgr);
}
SVal GetSValAsScalarOrLoc(const GRState* state, const Stmt *S) {
@@ -546,7 +546,7 @@ private:
}
SVal GetBlkExprSVal(const GRState* St, const Stmt* Ex) {
- return St->getEnvironment().GetBlkExprSVal(Ex, getBasicVals());
+ return St->getEnvironment().GetBlkExprSVal(Ex, ValueMgr);
}
const GRState* BindExpr(const GRState* St, const Stmt* Ex, SVal V,
@@ -613,7 +613,7 @@ public:
// We only want to do fetches from regions that we can actually bind
// values. For example, SymbolicRegions of type 'id<...>' cannot
// have direct bindings (but their can be bindings on their subregions).
- if (!R->isBoundable(getContext()))
+ if (!R->isBoundable())
return UnknownVal();
if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index 8afcc4c..ac158dc 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -59,11 +59,14 @@ private:
protected:
MemRegion(Kind k) : kind(k) {}
virtual ~MemRegion();
+ ASTContext &getContext() const;
public:
// virtual MemExtent getExtent(MemRegionManager& mrm) const = 0;
virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
-
+
+ virtual MemRegionManager* getMemRegionManager() const = 0;
+
std::string getString() const;
virtual void print(llvm::raw_ostream& os) const;
@@ -72,7 +75,7 @@ public:
template<typename RegionTy> const RegionTy* getAs() const;
- virtual bool isBoundable(ASTContext&) const { return true; }
+ virtual bool isBoundable() const { return true; }
static bool classof(const MemRegion*) { return true; }
};
@@ -81,14 +84,23 @@ public:
/// for example, the set of global variables, the stack frame, etc.
class MemSpaceRegion : public MemRegion {
friend class MemRegionManager;
- MemSpaceRegion() : MemRegion(MemSpaceRegionKind) {}
+
+protected:
+ MemRegionManager *Mgr;
+
+ MemSpaceRegion(MemRegionManager *mgr) : MemRegion(MemSpaceRegionKind),
+ Mgr(mgr) {}
+ MemRegionManager* getMemRegionManager() const {
+ return Mgr;
+ }
+
public:
//RegionExtent getExtent() const { return UndefinedExtent(); }
void Profile(llvm::FoldingSetNodeID& ID) const;
- bool isBoundable(ASTContext &) const { return false; }
+ bool isBoundable() const { return false; }
static bool classof(const MemRegion* R) {
return R->getKind() == MemSpaceRegionKind;
@@ -101,11 +113,12 @@ class SubRegion : public MemRegion {
protected:
const MemRegion* superRegion;
SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
-
public:
const MemRegion* getSuperRegion() const {
return superRegion;
}
+
+ MemRegionManager* getMemRegionManager() const;
bool isSubRegionOf(const MemRegion* R) const;
@@ -123,7 +136,7 @@ protected:
// memory allocated by alloca at the same call site.
const Expr* Ex;
- AllocaRegion(const Expr* ex, unsigned cnt, const MemRegion* superRegion)
+ AllocaRegion(const Expr* ex, unsigned cnt, const MemRegion *superRegion)
: SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {}
public:
@@ -133,7 +146,7 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr* Ex,
- unsigned Cnt);
+ unsigned Cnt, const MemRegion *superRegion);
void print(llvm::raw_ostream& os) const;
@@ -164,8 +177,8 @@ public:
return getLocationType(C)->getDesugaredType();
}
- bool isBoundable(ASTContext &C) const {
- return !getValueType(C).isNull();
+ bool isBoundable() const {
+ return !getValueType(getContext()).isNull();
}
static bool classof(const MemRegion* R) {
@@ -229,14 +242,14 @@ public:
return const_cast<SymbolRef>(static_cast<const SymbolRef>(Data));
}
- bool isBoundable(ASTContext&) const { return false; }
+ bool isBoundable() const { return false; }
virtual void print(llvm::raw_ostream& os) const;
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
- const void* data, QualType t);
+ const void* data, QualType t, const MemRegion*);
static bool classof(const MemRegion* R) {
return R->getKind() == CodeTextRegionKind;
@@ -262,7 +275,9 @@ public:
void Profile(llvm::FoldingSetNodeID& ID) const;
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym);
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ SymbolRef sym,
+ const MemRegion* superRegion);
void print(llvm::raw_ostream& os) const;
@@ -277,7 +292,7 @@ class StringRegion : public TypedRegion {
const StringLiteral* Str;
protected:
- StringRegion(const StringLiteral* str, MemRegion* sreg)
+ StringRegion(const StringLiteral* str, const MemRegion* sreg)
: TypedRegion(sreg, StringRegionKind), Str(str) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID,
@@ -327,7 +342,7 @@ public:
return PTy->getPointeeType();
}
- bool isBoundable(ASTContext &C) const {
+ bool isBoundable() const {
return isa<PointerType>(LValueType);
}
@@ -399,8 +414,8 @@ class VarRegion : public DeclRegion {
VarRegion(const VarDecl* vd, const MemRegion* sReg)
: DeclRegion(vd, sReg, VarRegionKind) {}
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, VarDecl* VD,
- const MemRegion* superRegion) {
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD,
+ const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
}
@@ -436,8 +451,8 @@ public:
return C.getCanonicalType(getDecl()->getType());
}
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, FieldDecl* FD,
- const MemRegion* superRegion) {
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl* FD,
+ const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
}
@@ -453,7 +468,8 @@ class ObjCObjectRegion : public DeclRegion {
ObjCObjectRegion(const ObjCInterfaceDecl* ivd, const MemRegion* sReg)
: DeclRegion(ivd, sReg, ObjCObjectRegionKind) {}
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCInterfaceDecl* ivd,
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const ObjCInterfaceDecl* ivd,
const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCObjectRegionKind);
}
@@ -479,8 +495,8 @@ class ObjCIvarRegion : public DeclRegion {
ObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* sReg)
: DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
- static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCIvarDecl* ivd,
- const MemRegion* superRegion) {
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl* ivd,
+ const MemRegion* superRegion) {
DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind);
}
@@ -556,6 +572,7 @@ const RegionTy* MemRegion::getAs() const {
//===----------------------------------------------------------------------===//
class MemRegionManager {
+ ASTContext &C;
llvm::BumpPtrAllocator& A;
llvm::FoldingSet<MemRegion> Regions;
@@ -566,11 +583,13 @@ class MemRegionManager {
MemSpaceRegion* code;
public:
- MemRegionManager(llvm::BumpPtrAllocator& a)
- : A(a), globals(0), stack(0), heap(0), unknown(0), code(0) {}
+ MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
+ : C(c), A(a), globals(0), stack(0), heap(0), unknown(0), code(0) {}
~MemRegionManager() {}
+ ASTContext &getContext() { return C; }
+
/// getStackRegion - Retrieve the memory region associated with the
/// current stack frame.
MemSpaceRegion* getStackRegion();
@@ -589,17 +608,6 @@ public:
MemSpaceRegion* getCodeRegion();
- bool isGlobalsRegion(const MemRegion* R) {
- assert(R);
- return R == globals;
- }
-
- /// onStack - check if the region is allocated on the stack.
- bool onStack(const MemRegion* R);
-
- /// onHeap - check if the region is allocated on the heap, usually by malloc.
- bool onHeap(const MemRegion* R);
-
/// getAllocaRegion - Retrieve a region associated with a call to alloca().
AllocaRegion* getAllocaRegion(const Expr* Ex, unsigned Cnt);
@@ -646,14 +654,164 @@ public:
CodeTextRegion* getCodeTextRegion(SymbolRef sym, QualType t);
CodeTextRegion* getCodeTextRegion(const FunctionDecl* fd, QualType t);
+
+ template <typename RegionTy, typename A1>
+ RegionTy* getRegion(const A1 a1);
+
+ template <typename RegionTy, typename A1>
+ RegionTy* getRegion(const A1 a1, const MemRegion* superRegion);
+
+ template <typename RegionTy, typename A1, typename A2>
+ RegionTy* getRegion(const A1 a1, const A2 a2);
+
+ bool isGlobalsRegion(const MemRegion* R) {
+ assert(R);
+ return R == globals;
+ }
bool hasStackStorage(const MemRegion* R);
+ bool hasHeapStorage(const MemRegion* R);
+
private:
MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
};
+
+//===----------------------------------------------------------------------===//
+// Out-of-line member definitions.
+//===----------------------------------------------------------------------===//
+
+inline ASTContext& MemRegion::getContext() const {
+ return getMemRegionManager()->getContext();
+}
+
+template<typename RegionTy> struct MemRegionManagerTrait;
+
+template <typename RegionTy, typename A1>
+RegionTy* MemRegionManager::getRegion(const A1 a1) {
+
+ const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
+ MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1);
+
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+template <typename RegionTy, typename A1>
+RegionTy* MemRegionManager::getRegion(const A1 a1, const MemRegion *superRegion)
+{
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+template <typename RegionTy, typename A1, typename A2>
+RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
+
+ const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
+ MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2);
+
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, a2, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, a2, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
+//===----------------------------------------------------------------------===//
+// Traits for constructing regions.
+//===----------------------------------------------------------------------===//
+
+template <> struct MemRegionManagerTrait<AllocaRegion> {
+ typedef MemRegion SuperRegionTy;
+ static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
+ const Expr *, unsigned) {
+ return MRMgr.getStackRegion();
+ }
+};
+
+template <> struct MemRegionManagerTrait<CompoundLiteralRegion> {
+ typedef MemRegion SuperRegionTy;
+ static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
+ const CompoundLiteralExpr *CL) {
+
+ return CL->isFileScope() ? MRMgr.getGlobalsRegion()
+ : MRMgr.getStackRegion();
+ }
+};
+
+template <> struct MemRegionManagerTrait<StringRegion> {
+ typedef MemSpaceRegion SuperRegionTy;
+ static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
+ const StringLiteral*) {
+ return MRMgr.getGlobalsRegion();
+ }
+};
+
+template <> struct MemRegionManagerTrait<VarRegion> {
+ typedef MemRegion SuperRegionTy;
+ static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
+ const VarDecl *d) {
+ return d->hasLocalStorage() ? MRMgr.getStackRegion()
+ : MRMgr.getGlobalsRegion();
+ }
+};
+
+template <> struct MemRegionManagerTrait<SymbolicRegion> {
+ typedef MemRegion SuperRegionTy;
+ static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
+ SymbolRef) {
+ return MRMgr.getUnknownRegion();
+ }
+};
+
+template<> struct MemRegionManagerTrait<CodeTextRegion> {
+ typedef MemSpaceRegion SuperRegionTy;
+ static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
+ const FunctionDecl*, QualType) {
+ return MRMgr.getCodeRegion();
+ }
+ static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr,
+ SymbolRef, QualType) {
+ return MRMgr.getCodeRegion();
+ }
+};
+
} // end clang namespace
+//===----------------------------------------------------------------------===//
+// Pretty-printing regions.
+//===----------------------------------------------------------------------===//
+
namespace llvm {
static inline raw_ostream& operator<<(raw_ostream& O,
const clang::MemRegion* R) {
diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h
index c9d1e25..de74dbd 100644
--- a/include/clang/Analysis/PathSensitive/SVals.h
+++ b/include/clang/Analysis/PathSensitive/SVals.h
@@ -30,6 +30,7 @@ class BasicValueFactory;
class MemRegion;
class MemRegionManager;
class GRStateManager;
+class ValueManager;
class SVal {
public:
@@ -171,28 +172,6 @@ protected:
public:
void print(llvm::raw_ostream& Out) const;
- // Utility methods to create NonLocs.
-
- static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
- bool isUnsigned);
-
- static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X,
- unsigned BitWidth, bool isUnsigned);
-
- static NonLoc MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T);
-
- static NonLoc MakeVal(BasicValueFactory& BasicVals, const IntegerLiteral *I);
-
- static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I,
- bool isUnsigned);
-
- static NonLoc MakeVal(BasicValueFactory& BasicVals, const llvm::APSInt& I);
-
- static NonLoc MakeIntTruthVal(BasicValueFactory& BasicVals, bool b);
-
- static NonLoc MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
- BasicValueFactory& BasicVals);
-
// Implement isa<T> support.
static inline bool classof(const SVal* V) {
return V->getBaseKind() == NonLocKind;
@@ -210,12 +189,6 @@ public:
Loc(const Loc& X) : SVal(X.Data, true, X.getSubKind()) {}
Loc& operator=(const Loc& X) { memcpy(this, &X, sizeof(Loc)); return *this; }
- static Loc MakeVal(const MemRegion* R);
-
- static Loc MakeVal(const AddrLabelExpr* E);
-
- static Loc MakeNull(BasicValueFactory &BasicVals);
-
// Implement isa<T> support.
static inline bool classof(const SVal* V) {
return V->getBaseKind() == LocKind;
@@ -301,6 +274,8 @@ public:
};
class LocAsInteger : public NonLoc {
+ friend class clang::ValueManager;
+
LocAsInteger(const std::pair<SVal, uintptr_t>& data) :
NonLoc(LocAsIntegerKind, &data) {
assert (isa<Loc>(data.first));
@@ -330,12 +305,10 @@ public:
static inline bool classof(const NonLoc* V) {
return V->getSubKind() == LocAsIntegerKind;
}
-
- static LocAsInteger Make(BasicValueFactory& Vals, Loc V, unsigned Bits);
};
class CompoundVal : public NonLoc {
- friend class NonLoc;
+ friend class clang::ValueManager;
CompoundVal(const CompoundValData* D) : NonLoc(CompoundValKind, D) {}
diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h
index b86f4e8..d8e557f 100644
--- a/include/clang/Analysis/PathSensitive/ValueManager.h
+++ b/include/clang/Analysis/PathSensitive/ValueManager.h
@@ -9,7 +9,7 @@
//
// This file defines ValueManager, a class that manages symbolic values
// and SVals created for use by GRExprEngine and related classes. It
-// wraps SymbolManager, MemRegionManager, and BasicValueFactory.
+// wraps and owns SymbolManager, MemRegionManager, and BasicValueFactory.
//
//===----------------------------------------------------------------------===//
@@ -39,7 +39,7 @@ public:
ValueManager(llvm::BumpPtrAllocator &alloc, ASTContext &context)
: Context(context), BasicVals(Context, alloc),
SymMgr(Context, BasicVals, alloc),
- MemMgr(alloc) {}
+ MemMgr(Context, alloc) {}
// Accessors to submanagers.
@@ -68,17 +68,8 @@ public:
return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag);
}
- // Aggregation methods that use multiple submanagers.
-
- Loc makeRegionVal(SymbolRef Sym) {
- return Loc::MakeVal(MemMgr.getSymbolicRegion(Sym));
- }
-
/// makeZeroVal - Construct an SVal representing '0' for the specified type.
SVal makeZeroVal(QualType T);
- /// makeZeroArrayIndex - Construct an SVal representing '0' index for array
- /// elements.
- SVal makeZeroArrayIndex();
/// GetRegionValueSymbolVal - make a unique symbol for value of R.
SVal getRegionValueSymbolVal(const MemRegion* R, QualType T = QualType());
@@ -87,16 +78,77 @@ public:
SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count);
SVal getFunctionPointer(const FunctionDecl* FD);
-
- NonLoc makeNonLoc(SymbolRef sym);
-
+
+ NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) {
+ return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
+ }
+
+ NonLoc makeZeroArrayIndex() {
+ return nonloc::ConcreteInt(BasicVals.getZeroWithPtrWidth(false));
+ }
+
+ NonLoc makeIntVal(const IntegerLiteral* I) {
+ return nonloc::ConcreteInt(BasicVals.getValue(I->getValue(),
+ I->getType()->isUnsignedIntegerType()));
+ }
+
+ NonLoc makeIntVal(const llvm::APSInt& V) {
+ return nonloc::ConcreteInt(BasicVals.getValue(V));
+ }
+
+ NonLoc makeIntVal(const llvm::APInt& V, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getValue(V, isUnsigned));
+ }
+
+ NonLoc makeIntVal(uint64_t X, QualType T) {
+ return nonloc::ConcreteInt(BasicVals.getValue(X, T));
+ }
+
+ NonLoc makeIntVal(uint64_t X, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned));
+ }
+
+ NonLoc makeIntVal(uint64_t X, unsigned BitWidth, bool isUnsigned) {
+ return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned));
+ }
+
+ NonLoc makeLocAsInteger(Loc V, unsigned Bits) {
+ return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(V, Bits));
+ }
+
NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const llvm::APSInt& rhs, QualType T);
NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType T);
- NonLoc makeTruthVal(bool b, QualType T);
+ NonLoc makeTruthVal(bool b, QualType T) {
+ return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T));
+ }
+
+ NonLoc makeTruthVal(bool b) {
+ return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
+ }
+
+ Loc makeNull() {
+ return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
+ }
+
+ Loc makeLoc(SymbolRef Sym) {
+ return loc::MemRegionVal(MemMgr.getSymbolicRegion(Sym));
+ }
+
+ Loc makeLoc(const MemRegion* R) {
+ return loc::MemRegionVal(R);
+ }
+
+ Loc makeLoc(const AddrLabelExpr* E) {
+ return loc::GotoLabel(E->getLabel());
+ }
+
+ Loc makeLoc(const llvm::APSInt& V) {
+ return loc::ConcreteInt(BasicVals.getValue(V));
+ }
};
} // end clang namespace
#endif
diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td
index ae5246d..9c43985 100644
--- a/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -136,4 +136,7 @@ def warn_pch_char_signed : Error<
def err_not_a_pch_file : Error<
"'%0' does not appear to be a precompiled header file">, DefaultFatal;
+def warn_unknown_warning_option : Warning<
+ "unknown warning option '%0'">,
+ InGroup<DiagGroup<"unknown-warning-option"> >;
}
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 755cfce..79a9efa 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -580,8 +580,8 @@ def err_param_default_argument_nonfunc : Error<
"default arguments can only be specified for parameters in a function "
"declaration">;
def err_defining_default_ctor : Error<
- "cannot define the default constructor for %0, because %select{base class|member}1 "
- "%2 does not have any implicit default constructor">;
+ "cannot define the implicit default constructor for %0, because %select{base class|member}1 "
+ "%2 does not have any default constructor">;
def note_previous_class_decl : Note<
"%0 declared here">;
def err_unintialized_member : Error<
@@ -870,7 +870,8 @@ def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
def err_undeclared_use : Error<"use of undeclared '%0'">;
def warn_deprecated : Warning<"%0 is deprecated">,
InGroup<DiagGroup<"deprecated-declarations">>;
-def warn_unavailable : Warning<"%0 is unavailable">;
+def warn_unavailable : Warning<"%0 is unavailable">,
+ InGroup<DiagGroup<"unavailable-declarations">>;
def note_unavailable_here : Note<
"function has been explicitly marked %select{unavailable|deleted}0 here">;
def warn_not_enough_argument : Warning<
diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h
index 7d78087..2405c2f 100644
--- a/include/clang/Basic/SourceLocation.h
+++ b/include/clang/Basic/SourceLocation.h
@@ -145,10 +145,6 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) {
return LHS.getRawEncoding() < RHS.getRawEncoding();
}
-inline bool operator<=(const SourceLocation &LHS, const SourceLocation &RHS) {
- return LHS.getRawEncoding() <= RHS.getRawEncoding();
-}
-
/// SourceRange - a trival tuple used to represent a source range.
class SourceRange {
SourceLocation B;
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 5b57521..8c85ba6 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -637,18 +637,50 @@ public:
// Expression Parsing Callbacks.
//===--------------------------------------------------------------------===//
- /// \brief Notifies the action when the parser is processing an unevaluated
- /// operand.
+ /// \brief Describes how the expressions currently being parsed are
+ /// evaluated at run-time, if at all.
+ enum ExpressionEvaluationContext {
+ /// \brief The current expression and its subexpressions occur within an
+ /// unevaluated operand (C++0x [expr]p8), such as a constant expression
+ /// or the subexpression of \c sizeof, where the type or the value of the
+ /// expression may be significant but no code will be generated to evaluate
+ /// the value of the expression at run time.
+ Unevaluated,
+
+ /// \brief The current expression is potentially evaluated at run time,
+ /// which means that code may be generated to evaluate the value of the
+ /// expression at run time.
+ PotentiallyEvaluated,
+
+ /// \brief The current expression may be potentially evaluated or it may
+ /// be unevaluated, but it is impossible to tell from the lexical context.
+ /// This evaluation context is used primary for the operand of the C++
+ /// \c typeid expression, whose argument is potentially evaluated only when
+ /// it is an lvalue of polymorphic class type (C++ [basic.def.odr]p2).
+ PotentiallyPotentiallyEvaluated
+ };
+
+ /// \brief The parser is entering a new expression evaluation context.
///
- /// \param UnevaluatedOperand true to indicate that the parser is processing
- /// an unevaluated operand, or false otherwise.
+ /// \param NewContext is the new expression evaluation context.
///
- /// \returns whether the the action module was previously in an unevaluated
- /// operand.
- virtual bool setUnevaluatedOperand(bool UnevaluatedOperand) {
- return false;
+ /// \returns the previous expression evaluation context.
+ virtual ExpressionEvaluationContext
+ PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) {
+ return PotentiallyEvaluated;
}
+ /// \brief The parser is existing an expression evaluation context.
+ ///
+ /// \param OldContext the expression evaluation context that the parser is
+ /// leaving.
+ ///
+ /// \param NewContext the expression evaluation context that the parser is
+ /// returning to.
+ virtual void
+ PopExpressionEvaluationContext(ExpressionEvaluationContext OldContext,
+ ExpressionEvaluationContext NewContext) { }
+
// Primary Expressions.
/// \brief Retrieve the source range that corresponds to the given
@@ -1891,6 +1923,29 @@ public:
virtual void print(llvm::raw_ostream &OS) const;
};
+/// \brief RAII object that enters a new expression evaluation context.
+class EnterExpressionEvaluationContext {
+ /// \brief The action object.
+ Action &Actions;
+
+ /// \brief The previous expression evaluation context.
+ Action::ExpressionEvaluationContext PrevContext;
+
+ /// \brief The current expression evaluation context.
+ Action::ExpressionEvaluationContext CurContext;
+
+public:
+ EnterExpressionEvaluationContext(Action &Actions,
+ Action::ExpressionEvaluationContext NewContext)
+ : Actions(Actions), CurContext(NewContext) {
+ PrevContext = Actions.PushExpressionEvaluationContext(NewContext);
+ }
+
+ ~EnterExpressionEvaluationContext() {
+ Actions.PopExpressionEvaluationContext(CurContext, PrevContext);
+ }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index 75458d8..7558793 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -104,24 +104,6 @@ class Parser {
GreaterThanIsOperator = OldGreaterThanIsOperator;
}
};
-
- /// \brief RAII object that enters an unevaluated operand.
- class EnterUnevaluatedOperand {
- /// \brief The action object.
- Action &Actions;
-
- /// \brief Whether we were previously within an unevaluated operand.
- bool PreviouslyInUnevaluatedOperand;
-
- public:
- explicit EnterUnevaluatedOperand(Action &Actions) : Actions(Actions) {
- PreviouslyInUnevaluatedOperand = Actions.setUnevaluatedOperand(true);
- }
-
- ~EnterUnevaluatedOperand() {
- Actions.setUnevaluatedOperand(PreviouslyInUnevaluatedOperand);
- }
- };
public:
Parser(Preprocessor &PP, Action &Actions);
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())
diff --git a/test/CodeGen/functions.c b/test/CodeGen/functions.c
index 9855992..12dff1b 100644
--- a/test/CodeGen/functions.c
+++ b/test/CodeGen/functions.c
@@ -33,3 +33,7 @@ void f1() {}
// RUN: grep 'define .* @f3' %t | not grep -F '...'
struct foo { int X, Y, Z; } f3() {
}
+
+// PR4423 - This shouldn't crash in codegen
+void f4() {}
+void f5() { f4(42); }
diff --git a/test/CodeGenCXX/implicit-instantiation-1.cpp b/test/CodeGenCXX/implicit-instantiation-1.cpp
new file mode 100644
index 0000000..f6c6114
--- /dev/null
+++ b/test/CodeGenCXX/implicit-instantiation-1.cpp
@@ -0,0 +1,29 @@
+// RUN: clang-cc -emit-llvm %s -o %t &&
+
+template<typename T>
+struct X {
+ void f(T) { }
+ void f(char) { }
+
+ void g(T) { }
+
+ void h(T) { }
+};
+
+void foo(X<int> &xi, X<float> *xfp, int i, float f) {
+ // RUN: grep "linkonce_odr.*_ZN1XIiE1fEi" %t | count 1 &&
+ xi.f(i);
+
+ // RUN: grep "linkonce_odr.*_ZN1XIiE1gEi" %t | count 1 &&
+ xi.g(f);
+
+ // RUN: grep "linkonce_odr.*_ZN1XIfE1fEf" %t | count 1 &&
+ xfp->f(f);
+
+ // RUN: grep "linkonce_odr.*_ZN1XIfE1hEf" %t | count 0 &&
+
+ // RUN: true
+}
+
+
+
diff --git a/test/SemaCXX/default-constructor-initializers.cpp b/test/SemaCXX/default-constructor-initializers.cpp
index c5250f8..24c53839 100644
--- a/test/SemaCXX/default-constructor-initializers.cpp
+++ b/test/SemaCXX/default-constructor-initializers.cpp
@@ -11,7 +11,7 @@ struct X2 : X1 { // expected-note {{'struct X2' declared here}} \
struct X3 : public X2 {
};
-X3 x3; // expected-error {{cannot define the default constructor for 'struct X3', because member 'struct X2' does not have any implicit default constructor}}
+X3 x3; // expected-error {{cannot define the implicit default constructor for 'struct X3', because member 'struct X2' does not have any default constructor}}
struct X4 {
@@ -19,7 +19,7 @@ struct X4 {
X2 & rx2; // expected-note {{declared at}}
};
-X4 x4; // expected-error {{cannot define the default constructor for 'struct X4', because base class 'struct X2' does not have any implicit default constructor}} \
+X4 x4; // expected-error {{cannot define the implicit default constructor for 'struct X4', because base class 'struct X2' does not have any default constructor}} \
// expected-error {{cannot define the implicit default constructor for 'struct X4', because reference member rx2 cannot be default-initialized}}
diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp
index c812677..d2e90c1 100644
--- a/test/SemaTemplate/class-template-decl.cpp
+++ b/test/SemaTemplate/class-template-decl.cpp
@@ -35,6 +35,12 @@ template<typename> class TemplateTemplateParm; // expected-error{{template param
template<template<typename T, int> class X> class TemplateTemplateParm; // expected-error{{too many template parameters in template template parameter redeclaration}}
+template<typename T>
+struct test {}; // expected-note{{previous definition}}
+
+template<typename T>
+struct test : T {}; // expected-error{{redefinition}}
+
#if 0
// FIXME: parse template declarations in these scopes, so that we can
// complain about the one at function scope.
diff --git a/test/SemaTemplate/example-dynarray.cpp b/test/SemaTemplate/example-dynarray.cpp
index cca3709..680ee04 100644
--- a/test/SemaTemplate/example-dynarray.cpp
+++ b/test/SemaTemplate/example-dynarray.cpp
@@ -89,6 +89,21 @@ public:
iterator end() { return Last; }
const_iterator end() const { return Last; }
+ bool operator==(const dynarray &other) const {
+ if (size() != other.size())
+ return false;
+
+ for (unsigned I = 0, N = size(); I != N; ++I)
+ if ((*this)[I] != other[I])
+ return false;
+
+ return true;
+ }
+
+ bool operator!=(const dynarray &other) const {
+ return !(*this == other);
+ }
+
public:
T* Start, *Last, *End;
};
@@ -100,11 +115,6 @@ struct Point {
float x, y, z;
};
-// FIXME: remove these when we have implicit instantiation for member
-// functions of class templates.
-template class dynarray<int>;
-template class dynarray<Point>;
-
int main() {
dynarray<int> di;
di.push_back(0);
@@ -146,5 +156,13 @@ int main() {
I != IEnd; ++I)
assert(*I == I - di4.begin());
+ assert(di4 == di);
+ di4[3] = 17;
+ assert(di4 != di);
+
+ dynarray<Point> dp;
+ dp.push_back(Point());
+ assert(dp.size() == 1);
+
return 0;
}
diff --git a/test/SemaTemplate/implicit-instantiation-1.cpp b/test/SemaTemplate/implicit-instantiation-1.cpp
new file mode 100644
index 0000000..eecaf2f
--- /dev/null
+++ b/test/SemaTemplate/implicit-instantiation-1.cpp
@@ -0,0 +1,16 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+template<typename T, typename U>
+struct X {
+ T f(T x, U y) { return x + y; }
+
+ unsigned g(T x, U y) { return sizeof(f(x, y)); }
+};
+
+void test(X<int, int> *xii, X<int*, int> *xpi, X<int, int*> *xip) {
+ (void)xii->f(1, 2);
+ (void)xpi->f(0, 2);
+ (void)sizeof(xip->f(2, 0)); // okay: does not instantiate
+ (void)xip->g(2, 0); // okay: does not instantiate
+}
+
OpenPOWER on IntegriCloud