diff options
author | Ed Schouten <ed@FreeBSD.org> | 2009-06-23 14:50:21 +0000 |
---|---|---|
committer | Ed Schouten <ed@FreeBSD.org> | 2009-06-23 14:50:21 +0000 |
commit | d6aff018d446f22be4e4e0277080ebfa5b157288 (patch) | |
tree | 64b43af65e97f7659637c9ac028e39af2e26b841 | |
parent | b897c8660c4ff7037dde81b9645737bc1c992abe (diff) |
Import Clang r73954.vendor/clang/clang-r73954
Notes
Notes:
svn path=/vendor/clang/dist/; revision=194711
svn path=/vendor/clang/clang-r73954/; revision=194713; tag=vendor/clang/clang-r73954
55 files changed, 1265 insertions, 835 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 77b7bf6a9520..f594db27bc8f 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 9ca1823f3822..52ed0ec8535e 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 af06965f84e9..2608dd9d3157 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 0fc49f5a586e..6f8a12642769 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 4af8a7c845a7..5db666c4b83f 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 6f95c6ff4ab0..2cb3f9470cf0 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 8afcc4c2414f..ac158dc88f5c 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 c9d1e25da789..de74dbdb17b0 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 b86f4e875304..d8e557f76036 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 ae5246d7929a..9c439851b182 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 755cfce4d85b..79a9efac8554 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 7d78087d9db5..2405c2fe7db7 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 5b57521f6751..8c85ba60ac2e 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 75458d821e8e..75587936065b 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 bf63932011a2..71e88a9efc49 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 7a930d78c123..25e4d1961778 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 23c26378757f..165672d50f4e 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 fcb405d2d20d..6b346cd52557 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 c58ceb419324..1ccd0924f378 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 7ada6d809bd4..2b751df830c2 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 87432d4815a8..d5f0e406bb7c 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 7f7270d40d64..13df89ebbfdc 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 7e54f1ad6866..480612113d10 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 9e11a263536d..9bd93cd6eb9c 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 5f2b8f809de3..f76807beb29e 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 77c3c8f7722a..dd9490bebb96 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 000000000000..724a2e92d744 --- /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 8dfc5d100e85..23a01c953a46 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 13758ad18308..1d69e4e96efa 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 ec6058afd963..30c5d28c227e 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 41908ad00e49..730414e44822 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 81f75bdf755c..c8fd5f6fcbc0 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 c2ffd6d4339e..81ea606f0d9f 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 69152523a112..426f56f4380e 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 4a07d05650bd..13b32acd5b29 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 87aa5dc67116..2be44a4e77a0 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 a9f75d8be17d..eabe10f1450e 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 e756b41b12f5..c37f66dae907 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 560f952bffa5..8604fe56a278 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 06fd1a17362a..eba1d58d6024 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 6d740eb5b7ec..c9c662671c1f 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 692502bbbe81..56d3bfe690bf 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 bec595ca9cf9..a567218eaa88 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 fb41b2b7536f..e98ebb13f811 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 784e451804aa..de3e52df3763 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 3992f8cbe536..1c4e907d4d6f 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 6d7dc2e6d531..ece71bc0d326 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 bf19701d6bed..749fb5894878 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 efdcec81afff..565b95b329f7 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 985599216e1c..12dff1b72cbc 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 000000000000..f6c6114d20c3 --- /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 c5250f8912cc..24c53839622c 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 c81267771297..d2e90c1daa8f 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 cca3709bebbf..680ee04ba18e 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 000000000000..eecaf2f6c799 --- /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 +} + |