diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2010-04-02 08:55:10 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2010-04-02 08:55:10 +0000 |
commit | 11d2b2d2bb706fca0656f2760839721bb7f6cb6f (patch) | |
tree | d374cdca417e76f1bf101f139dba2db1d10ee8f7 /include | |
parent | c0c7bca4e5b8d12699dc93a0da49e9e4bb79671b (diff) | |
download | src-11d2b2d2bb706fca0656f2760839721bb7f6cb6f.tar.gz src-11d2b2d2bb706fca0656f2760839721bb7f6cb6f.zip |
Update clang to r100181.
Notes
Notes:
svn path=/vendor/clang/dist/; revision=206084
Diffstat (limited to 'include')
58 files changed, 1165 insertions, 461 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index e77dcf86cca6..c41857ec0200 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -17,6 +17,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" @@ -57,6 +58,7 @@ namespace clang { class ObjCIvarRefExpr; class ObjCPropertyDecl; class RecordDecl; + class StoredDeclsMap; class TagDecl; class TemplateTypeParmDecl; class TranslationUnitDecl; @@ -115,7 +117,7 @@ class ASTContext { llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes; llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes; - llvm::FoldingSet<TypenameType> TypenameTypes; + llvm::FoldingSet<DependentNameType> DependentNameTypes; llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes; llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; llvm::FoldingSet<ElaboratedType> ElaboratedTypes; @@ -264,6 +266,9 @@ class ASTContext { llvm::MallocAllocator MallocAlloc; llvm::BumpPtrAllocator BumpAlloc; + /// \brief Allocator for partial diagnostics. + PartialDiagnostic::StorageAllocator DiagAllocator; + public: const TargetInfo &Target; IdentifierTable &Idents; @@ -289,6 +294,11 @@ public: if (FreeMemory) MallocAlloc.Deallocate(Ptr); } + + PartialDiagnostic::StorageAllocator &getDiagAllocator() { + return DiagAllocator; + } + const LangOptions& getLangOptions() const { return LangOpts; } FullSourceLoc getFullLoc(SourceLocation Loc) const { @@ -437,6 +447,11 @@ public: /// allowable type. QualType getCallConvType(QualType T, CallingConv CallConv); + /// getRegParmType - Sets the specified regparm attribute to + /// the given type, which must be a FunctionType or a pointer to an + /// allowable type. + QualType getRegParmType(QualType T, unsigned RegParm); + /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T); @@ -554,8 +569,12 @@ public: /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'. /// - QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false, - CallingConv CallConv = CC_Default); + QualType getFunctionNoProtoType(QualType ResultTy, + const FunctionType::ExtInfo &Info); + + QualType getFunctionNoProtoType(QualType ResultTy) { + return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo()); + } /// getFunctionType - Return a normal function type with a typed argument /// list. isVariadic indicates whether the argument list includes '...'. @@ -564,8 +583,7 @@ public: unsigned TypeQuals, bool hasExceptionSpec, bool hasAnyExceptionSpec, unsigned NumExs, const QualType *ExArray, - bool NoReturn, - CallingConv CallConv); + const FunctionType::ExtInfo &Info); /// getTypeDeclType - Return the unique reference to the type for /// the specified type declaration. @@ -612,12 +630,14 @@ public: QualType getQualifiedNameType(NestedNameSpecifier *NNS, QualType NamedType); - QualType getTypenameType(NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - QualType Canon = QualType()); - QualType getTypenameType(NestedNameSpecifier *NNS, - const TemplateSpecializationType *TemplateId, - QualType Canon = QualType()); + QualType getDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + QualType Canon = QualType()); + QualType getDependentNameType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const TemplateSpecializationType *TemplateId, + QualType Canon = QualType()); QualType getElaboratedType(QualType UnderlyingType, ElaboratedType::TagKind Tag); @@ -937,8 +957,7 @@ public: llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); void CollectNonClassIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); - unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI); - unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD); + unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI); void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); @@ -1273,9 +1292,8 @@ private: // FIXME: This currently contains the set of StoredDeclMaps used // by DeclContext objects. This probably should not be in ASTContext, // but we include it here so that ASTContext can quickly deallocate them. - std::vector<void*> SDMs; + llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM; friend class DeclContext; - void *CreateStoredDeclsMap(); void ReleaseDeclContextMaps(); }; diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index c89e5e4b167a..edd633e8e140 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -19,6 +19,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" #include "clang/AST/TypeOrdering.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include <list> #include <map> @@ -227,6 +228,137 @@ public: /// object. void swap(CXXBasePaths &Other); }; + +/// \brief Uniquely identifies a virtual method within a class +/// hierarchy by the method itself and a class subobject number. +struct UniqueVirtualMethod { + UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { } + + UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject, + const CXXRecordDecl *InVirtualSubobject) + : Method(Method), Subobject(Subobject), + InVirtualSubobject(InVirtualSubobject) { } + + /// \brief The overriding virtual method. + CXXMethodDecl *Method; + + /// \brief The subobject in which the overriding virtual method + /// resides. + unsigned Subobject; + + /// \brief The virtual base class subobject of which this overridden + /// virtual method is a part. Note that this records the closest + /// derived virtual base class subobject. + const CXXRecordDecl *InVirtualSubobject; + + friend bool operator==(const UniqueVirtualMethod &X, + const UniqueVirtualMethod &Y) { + return X.Method == Y.Method && X.Subobject == Y.Subobject && + X.InVirtualSubobject == Y.InVirtualSubobject; + } + + friend bool operator!=(const UniqueVirtualMethod &X, + const UniqueVirtualMethod &Y) { + return !(X == Y); + } +}; + +/// \brief The set of methods that override a given virtual method in +/// each subobject where it occurs. +/// +/// The first part of the pair is the subobject in which the +/// overridden virtual function occurs, while the second part of the +/// pair is the virtual method that overrides it (including the +/// subobject in which that virtual function occurs). +class OverridingMethods { + llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> > + Overrides; + +public: + // Iterate over the set of subobjects that have overriding methods. + typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> > + ::iterator iterator; + typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> > + ::const_iterator const_iterator; + iterator begin() { return Overrides.begin(); } + const_iterator begin() const { return Overrides.begin(); } + iterator end() { return Overrides.end(); } + const_iterator end() const { return Overrides.end(); } + unsigned size() const { return Overrides.size(); } + + // Iterate over the set of overriding virtual methods in a given + // subobject. + typedef llvm::SmallVector<UniqueVirtualMethod, 4>::iterator + overriding_iterator; + typedef llvm::SmallVector<UniqueVirtualMethod, 4>::const_iterator + overriding_const_iterator; + + // Add a new overriding method for a particular subobject. + void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding); + + // Add all of the overriding methods from "other" into overrides for + // this method. Used when merging the overrides from multiple base + // class subobjects. + void add(const OverridingMethods &Other); + + // Replace all overriding virtual methods in all subobjects with the + // given virtual method. + void replaceAll(UniqueVirtualMethod Overriding); +}; + +/// \brief A mapping from each virtual member function to its set of +/// final overriders. +/// +/// Within a class hierarchy for a given derived class, each virtual +/// member function in that hierarchy has one or more "final +/// overriders" (C++ [class.virtual]p2). A final overrider for a +/// virtual function "f" is the virtual function that will actually be +/// invoked when dispatching a call to "f" through the +/// vtable. Well-formed classes have a single final overrider for each +/// virtual function; in abstract classes, the final overrider for at +/// least one virtual function is a pure virtual function. Due to +/// multiple, virtual inheritance, it is possible for a class to have +/// more than one final overrider. Athough this is an error (per C++ +/// [class.virtual]p2), it is not considered an error here: the final +/// overrider map can represent multiple final overriders for a +/// method, and it is up to the client to determine whether they are +/// problem. For example, the following class \c D has two final +/// overriders for the virtual function \c A::f(), one in \c C and one +/// in \c D: +/// +/// \code +/// struct A { virtual void f(); }; +/// struct B : virtual A { virtual void f(); }; +/// struct C : virtual A { virtual void f(); }; +/// struct D : B, C { }; +/// \endcode +/// +/// This data structure contaings a mapping from every virtual +/// function *that does not override an existing virtual function* and +/// in every subobject where that virtual function occurs to the set +/// of virtual functions that override it. Thus, the same virtual +/// function \c A::f can actually occur in multiple subobjects of type +/// \c A due to multiple inheritance, and may be overriden by +/// different virtual functions in each, as in the following example: +/// +/// \code +/// struct A { virtual void f(); }; +/// struct B : A { virtual void f(); }; +/// struct C : A { virtual void f(); }; +/// struct D : B, C { }; +/// \endcode +/// +/// Unlike in the previous example, where the virtual functions \c +/// B::f and \c C::f both overrode \c A::f in the same subobject of +/// type \c A, in this example the two virtual functions both override +/// \c A::f but in *different* subobjects of type A. This is +/// represented by numbering the subobjects in which the overridden +/// and the overriding virtual member functions are located. Subobject +/// 0 represents the virtua base class subobject of that type, while +/// subobject numbers greater than 0 refer to non-virtual base class +/// subobjects of that type. +class CXXFinalOverriderMap + : public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { }; } // end namespace clang diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 1f459b08ca78..b2a87f617063 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -165,6 +165,8 @@ public: // (dynamic) type. static CanQual<T> CreateUnsafe(QualType Other); + void dump() const { Stored.dump(); } + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddPointer(getAsOpaquePtr()); } @@ -562,24 +564,21 @@ struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> { template<> struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) }; template<> struct CanProxyAdaptor<FunctionNoProtoType> : public CanProxyBase<FunctionNoProtoType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) }; template<> struct CanProxyAdaptor<FunctionProtoType> : public CanProxyBase<FunctionProtoType> { LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs) CanQualType getArgType(unsigned i) const { return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i)); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index e23811d8f9c0..2cdb98351394 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -224,18 +224,26 @@ class NamespaceDecl : public NamedDecl, public DeclContext { // NextNamespace points to the next extended declaration. // OrigNamespace points to the original namespace declaration. // OrigNamespace of the first namespace decl points to itself. - NamespaceDecl *OrigNamespace, *NextNamespace; + NamespaceDecl *NextNamespace; - // The (most recently entered) anonymous namespace inside this - // namespace. - NamespaceDecl *AnonymousNamespace; + /// \brief A pointer to either the original namespace definition for + /// this namespace (if the boolean value is false) or the anonymous + /// namespace that lives just inside this namespace (if the boolean + /// value is true). + /// + /// We can combine these two notions because the anonymous namespace + /// must only be stored in one of the namespace declarations (so all + /// of the namespace declarations can find it). We therefore choose + /// the original namespace declaration, since all of the namespace + /// declarations have a link directly to it; the original namespace + /// declaration itself only needs to know that it is the original + /// namespace declaration (which the boolean indicates). + llvm::PointerIntPair<NamespaceDecl *, 1, bool> OrigOrAnonNamespace; NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) - : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) { - OrigNamespace = this; - NextNamespace = 0; - AnonymousNamespace = 0; - } + : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), + NextNamespace(0), OrigOrAnonNamespace(0, true) { } + public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); @@ -258,22 +266,33 @@ public: void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } NamespaceDecl *getOriginalNamespace() const { - return OrigNamespace; + if (OrigOrAnonNamespace.getInt()) + return const_cast<NamespaceDecl *>(this); + + return OrigOrAnonNamespace.getPointer(); + } + + void setOriginalNamespace(NamespaceDecl *ND) { + if (ND != this) { + OrigOrAnonNamespace.setPointer(ND); + OrigOrAnonNamespace.setInt(false); + } } - void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; } NamespaceDecl *getAnonymousNamespace() const { - return AnonymousNamespace; + return getOriginalNamespace()->OrigOrAnonNamespace.getPointer(); } void setAnonymousNamespace(NamespaceDecl *D) { assert(!D || D->isAnonymousNamespace()); assert(!D || D->getParent() == this); - AnonymousNamespace = D; + getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); } - virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; } - const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; } + virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); } + const NamespaceDecl *getCanonicalDecl() const { + return getOriginalNamespace(); + } virtual SourceRange getSourceRange() const { return SourceRange(getLocation(), RBracLoc); @@ -1819,12 +1838,12 @@ class RecordDecl : public TagDecl { /// If so, this cannot be contained in arrays or other structs as a member. bool HasFlexibleArrayMember : 1; - /// AnonymousStructOrUnion - Whether this is the type of an - /// anonymous struct or union. + /// AnonymousStructOrUnion - Whether this is the type of an anonymous struct + /// or union. bool AnonymousStructOrUnion : 1; - /// HasObjectMember - This is true if this struct has at least one - /// member containing an object + /// HasObjectMember - This is true if this struct has at least one member + /// containing an object. bool HasObjectMember : 1; protected: diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 6f8284458f2b..d5913e236c2c 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -41,6 +41,8 @@ class LinkageSpecDecl; class BlockDecl; class DeclarationName; class CompoundStmt; +class StoredDeclsMap; +class DependentDiagnostic; } namespace llvm { @@ -450,15 +452,23 @@ public: /// same entity may not (and probably don't) share this property. void setObjectOfFriendDecl(bool PreviouslyDeclared) { unsigned OldNS = IdentifierNamespace; - assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary || - OldNS == (IDNS_Tag | IDNS_Ordinary)) - && "unsupported namespace for undeclared friend"); - if (!PreviouslyDeclared) IdentifierNamespace = 0; - - if (OldNS == IDNS_Tag) + assert((OldNS & (IDNS_Tag | IDNS_Ordinary | + IDNS_TagFriend | IDNS_OrdinaryFriend)) && + "namespace includes neither ordinary nor tag"); + assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | + IDNS_TagFriend | IDNS_OrdinaryFriend)) && + "namespace includes other than ordinary or tag"); + + IdentifierNamespace = 0; + if (OldNS & (IDNS_Tag | IDNS_TagFriend)) { IdentifierNamespace |= IDNS_TagFriend; - else + if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag; + } + + if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) { IdentifierNamespace |= IDNS_OrdinaryFriend; + if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary; + } } enum FriendObjectKind { @@ -545,9 +555,9 @@ class DeclContext { mutable bool ExternalVisibleStorage : 1; /// \brief Pointer to the data structure used to lookup declarations - /// within this context, which is a DenseMap<DeclarationName, - /// StoredDeclsList>. - mutable void* LookupPtr; + /// within this context (or a DependentStoredDeclsMap if this is a + /// dependent context). + mutable StoredDeclsMap *LookupPtr; /// FirstDecl - The first declaration stored within this declaration /// context. @@ -674,6 +684,9 @@ public: /// "primary" DeclContext structure, which will contain the /// information needed to perform name lookup into this context. DeclContext *getPrimaryContext(); + const DeclContext *getPrimaryContext() const { + return const_cast<DeclContext*>(this)->getPrimaryContext(); + } /// getLookupContext - Retrieve the innermost non-transparent /// context of this context, which corresponds to the innermost @@ -976,10 +989,15 @@ public: return getUsingDirectives().second; } + // These are all defined in DependentDiagnostic.h. + class ddiag_iterator; + inline ddiag_iterator ddiag_begin() const; + inline ddiag_iterator ddiag_end() const; + // Low-level accessors /// \brief Retrieve the internal representation of the lookup structure. - void* getLookupPtr() const { return LookupPtr; } + StoredDeclsMap* getLookupPtr() const { return LookupPtr; } /// \brief Whether this DeclContext has external storage containing /// additional declarations that are lexically in this context. @@ -1013,6 +1031,9 @@ private: void LoadLexicalDeclsFromExternalStorage() const; void LoadVisibleDeclsFromExternalStorage() const; + friend class DependentDiagnostic; + StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; + void buildLookup(DeclContext *DCtx); void makeDeclVisibleInContextImpl(NamedDecl *D); }; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 6b04ed54109a..23769af46b36 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -33,6 +33,7 @@ class CXXDestructorDecl; class CXXMethodDecl; class CXXRecordDecl; class CXXMemberLookupCriteria; +class CXXFinalOverriderMap; class FriendDecl; /// \brief Represents any kind of function declaration, whether it is a @@ -328,6 +329,10 @@ class CXXRecordDecl : public RecordDecl { /// instantiated or specialized. llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*> TemplateOrInstantiation; + +#ifndef NDEBUG + void CheckConversionFunction(NamedDecl *D); +#endif protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, @@ -549,17 +554,26 @@ public: return getConversionFunctions()->replace(Old, New); } + /// Removes a conversion function from this class. The conversion + /// function must currently be a member of this class. Furthermore, + /// this class must currently be in the process of being defined. + void removeConversion(const NamedDecl *Old); + /// getVisibleConversionFunctions - get all conversion functions visible /// in current class; including conversion function templates. const UnresolvedSetImpl *getVisibleConversionFunctions(); - /// addConversionFunction - Add a new conversion function to the - /// list of conversion functions. - void addConversionFunction(CXXConversionDecl *ConvDecl); + /// addConversionFunction - Registers a conversion function which + /// this class declares directly. + void addConversionFunction(NamedDecl *Decl) { +#ifndef NDEBUG + CheckConversionFunction(Decl); +#endif - /// \brief Add a new conversion function template to the list of conversion - /// functions. - void addConversionFunction(FunctionTemplateDecl *ConvDecl); + // We intentionally don't use the decl's access here because it + // hasn't been set yet. That's really just a misdesign in Sema. + data().Conversions.addDecl(Decl); + } /// isAggregate - Whether this class is an aggregate (C++ /// [dcl.init.aggr]), which is a class with no user-declared @@ -879,7 +893,12 @@ public: static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData); - + + /// \brief Retrieve the final overriders for each virtual member + /// function in the class hierarchy where this class is the + /// most-derived class in the class hierarchy. + void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const; + /// viewInheritance - Renders and displays an inheritance diagram /// for this C++ class and all of its base classes (transitively) using /// GraphViz. @@ -935,7 +954,7 @@ public: return (CD->begin_overridden_methods() != CD->end_overridden_methods()); } - + /// \brief Determine whether this is a usual deallocation function /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded /// delete or delete[] operator with a particular signature. diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 32405ee81260..16cb491344bc 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -24,6 +24,8 @@ namespace clang { +class DependentDiagnostic; + /// StoredDeclsList - This is an array of decls optimized a common case of only /// containing one entry. struct StoredDeclsList { @@ -258,8 +260,28 @@ public: } }; -typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap; +class StoredDeclsMap + : public llvm::DenseMap<DeclarationName, StoredDeclsList> { + +public: + static void DestroyAll(StoredDeclsMap *Map, bool Dependent); + +private: + friend class ASTContext; // walks the chain deleting these + friend class DeclContext; + llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; +}; +class DependentStoredDeclsMap : public StoredDeclsMap { +public: + DependentStoredDeclsMap() : FirstDiagnostic(0) {} + +private: + friend class DependentDiagnostic; + friend class DeclContext; // iterates over diagnostics + + DependentDiagnostic *FirstDiagnostic; +}; } // end namespace clang diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 5022ad018f4f..99ef738980cc 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -36,7 +36,7 @@ namespace clang { /// The semantic context of a friend decl is its declaring class. class FriendDecl : public Decl { public: - typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion; + typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; private: // The declaration that's a friend of this class. @@ -73,8 +73,8 @@ public: /// possibly dependent) type, return the type; otherwise /// return null. This is used only for C++0x's unelaborated /// friend type declarations. - Type *getFriendType() const { - return Friend.dyn_cast<Type*>(); + TypeSourceInfo *getFriendType() const { + return Friend.dyn_cast<TypeSourceInfo*>(); } /// If this friend declaration doesn't name an unelaborated diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 560ce46ede7c..8d1a4caccb23 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -1238,7 +1238,7 @@ public: /// template <typename U> friend class Foo<T>::Nested; // friend template class FriendTemplateDecl : public Decl { public: - typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion; + typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion; private: // The number of template parameters; always non-zero. @@ -1277,8 +1277,8 @@ public: /// If this friend declaration names a templated type (or /// a dependent member type of a templated type), return that /// type; otherwise return null. - Type *getFriendType() const { - return Friend.dyn_cast<Type*>(); + TypeSourceInfo *getFriendType() const { + return Friend.dyn_cast<TypeSourceInfo*>(); } /// If this friend declaration names a templated function (or diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 2254724410d0..6225069c602f 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -378,7 +378,7 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, Diagnostic::ak_declarationname); return PD; } - + } // end namespace clang namespace llvm { diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h new file mode 100644 index 000000000000..1954a282e802 --- /dev/null +++ b/include/clang/AST/DependentDiagnostic.h @@ -0,0 +1,183 @@ +//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- 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 interfaces for diagnostics which may or may +// fire based on how a template is instantiated. +// +// At the moment, the only consumer of this interface is access +// control. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H +#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H + +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclContextInternals.h" + +namespace clang { + +class ASTContext; +class CXXRecordDecl; +class NamedDecl; + +/// A dependently-generated diagnostic. +class DependentDiagnostic { +public: + enum AccessNonce { Access = 0 }; + + static DependentDiagnostic *Create(ASTContext &Context, + DeclContext *Parent, + AccessNonce _, + SourceLocation Loc, + bool IsMemberAccess, + AccessSpecifier AS, + NamedDecl *TargetDecl, + CXXRecordDecl *NamingClass, + const PartialDiagnostic &PDiag) { + DependentDiagnostic *DD = Create(Context, Parent, PDiag); + DD->AccessData.Loc = Loc.getRawEncoding(); + DD->AccessData.IsMember = IsMemberAccess; + DD->AccessData.Access = AS; + DD->AccessData.TargetDecl = TargetDecl; + DD->AccessData.NamingClass = NamingClass; + return DD; + } + + unsigned getKind() const { + return Access; + } + + bool isAccessToMember() const { + assert(getKind() == Access); + return AccessData.IsMember; + } + + AccessSpecifier getAccess() const { + assert(getKind() == Access); + return AccessSpecifier(AccessData.Access); + } + + SourceLocation getAccessLoc() const { + assert(getKind() == Access); + return SourceLocation::getFromRawEncoding(AccessData.Loc); + } + + NamedDecl *getAccessTarget() const { + assert(getKind() == Access); + return AccessData.TargetDecl; + } + + NamedDecl *getAccessNamingClass() const { + assert(getKind() == Access); + return AccessData.NamingClass; + } + + const PartialDiagnostic &getDiagnostic() const { + return Diag; + } + +private: + DependentDiagnostic(const PartialDiagnostic &PDiag, + PartialDiagnostic::Storage *Storage) + : Diag(PDiag, Storage) {} + + static DependentDiagnostic *Create(ASTContext &Context, + DeclContext *Parent, + const PartialDiagnostic &PDiag); + + friend class DependentStoredDeclsMap; + friend class DeclContext::ddiag_iterator; + DependentDiagnostic *NextDiagnostic; + + PartialDiagnostic Diag; + + union { + struct { + unsigned Loc; + unsigned Access : 2; + unsigned IsMember : 1; + NamedDecl *TargetDecl; + CXXRecordDecl *NamingClass; + } AccessData; + }; +}; + +/// + +/// An iterator over the dependent diagnostics in a dependent context. +class DeclContext::ddiag_iterator { +public: + ddiag_iterator() : Ptr(0) {} + explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {} + + typedef DependentDiagnostic *value_type; + typedef DependentDiagnostic *reference; + typedef DependentDiagnostic *pointer; + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + + reference operator*() const { return Ptr; } + + ddiag_iterator &operator++() { + assert(Ptr && "attempt to increment past end of diag list"); + Ptr = Ptr->NextDiagnostic; + return *this; + } + + ddiag_iterator operator++(int) { + ddiag_iterator tmp = *this; + ++*this; + return tmp; + } + + bool operator==(ddiag_iterator Other) const { + return Ptr == Other.Ptr; + } + + bool operator!=(ddiag_iterator Other) const { + return Ptr != Other.Ptr; + } + + ddiag_iterator &operator+=(difference_type N) { + assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator"); + while (N--) + ++*this; + return *this; + } + + ddiag_iterator operator+(difference_type N) const { + ddiag_iterator tmp = *this; + tmp += N; + return tmp; + } + +private: + DependentDiagnostic *Ptr; +}; + +inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const { + assert(isDependentContext() + && "cannot iterate dependent diagnostics of non-dependent context"); + const DependentStoredDeclsMap *Map + = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->LookupPtr); + + if (!Map) return ddiag_iterator(); + return ddiag_iterator(Map->FirstDiagnostic); +} + +inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const { + return ddiag_iterator(); +} + +} + +#endif diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6b14e47cbef5..507a61c6d7a6 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1263,6 +1263,11 @@ public: /// MemberExpr - [C99 6.5.2.3] Structure and Union Members. X->F and X.F. /// class MemberExpr : public Expr { + /// Extra data stored in some member expressions. + struct MemberNameQualifier : public NameQualifier { + NamedDecl *FoundDecl; + }; + /// Base - the expression for the base pointer or structure references. In /// X.F, this is "X". Stmt *Base; @@ -1278,27 +1283,26 @@ class MemberExpr : public Expr { bool IsArrow : 1; /// \brief True if this member expression used a nested-name-specifier to - /// refer to the member, e.g., "x->Base::f". When true, a NameQualifier + /// refer to the member, e.g., "x->Base::f", or found its member via a using + /// declaration. When true, a MemberNameQualifier /// structure is allocated immediately after the MemberExpr. - bool HasQualifier : 1; + bool HasQualifierOrFoundDecl : 1; /// \brief True if this member expression specified a template argument list /// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList /// structure (and its TemplateArguments) are allocated immediately after /// the MemberExpr or, if the member expression also has a qualifier, after - /// the NameQualifier structure. + /// the MemberNameQualifier structure. bool HasExplicitTemplateArgumentList : 1; /// \brief Retrieve the qualifier that preceded the member name, if any. - NameQualifier *getMemberQualifier() { - if (!HasQualifier) - return 0; - - return reinterpret_cast<NameQualifier *> (this + 1); + MemberNameQualifier *getMemberQualifier() { + assert(HasQualifierOrFoundDecl); + return reinterpret_cast<MemberNameQualifier *> (this + 1); } /// \brief Retrieve the qualifier that preceded the member name, if any. - const NameQualifier *getMemberQualifier() const { + const MemberNameQualifier *getMemberQualifier() const { return const_cast<MemberExpr *>(this)->getMemberQualifier(); } @@ -1308,7 +1312,7 @@ class MemberExpr : public Expr { if (!HasExplicitTemplateArgumentList) return 0; - if (!HasQualifier) + if (!HasQualifierOrFoundDecl) return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); return reinterpret_cast<ExplicitTemplateArgumentList *>( @@ -1321,26 +1325,22 @@ class MemberExpr : public Expr { return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList(); } - MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, - SourceRange qualrange, ValueDecl *memberdecl, SourceLocation l, - const TemplateArgumentListInfo *targs, QualType ty); - public: MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, SourceLocation l, QualType ty) : Expr(MemberExprClass, ty, base->isTypeDependent(), base->isValueDependent()), Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), - HasQualifier(false), HasExplicitTemplateArgumentList(false) {} + HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} /// \brief Build an empty member reference expression. explicit MemberExpr(EmptyShell Empty) - : Expr(MemberExprClass, Empty), HasQualifier(false), + : Expr(MemberExprClass, Empty), HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) { } static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, - ValueDecl *memberdecl, + ValueDecl *memberdecl, NamedDecl *founddecl, SourceLocation l, const TemplateArgumentListInfo *targs, QualType ty); @@ -1355,16 +1355,23 @@ public: ValueDecl *getMemberDecl() const { return MemberDecl; } void setMemberDecl(ValueDecl *D) { MemberDecl = D; } + /// \brief Retrieves the declaration found by lookup. + NamedDecl *getFoundDecl() const { + if (!HasQualifierOrFoundDecl) + return getMemberDecl(); + return getMemberQualifier()->FoundDecl; + } + /// \brief Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. - bool hasQualifier() const { return HasQualifier; } + bool hasQualifier() const { return getQualifier() != 0; } /// \brief If the member name was qualified, retrieves the source range of /// the nested-name-specifier that precedes the member name. Otherwise, /// returns an empty source range. SourceRange getQualifierRange() const { - if (!HasQualifier) + if (!HasQualifierOrFoundDecl) return SourceRange(); return getMemberQualifier()->Range; @@ -1374,7 +1381,7 @@ public: /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. NestedNameSpecifier *getQualifier() const { - if (!HasQualifier) + if (!HasQualifierOrFoundDecl) return 0; return getMemberQualifier()->NNS; @@ -1545,6 +1552,10 @@ public: /// CK_DerivedToBase - Derived to base class casts. CK_DerivedToBase, + /// CK_UncheckedDerivedToBase - Derived to base class casts that + /// assume that the derived pointer is not null. + CK_UncheckedDerivedToBase, + /// CK_Dynamic - Dynamic cast. CK_Dynamic, diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index d1351b8b1447..6e2e832e3542 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1095,8 +1095,8 @@ public: : Expr(CXXPseudoDestructorExprClass, Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0, false, 0, false, - false, 0, 0, false, - CC_Default)), + false, 0, 0, + FunctionType::ExtInfo())), /*isTypeDependent=*/(Base->isTypeDependent() || (DestroyedType.getTypeSourceInfo() && DestroyedType.getTypeSourceInfo()->getType()->isDependentType())), diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 111be5562199..72793651c4be 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -17,6 +17,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Linkage.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" #include "llvm/Support/Casting.h" @@ -678,14 +679,6 @@ public: return getObjCGCAttr() == Qualifiers::Strong; } - /// getNoReturnAttr - Returns true if the type has the noreturn attribute, - /// false otherwise. - bool getNoReturnAttr() const; - - /// getCallConv - Returns the calling convention of the type if the type - /// is a function type, CC_Default otherwise. - CallingConv getCallConv() const; - private: // These methods are implemented in a separate translation unit; // "static"-ize them to avoid creating temporary QualTypes in the @@ -902,6 +895,9 @@ public: bool isDependentType() const { return Dependent; } bool isOverloadableType() const; + /// \brief Determine wither this type is a C++ elaborated-type-specifier. + bool isElaboratedTypeSpecifier() const; + /// hasPointerRepresentation - Whether this type is represented /// natively as a pointer; this includes pointers, references, block /// pointers, and Objective-C interface, qualified id, and qualified @@ -1747,25 +1743,101 @@ class FunctionType : public Type { /// NoReturn - Indicates if the function type is attribute noreturn. unsigned NoReturn : 1; + /// RegParm - How many arguments to pass inreg. + unsigned RegParm : 3; + /// CallConv - The calling convention used by the function. unsigned CallConv : 2; // The type returned by the function. QualType ResultType; + + public: + // This class is used for passing arround the information needed to + // construct a call. It is not actually used for storage, just for + // factoring together common arguments. + // If you add a field (say Foo), other than the obvious places (both, constructors, + // compile failures), what you need to update is + // * Operetor== + // * getFoo + // * withFoo + // * functionType. Add Foo, getFoo. + // * ASTContext::getFooType + // * ASTContext::mergeFunctionTypes + // * FunctionNoProtoType::Profile + // * FunctionProtoType::Profile + // * TypePrinter::PrintFunctionProto + // * PCH read and write + // * Codegen + + class ExtInfo { + public: + // Constructor with no defaults. Use this when you know that you + // have all the elements (when reading a PCH file for example). + ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) : + NoReturn(noReturn), RegParm(regParm), CC(cc) {} + + // Constructor with all defaults. Use when for example creating a + // function know to use defaults. + ExtInfo() : NoReturn(false), RegParm(0), CC(CC_Default) {} + + bool getNoReturn() const { return NoReturn; } + unsigned getRegParm() const { return RegParm; } + CallingConv getCC() const { return CC; } + + bool operator==(const ExtInfo &Other) const { + return getNoReturn() == Other.getNoReturn() && + getRegParm() == Other.getRegParm() && + getCC() == Other.getCC(); + } + bool operator!=(const ExtInfo &Other) const { + return !(*this == Other); + } + + // Note that we don't have setters. That is by design, use + // the following with methods instead of mutating these objects. + + ExtInfo withNoReturn(bool noReturn) const { + return ExtInfo(noReturn, getRegParm(), getCC()); + } + + ExtInfo withRegParm(unsigned RegParm) const { + return ExtInfo(getNoReturn(), RegParm, getCC()); + } + + ExtInfo withCallingConv(CallingConv cc) const { + return ExtInfo(getNoReturn(), getRegParm(), cc); + } + + private: + // True if we have __attribute__((noreturn)) + bool NoReturn; + // The value passed to __attribute__((regparm(x))) + unsigned RegParm; + // The calling convention as specified via + // __attribute__((cdecl|stdcall||fastcall)) + CallingConv CC; + }; + protected: FunctionType(TypeClass tc, QualType res, bool SubclassInfo, unsigned typeQuals, QualType Canonical, bool Dependent, - bool noReturn = false, CallingConv callConv = CC_Default) + const ExtInfo &Info) : Type(tc, Canonical, Dependent), - SubClassData(SubclassInfo), TypeQuals(typeQuals), NoReturn(noReturn), - CallConv(callConv), ResultType(res) {} + SubClassData(SubclassInfo), TypeQuals(typeQuals), + NoReturn(Info.getNoReturn()), + RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {} bool getSubClassData() const { return SubClassData; } unsigned getTypeQuals() const { return TypeQuals; } public: QualType getResultType() const { return ResultType; } + unsigned getRegParmType() const { return RegParm; } bool getNoReturnAttr() const { return NoReturn; } CallingConv getCallConv() const { return (CallingConv)CallConv; } + ExtInfo getExtInfo() const { + return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv); + } static llvm::StringRef getNameForCallConv(CallingConv CC); @@ -1780,9 +1852,9 @@ public: /// no information available about its arguments. class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { FunctionNoProtoType(QualType Result, QualType Canonical, - bool NoReturn = false, CallingConv CallConv = CC_Default) + const ExtInfo &Info) : FunctionType(FunctionNoProto, Result, false, 0, Canonical, - /*Dependent=*/false, NoReturn, CallConv) {} + /*Dependent=*/false, Info) {} friend class ASTContext; // ASTContext creates these. public: // No additional state past what FunctionType provides. @@ -1791,12 +1863,13 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getResultType(), getNoReturnAttr(), getCallConv()); + Profile(ID, getResultType(), getExtInfo()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, - bool NoReturn, CallingConv CallConv) { - ID.AddInteger(CallConv); - ID.AddInteger(NoReturn); + const ExtInfo &Info) { + ID.AddInteger(Info.getCC()); + ID.AddInteger(Info.getRegParm()); + ID.AddInteger(Info.getNoReturn()); ID.AddPointer(ResultType.getAsOpaquePtr()); } @@ -1827,12 +1900,12 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs, bool isVariadic, unsigned typeQuals, bool hasExs, bool hasAnyExs, const QualType *ExArray, - unsigned numExs, QualType Canonical, bool NoReturn, - CallingConv CallConv) + unsigned numExs, QualType Canonical, + const ExtInfo &Info) : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical, (Result->isDependentType() || - hasAnyDependentType(ArgArray, numArgs)), NoReturn, - CallConv), + hasAnyDependentType(ArgArray, numArgs)), + Info), NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs), AnyExceptionSpec(hasAnyExs) { // Fill in the trailing argument array. @@ -1918,7 +1991,7 @@ public: bool isVariadic, unsigned TypeQuals, bool hasExceptionSpec, bool anyExceptionSpec, unsigned NumExceptions, exception_iterator Exs, - bool NoReturn, CallingConv CallConv); + const ExtInfo &ExtInfo); }; @@ -2481,6 +2554,24 @@ public: static bool classof(const InjectedClassNameType *T) { return true; } }; +/// \brief The elaboration keyword that precedes a qualified type name or +/// introduces an elaborated-type-specifier. +enum ElaboratedTypeKeyword { + /// \brief No keyword precedes the qualified type name. + ETK_None, + /// \brief The "typename" keyword precedes the qualified type name, e.g., + /// \c typename T::type. + ETK_Typename, + /// \brief The "class" keyword introduces the elaborated-type-specifier. + ETK_Class, + /// \brief The "struct" keyword introduces the elaborated-type-specifier. + ETK_Struct, + /// \brief The "union" keyword introduces the elaborated-type-specifier. + ETK_Union, + /// \brief The "enum" keyword introduces the elaborated-type-specifier. + ETK_Enum +}; + /// \brief Represents a type that was referred to via a qualified /// name, e.g., N::M::type. /// @@ -2531,19 +2622,19 @@ public: static bool classof(const QualifiedNameType *T) { return true; } }; -/// \brief Represents a 'typename' specifier that names a type within -/// a dependent type, e.g., "typename T::type". +/// \brief Represents a qualified type name for which the type name is +/// dependent. /// -/// TypenameType has a very similar structure to QualifiedNameType, -/// which also involves a nested-name-specifier following by a type, -/// and (FIXME!) both can even be prefixed by the 'typename' -/// keyword. However, the two types serve very different roles: -/// QualifiedNameType is a non-semantic type that serves only as sugar -/// to show how a particular type was written in the source -/// code. TypenameType, on the other hand, only occurs when the -/// nested-name-specifier is dependent, such that we cannot resolve -/// the actual type until after instantiation. -class TypenameType : public Type, public llvm::FoldingSetNode { +/// DependentNameType represents a class of dependent types that involve a +/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent) +/// name of a type. The DependentNameType may start with a "typename" (for a +/// typename-specifier), "class", "struct", "union", or "enum" (for a +/// dependent elaborated-type-specifier), or nothing (in contexts where we +/// know that we must be referring to a type, e.g., in a base class specifier). +class DependentNameType : public Type, public llvm::FoldingSetNode { + /// \brief The keyword used to elaborate this type. + ElaboratedTypeKeyword Keyword; + /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; @@ -2553,23 +2644,28 @@ class TypenameType : public Type, public llvm::FoldingSetNode { /// \brief The type that this typename specifier refers to. NameType Name; - TypenameType(NestedNameSpecifier *NNS, const IdentifierInfo *Name, - QualType CanonType) - : Type(Typename, CanonType, true), NNS(NNS), Name(Name) { + DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + const IdentifierInfo *Name, QualType CanonType) + : Type(DependentName, CanonType, true), + Keyword(Keyword), NNS(NNS), Name(Name) { assert(NNS->isDependent() && - "TypenameType requires a dependent nested-name-specifier"); + "DependentNameType requires a dependent nested-name-specifier"); } - TypenameType(NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty, - QualType CanonType) - : Type(Typename, CanonType, true), NNS(NNS), Name(Ty) { + DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + const TemplateSpecializationType *Ty, QualType CanonType) + : Type(DependentName, CanonType, true), + Keyword(Keyword), NNS(NNS), Name(Ty) { assert(NNS->isDependent() && - "TypenameType requires a dependent nested-name-specifier"); + "DependentNameType requires a dependent nested-name-specifier"); } friend class ASTContext; // ASTContext creates these public: + /// \brief Retrieve the keyword used to elaborate this type. + ElaboratedTypeKeyword getKeyword() const { return Keyword; } + /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2593,19 +2689,20 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, NNS, Name); + Profile(ID, Keyword, NNS, Name); } - static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - NameType Name) { + static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, NameType Name) { + ID.AddInteger(Keyword); ID.AddPointer(NNS); ID.AddPointer(Name.getOpaqueValue()); } static bool classof(const Type *T) { - return T->getTypeClass() == Typename; + return T->getTypeClass() == DependentName; } - static bool classof(const TypenameType *T) { return true; } + static bool classof(const DependentNameType *T) { return true; } }; /// ObjCInterfaceType - Interfaces are the core concept in Objective-C for @@ -2936,37 +3033,18 @@ inline Qualifiers::GC QualType::getObjCGCAttr() const { return Qualifiers::GCNone; } - /// getNoReturnAttr - Returns true if the type has the noreturn attribute, - /// false otherwise. -inline bool QualType::getNoReturnAttr() const { - QualType CT = getTypePtr()->getCanonicalTypeInternal(); - if (const PointerType *PT = getTypePtr()->getAs<PointerType>()) { +inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { + if (const PointerType *PT = t.getAs<PointerType>()) { if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>()) - return FT->getNoReturnAttr(); - } else if (const FunctionType *FT = getTypePtr()->getAs<FunctionType>()) - return FT->getNoReturnAttr(); + return FT->getExtInfo(); + } else if (const FunctionType *FT = t.getAs<FunctionType>()) + return FT->getExtInfo(); - return false; + return FunctionType::ExtInfo(); } -/// getCallConv - Returns the calling convention of the type if the type -/// is a function type, CC_Default otherwise. -inline CallingConv QualType::getCallConv() const { - if (const PointerType *PT = getTypePtr()->getAs<PointerType>()) - return PT->getPointeeType().getCallConv(); - else if (const ReferenceType *RT = getTypePtr()->getAs<ReferenceType>()) - return RT->getPointeeType().getCallConv(); - else if (const MemberPointerType *MPT = - getTypePtr()->getAs<MemberPointerType>()) - return MPT->getPointeeType().getCallConv(); - else if (const BlockPointerType *BPT = - getTypePtr()->getAs<BlockPointerType>()) { - if (const FunctionType *FT = BPT->getPointeeType()->getAs<FunctionType>()) - return FT->getCallConv(); - } else if (const FunctionType *FT = getTypePtr()->getAs<FunctionType>()) - return FT->getCallConv(); - - return CC_Default; +inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { + return getFunctionExtInfo(*t); } /// isMoreQualifiedThan - Determine whether this type is more @@ -3152,6 +3230,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, return DB; } +/// Insertion operator for partial diagnostics. This allows sending QualType's +/// into a diagnostic with <<. +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + QualType T) { + PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), + Diagnostic::ak_qualtype); + return PD; +} + // Helper class template that is used by Type::getAs to ensure that one does // not try to look through a qualified type to get to an array type. template<typename T, diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 27659bd02f97..a51da7474d37 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1242,9 +1242,9 @@ class QualifiedNameTypeLoc : }; // FIXME: locations for the typename keyword and nested name specifier. -class TypenameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, - TypenameTypeLoc, - TypenameType> { +class DependentNameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + DependentNameTypeLoc, + DependentNameType> { }; } diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index e75202e50abf..7e8b73c7a5f9 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -92,7 +92,7 @@ NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) NON_CANONICAL_TYPE(QualifiedName, Type) NON_CANONICAL_TYPE(InjectedClassName, Type) -DEPENDENT_TYPE(Typename, Type) +DEPENDENT_TYPE(DependentName, Type) TYPE(ObjCInterface, Type) TYPE(ObjCObjectPointer, Type) diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index bde441741227..9ebd93b75b38 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -33,7 +33,7 @@ class ParentMap; class ImplicitParamDecl; class LocationContextManager; class StackFrameContext; - + /// AnalysisContext contains the context data for the function or method under /// analysis. class AnalysisContext { @@ -41,6 +41,7 @@ class AnalysisContext { // AnalysisContext owns the following data. CFG *cfg; + bool builtCFG; LiveVariables *liveness; ParentMap *PM; llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; @@ -48,8 +49,8 @@ class AnalysisContext { bool AddEHEdges; public: AnalysisContext(const Decl *d, bool addehedges = false) - : D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0), - AddEHEdges(addehedges) {} + : D(d), cfg(0), builtCFG(false), liveness(0), PM(0), + ReferencedBlockVars(0), AddEHEdges(addehedges) {} ~AnalysisContext(); @@ -69,7 +70,7 @@ public: std::pair<referenced_decls_iterator, referenced_decls_iterator> getReferencedBlockVars(const BlockDecl *BD); - + /// Return the ImplicitParamDecl* associated with 'self' if this /// AnalysisContext wraps an ObjCMethodDecl. Returns NULL otherwise. const ImplicitParamDecl *getSelfDecl() const; @@ -82,7 +83,7 @@ public: ~AnalysisContextManager(); AnalysisContext *getContext(const Decl *D); - + // Discard all previously created AnalysisContexts. void clear(); }; @@ -103,7 +104,7 @@ protected: public: virtual ~LocationContext(); - + ContextKind getKind() const { return Kind; } AnalysisContext *getAnalysisContext() const { return Ctx; } @@ -120,14 +121,14 @@ public: return getAnalysisContext()->getLiveVariables(); } - ParentMap &getParentMap() const { + ParentMap &getParentMap() const { return getAnalysisContext()->getParentMap(); } const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); } - + const StackFrameContext *getCurrentStackFrame() const; const StackFrameContext * getStackFrameForDeclContext(const DeclContext *DC) const; @@ -157,7 +158,7 @@ class StackFrameContext : public LocationContext { friend class LocationContextManager; StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s, const CFGBlock *blk, unsigned idx) - : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), + : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk), Index(idx) {} public: @@ -170,9 +171,9 @@ public: unsigned getIndex() const { return Index; } void Profile(llvm::FoldingSetNodeID &ID); - + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, - const LocationContext *parent, const Stmt *s, + const LocationContext *parent, const Stmt *s, const CFGBlock *blk, unsigned idx) { ProfileCommon(ID, StackFrame, ctx, parent, s); ID.AddPointer(blk); @@ -186,7 +187,7 @@ public: class ScopeContext : public LocationContext { const Stmt *Enter; - + friend class LocationContextManager; ScopeContext(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s) @@ -229,7 +230,7 @@ public: const LocationContext *parent, const BlockDecl *bd) { ProfileCommon(ID, Block, ctx, parent, bd); } - + static bool classof(const LocationContext* Ctx) { return Ctx->getKind() == Block; } @@ -239,7 +240,7 @@ class LocationContextManager { llvm::FoldingSet<LocationContext> Contexts; public: ~LocationContextManager(); - + const StackFrameContext *getStackFrame(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s, const CFGBlock *blk, @@ -248,7 +249,7 @@ public: const ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s); - + /// Discard all previously created LocationContext objects. void clear(); private: diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index cbf7010bfdb5..3c762011a657 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -17,7 +17,8 @@ #include "clang/Analysis/CFG.h" #include "clang/Analysis/ProgramPoint.h" #include "clang/Analysis/FlowSensitive/DataflowValues.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "functional" // STL namespace clang { @@ -28,23 +29,30 @@ namespace clang { //===----------------------------------------------------------------------===// class DataflowWorkListTy { - typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet; - BlockSet wlist; + llvm::DenseMap<const CFGBlock*, unsigned char> BlockSet; + llvm::SmallVector<const CFGBlock *, 10> BlockQueue; public: /// enqueue - Add a block to the worklist. Blocks already on the /// worklist are not added a second time. - void enqueue(const CFGBlock* B) { wlist.insert(B); } + void enqueue(const CFGBlock* B) { + unsigned char &x = BlockSet[B]; + if (x == 1) + return; + x = 1; + BlockQueue.push_back(B); + } /// dequeue - Remove a block from the worklist. const CFGBlock* dequeue() { - assert (!wlist.empty()); - const CFGBlock* B = *wlist.begin(); - wlist.erase(B); + assert(!BlockQueue.empty()); + const CFGBlock *B = BlockQueue.back(); + BlockQueue.pop_back(); + BlockSet[B] = 0; return B; } /// isEmpty - Return true if the worklist is empty. - bool isEmpty() const { return wlist.empty(); } + bool isEmpty() const { return BlockQueue.empty(); } }; //===----------------------------------------------------------------------===// @@ -188,10 +196,7 @@ private: /// SolveDataflowEquations - Perform the actual worklist algorithm /// to compute dataflow values. void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) { - // Enqueue all blocks to ensure the dataflow values are computed - // for every block. Not all blocks are guaranteed to reach the exit block. - for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I) - WorkList.enqueue(&**I); + EnqueueBlocksOnWorklist(cfg, AnalysisDirTag()); while (!WorkList.isEmpty()) { const CFGBlock* B = WorkList.dequeue(); @@ -201,6 +206,22 @@ private: } } + void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::forward_analysis_tag) { + // Enqueue all blocks to ensure the dataflow values are computed + // for every block. Not all blocks are guaranteed to reach the exit block. + for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I) + WorkList.enqueue(&**I); + } + + void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::backward_analysis_tag) { + // Enqueue all blocks to ensure the dataflow values are computed + // for every block. Not all blocks are guaranteed to reach the exit block. + // Enqueue in reverse order since that will more likely match with + // the order they should ideally processed by the dataflow algorithm. + for (CFG::reverse_iterator I=cfg.rbegin(), E=cfg.rend(); I!=E; ++I) + WorkList.enqueue(&**I); + } + void ProcessMerge(CFG& cfg, const CFGBlock* B) { ValTy& V = TF.getVal(); TF.SetTopValue(V); diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 3afdaf5b0eb1..453f660c360a 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -397,13 +397,6 @@ BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n") BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n") -BUILTIN(__sync_fetch_and_nand, "v.", "") -BUILTIN(__sync_fetch_and_nand_1, "cc*c.", "n") -BUILTIN(__sync_fetch_and_nand_2, "ss*s.", "n") -BUILTIN(__sync_fetch_and_nand_4, "ii*i.", "n") -BUILTIN(__sync_fetch_and_nand_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLi*LLLi.", "n") - BUILTIN(__sync_add_and_fetch, "v.", "") BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n") @@ -440,14 +433,6 @@ BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n") BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n") BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n") -BUILTIN(__sync_nand_and_fetch, "v.", "") -BUILTIN(__sync_nand_and_fetch_1, "cc*c.", "n") -BUILTIN(__sync_nand_and_fetch_2, "ss*s.", "n") -BUILTIN(__sync_nand_and_fetch_4, "ii*i.", "n") -BUILTIN(__sync_nand_and_fetch_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLi*LLLi.", "n") - - BUILTIN(__sync_bool_compare_and_swap, "v.", "") BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n") BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "n") diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 00b076aa1004..5c75d3799bcb 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -317,4 +317,12 @@ BUILTIN(__builtin_ia32_crc32qi, "iic", "") BUILTIN(__builtin_ia32_crc32hi, "iis", "") BUILTIN(__builtin_ia32_crc32si, "iii", "") BUILTIN(__builtin_ia32_crc32di, "LLiLLiLLi", "") + +// AES +BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLii", "") #undef BUILTIN diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index 9e643bb3c2c1..c2a4e1364a9e 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -1,8 +1,8 @@ macro(clang_diag_gen component) - tablegen(Diagnostic${component}Kinds.inc - -gen-clang-diags-defs -clang-component=${component}) + tablegen(Diagnostic${component}Kinds.inc + -gen-clang-diags-defs -clang-component=${component}) add_custom_target(ClangDiagnostic${component} - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Diagnostic${component}Kinds.inc) + DEPENDS Diagnostic${component}Kinds.inc) endmacro(clang_diag_gen) set(LLVM_TARGET_DEFINITIONS Diagnostic.td) @@ -17,4 +17,4 @@ clang_diag_gen(Sema) tablegen(DiagnosticGroups.inc -gen-clang-diag-groups) add_custom_target(ClangDiagnosticGroups - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/DiagnosticGroups.inc) + DEPENDS DiagnosticGroups.inc) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index d6c8797fc901..643868506d8f 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -95,7 +95,7 @@ namespace clang { /// should also provide full recovery from such errors, such that /// suppressing the diagnostic output can still result in successful /// compilation. -class CodeModificationHint { +class FixItHint { public: /// \brief Tokens that should be removed to correct the error. SourceRange RemoveRange; @@ -110,7 +110,7 @@ public: /// \brief Empty code modification hint, indicating that no code /// modification is known. - CodeModificationHint() : RemoveRange(), InsertionLoc() { } + FixItHint() : RemoveRange(), InsertionLoc() { } bool isNull() const { return !RemoveRange.isValid() && !InsertionLoc.isValid(); @@ -118,9 +118,9 @@ public: /// \brief Create a code modification hint that inserts the given /// code string at a specific location. - static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc, - llvm::StringRef Code) { - CodeModificationHint Hint; + static FixItHint CreateInsertion(SourceLocation InsertionLoc, + llvm::StringRef Code) { + FixItHint Hint; Hint.InsertionLoc = InsertionLoc; Hint.CodeToInsert = Code; return Hint; @@ -128,17 +128,17 @@ public: /// \brief Create a code modification hint that removes the given /// source range. - static CodeModificationHint CreateRemoval(SourceRange RemoveRange) { - CodeModificationHint Hint; + static FixItHint CreateRemoval(SourceRange RemoveRange) { + FixItHint Hint; Hint.RemoveRange = RemoveRange; return Hint; } /// \brief Create a code modification hint that replaces the given /// source range with the given code string. - static CodeModificationHint CreateReplacement(SourceRange RemoveRange, - llvm::StringRef Code) { - CodeModificationHint Hint; + static FixItHint CreateReplacement(SourceRange RemoveRange, + llvm::StringRef Code) { + FixItHint Hint; Hint.RemoveRange = RemoveRange; Hint.InsertionLoc = RemoveRange.getBegin(); Hint.CodeToInsert = Code; @@ -234,6 +234,18 @@ private: void *Cookie); void *ArgToStringCookie; ArgToStringFnTy ArgToStringFn; + + /// \brief ID of the "delayed" diagnostic, which is a (typically + /// fatal) diagnostic that had to be delayed because it was found + /// while emitting another diagnostic. + unsigned DelayedDiagID; + + /// \brief First string argument for the delayed diagnostic. + std::string DelayedDiagArg1; + + /// \brief Second string argument for the delayed diagnostic. + std::string DelayedDiagArg2; + public: explicit Diagnostic(DiagnosticClient *client = 0); ~Diagnostic(); @@ -377,6 +389,28 @@ public: /// the diagnostic, this returns null. static const char *getWarningOptionForDiag(unsigned DiagID); + /// \brief Enumeration describing how the the emission of a diagnostic should + /// be treated when it occurs during C++ template argument deduction. + enum SFINAEResponse { + /// \brief The diagnostic should not be reported, but it should cause + /// template argument deduction to fail. + /// + /// The vast majority of errors that occur during template argument + /// deduction fall into this category. + SFINAE_SubstitutionFailure, + + /// \brief The diagnostic should be suppressed entirely. + /// + /// Warnings generally fall into this category. + SFINAE_Suppress, + + /// \brief The diagnostic should be reported. + /// + /// The diagnostic should be reported. Various fatal errors (e.g., + /// template instantiation depth exceeded) fall into this category. + SFINAE_Report + }; + /// \brief Determines whether the given built-in diagnostic ID is /// for an error that is suppressed if it occurs during C++ template /// argument deduction. @@ -385,7 +419,7 @@ public: /// deduction fails but no diagnostic is emitted. Certain classes of /// errors, such as those errors that involve C++ access control, /// are not SFINAE errors. - static bool isBuiltinSFINAEDiag(unsigned DiagID); + static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); /// getDiagnosticLevel - Based on the way the client configured the Diagnostic /// object, classify the specified diagnostic ID into a Level, consumable by @@ -400,10 +434,41 @@ public: inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID); inline DiagnosticBuilder Report(unsigned DiagID); + /// \brief Determine whethere there is already a diagnostic in flight. + bool isDiagnosticInFlight() const { return CurDiagID != ~0U; } + + /// \brief Set the "delayed" diagnostic that will be emitted once + /// the current diagnostic completes. + /// + /// If a diagnostic is already in-flight but the front end must + /// report a problem (e.g., with an inconsistent file system + /// state), this routine sets a "delayed" diagnostic that will be + /// emitted after the current diagnostic completes. This should + /// only be used for fatal errors detected at inconvenient + /// times. If emitting a delayed diagnostic causes a second delayed + /// diagnostic to be introduced, that second delayed diagnostic + /// will be ignored. + /// + /// \param DiagID The ID of the diagnostic being delayed. + /// + /// \param Arg1 A string argument that will be provided to the + /// diagnostic. A copy of this string will be stored in the + /// Diagnostic object itself. + /// + /// \param Arg2 A string argument that will be provided to the + /// diagnostic. A copy of this string will be stored in the + /// Diagnostic object itself. + void SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1 = "", + llvm::StringRef Arg2 = ""); + /// \brief Clear out the current diagnostic. void Clear() { CurDiagID = ~0U; } private: + /// \brief Report the delayed diagnostic. + void ReportDelayed(); + + /// getDiagnosticMappingInfo - Return the mapping info currently set for the /// specified builtin diagnostic. This returns the high bit encoding, or zero /// if the field is completely uninitialized. @@ -454,8 +519,8 @@ private: /// NumRanges - This is the number of ranges in the DiagRanges array. unsigned char NumDiagRanges; /// \brief The number of code modifications hints in the - /// CodeModificationHints array. - unsigned char NumCodeModificationHints; + /// FixItHints array. + unsigned char NumFixItHints; /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum /// values, with one for each argument. This specifies whether the argument @@ -477,11 +542,11 @@ private: /// only support 10 ranges, could easily be extended if needed. SourceRange DiagRanges[10]; - enum { MaxCodeModificationHints = 3 }; + enum { MaxFixItHints = 3 }; - /// CodeModificationHints - If valid, provides a hint with some code + /// FixItHints - If valid, provides a hint with some code /// to insert, remove, or modify at a particular position. - CodeModificationHint CodeModificationHints[MaxCodeModificationHints]; + FixItHint FixItHints[MaxFixItHints]; /// ProcessDiag - This is the method used to report a diagnostic that is /// finally fully formed. @@ -508,13 +573,12 @@ private: /// for example. class DiagnosticBuilder { mutable Diagnostic *DiagObj; - mutable unsigned NumArgs, NumRanges, NumCodeModificationHints; + mutable unsigned NumArgs, NumRanges, NumFixItHints; void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT friend class Diagnostic; explicit DiagnosticBuilder(Diagnostic *diagObj) - : DiagObj(diagObj), NumArgs(0), NumRanges(0), - NumCodeModificationHints(0) {} + : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {} public: /// Copy constructor. When copied, this "takes" the diagnostic info from the @@ -524,7 +588,7 @@ public: D.DiagObj = 0; NumArgs = D.NumArgs; NumRanges = D.NumRanges; - NumCodeModificationHints = D.NumCodeModificationHints; + NumFixItHints = D.NumFixItHints; } /// \brief Simple enumeration value used to give a name to the @@ -534,7 +598,7 @@ public: /// \brief Create an empty DiagnosticBuilder object that represents /// no actual diagnostic. explicit DiagnosticBuilder(SuppressKind) - : DiagObj(0), NumArgs(0), NumRanges(0), NumCodeModificationHints(0) { } + : DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { } /// \brief Force the diagnostic builder to emit the diagnostic now. /// @@ -543,29 +607,7 @@ public: /// /// \returns true if a diagnostic was emitted, false if the /// diagnostic was suppressed. - bool Emit() { - // If DiagObj is null, then its soul was stolen by the copy ctor - // or the user called Emit(). - if (DiagObj == 0) return false; - - // When emitting diagnostics, we set the final argument count into - // the Diagnostic object. - DiagObj->NumDiagArgs = NumArgs; - DiagObj->NumDiagRanges = NumRanges; - DiagObj->NumCodeModificationHints = NumCodeModificationHints; - - // Process the diagnostic, sending the accumulated information to the - // DiagnosticClient. - bool Emitted = DiagObj->ProcessDiag(); - - // Clear out the current diagnostic object. - DiagObj->Clear(); - - // This diagnostic is dead. - DiagObj = 0; - - return Emitted; - } + bool Emit(); /// Destructor - The dtor emits the diagnostic if it hasn't already /// been emitted. @@ -605,14 +647,14 @@ public: DiagObj->DiagRanges[NumRanges++] = R; } - void AddCodeModificationHint(const CodeModificationHint &Hint) const { + void AddFixItHint(const FixItHint &Hint) const { if (Hint.isNull()) return; - assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints && - "Too many code modification hints!"); + assert(NumFixItHints < Diagnostic::MaxFixItHints && + "Too many fix-it hints!"); if (DiagObj) - DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint; + DiagObj->FixItHints[NumFixItHints++] = Hint; } }; @@ -673,8 +715,8 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, } inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, - const CodeModificationHint &Hint) { - DB.AddCodeModificationHint(Hint); + const FixItHint &Hint) { + DB.AddFixItHint(Hint); return DB; } @@ -770,17 +812,17 @@ public: return DiagObj->DiagRanges[Idx]; } - unsigned getNumCodeModificationHints() const { - return DiagObj->NumCodeModificationHints; + unsigned getNumFixItHints() const { + return DiagObj->NumFixItHints; } - const CodeModificationHint &getCodeModificationHint(unsigned Idx) const { - return DiagObj->CodeModificationHints[Idx]; + const FixItHint &getFixItHint(unsigned Idx) const { + return DiagObj->FixItHints[Idx]; } - const CodeModificationHint *getCodeModificationHints() const { - return DiagObj->NumCodeModificationHints? - &DiagObj->CodeModificationHints[0] : 0; + const FixItHint *getFixItHints() const { + return DiagObj->NumFixItHints? + &DiagObj->FixItHints[0] : 0; } /// FormatDiagnostic - Format this diagnostic into a string, substituting the @@ -803,7 +845,7 @@ class StoredDiagnostic { FullSourceLoc Loc; std::string Message; std::vector<SourceRange> Ranges; - std::vector<CodeModificationHint> FixIts; + std::vector<FixItHint> FixIts; public: StoredDiagnostic(); @@ -823,7 +865,7 @@ public: range_iterator range_end() const { return Ranges.end(); } unsigned range_size() const { return Ranges.size(); } - typedef std::vector<CodeModificationHint>::const_iterator fixit_iterator; + typedef std::vector<FixItHint>::const_iterator fixit_iterator; fixit_iterator fixit_begin() const { return FixIts.begin(); } fixit_iterator fixit_end() const { return FixIts.end(); } unsigned fixit_size() const { return FixIts.size(); } diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 3a28282d5522..2e0b4bad6b5b 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -22,7 +22,7 @@ def err_fe_stdout_binary : Error<"unable to change standard output to binary">, def err_fe_stderr_binary : Error<"unable to change standard error to binary">, DefaultFatal; def err_fe_dependency_file_requires_MT : Error< - "-dependency-file requires at least one -MT option">; + "-dependency-file requires at least one -MT or -MQ option">; def err_fe_incompatible_options : Error< "'%0' cannot be used with '%1'">, DefaultFatal; def err_fe_no_fixit_and_codegen : Error< @@ -57,6 +57,9 @@ def err_fe_pch_malformed_block : Error< "malformed block record in PCH file: '%0'">, DefaultFatal; def err_fe_pch_error_at_end_block : Error< "error at end of module block in PCH file: '%0'">, DefaultFatal; +def err_fe_pch_file_modified : Error< + "file '%0' has been modified since the precompiled header was built">, + DefaultFatal; def err_fe_unable_to_open_output : Error< "unable to open output file '%0': '%1'">; def err_fe_unable_to_open_logfile : Error< diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 203ab1eed547..b0c016bbfd28 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -31,6 +31,7 @@ def : DiagGroup<"char-align">; def Comment : DiagGroup<"comment">; def : DiagGroup<"ctor-dtor-privacy">; def : DiagGroup<"declaration-after-statement">; +def GNUDesignator : DiagGroup<"gnu-designator">; def Deprecated : DiagGroup<"deprecated">; def : DiagGroup<"disabled-optimization">; def : DiagGroup<"discard-qual">; @@ -115,6 +116,7 @@ def UnusedVariable : DiagGroup<"unused-variable">; def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">; def Reorder : DiagGroup<"reorder">; def UndeclaredSelector : DiagGroup<"undeclared-selector">; +def Protocol : DiagGroup<"protocol">; def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def : DiagGroup<"variadic-macros">; def VariadicMacros : DiagGroup<"variadic-macros">; @@ -185,3 +187,6 @@ def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment // but which aren't on by default in GCC. def NonGCC : DiagGroup<"non-gcc", [SignCompare, Conversion, LiteralRange]>; + +// A warning group for warnings about GCC extensions. +def GNU : DiagGroup<"gnu", [GNUDesignator]>; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 9d001d48cc2a..facf15f52e85 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -50,22 +50,26 @@ def ext_enumerator_list_comma : Extension< "feature">; def ext_gnu_indirect_goto : Extension< - "use of GNU indirect-goto extension">; + "use of GNU indirect-goto extension">, InGroup<GNU>; def ext_gnu_address_of_label : Extension< - "use of GNU address-of-label extension">; + "use of GNU address-of-label extension">, InGroup<GNU>; def ext_gnu_statement_expr : Extension< - "use of GNU statement expression extension">; + "use of GNU statement expression extension">, InGroup<GNU>; def ext_gnu_conditional_expr : Extension< - "use of GNU ?: expression extension, eliding middle term">; + "use of GNU ?: expression extension, eliding middle term">, InGroup<GNU>; def ext_gnu_empty_initializer : Extension< - "use of GNU empty initializer extension">; -def ext_gnu_array_range : Extension<"use of GNU array range extension">; + "use of GNU empty initializer extension">, InGroup<GNU>; +def ext_gnu_array_range : Extension<"use of GNU array range extension">, + InGroup<GNUDesignator>; def ext_gnu_missing_equal_designator : ExtWarn< - "use of GNU 'missing =' extension in designator">; + "use of GNU 'missing =' extension in designator">, + InGroup<GNUDesignator>; def err_expected_equal_designator : Error<"expected '=' or another designator">; def ext_gnu_old_style_field_designator : ExtWarn< - "use of GNU old-style field designator extension">; -def ext_gnu_case_range : Extension<"use of GNU case range extension">; + "use of GNU old-style field designator extension">, + InGroup<GNUDesignator>; +def ext_gnu_case_range : Extension<"use of GNU case range extension">, + InGroup<GNU>; // Generic errors. def err_parse_error : Error<"parse error">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 752be5df7a12..be00972dac5c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -68,7 +68,7 @@ def err_designator_into_flexible_array_member : Error< def note_flexible_array_member : Note< "initialized flexible array member %0 is here">; def ext_flexible_array_init : Extension< - "flexible array initialization is a GNU extension">; + "flexible array initialization is a GNU extension">, InGroup<GNU>; // Declarations. def ext_vla : Extension< @@ -268,8 +268,6 @@ def err_duplicate_ivar_declaration : Error< "instance variable is already declared">; def warn_on_superclass_use : Warning< "class implementation may not have super class">; -def err_non_private_ivar_declaration : Error< - "only private ivars may be declared in implementation">; def err_conflicting_ivar_bitwidth : Error< "instance variable %0 has conflicting bit-field width">; def err_conflicting_ivar_name : Error< @@ -277,7 +275,9 @@ def err_conflicting_ivar_name : Error< def err_inconsistant_ivar_count : Error< "inconsistent number of instance variables specified">; def warn_incomplete_impl : Warning<"incomplete implementation">; -def warn_undef_method_impl : Warning<"method definition for %0 not found">; +def note_undef_method_impl : Note<"method definition for %0 not found">; +def note_required_for_protocol_at : + Note<"required for direct or indirect protocol %0">; def warn_conflicting_ret_types : Warning< "conflicting return type in implementation of %0: %1 vs %2">; @@ -350,7 +350,7 @@ def error_synthesized_ivar_yet_not_supported : Error< " (need to declare %0 explicitly)">; def error_property_ivar_type : Error< - "type of property %0 does not match type of ivar %1">; + "type of property %0 (%1) does not match type of ivar %2 (%3)">; def error_ivar_in_superclass_use : Error< "property %0 attempting to use ivar %1 declared in super class %2">; def error_weak_property : Error< @@ -367,6 +367,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning< InGroup<ReadOnlySetterAttrs>, DefaultIgnore; def warn_undeclared_selector : Warning< "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore; +def warn_unimplemented_protocol_method : Warning< + "method in protocol not implemented">, InGroup<Protocol>; // C++ declarations def err_static_assert_expression_is_not_constant : Error< @@ -393,7 +395,11 @@ def err_abstract_type_in_decl : Error< "%select{return|parameter|variable|field}0 type %1 is an abstract class">; def err_allocation_of_abstract_type : Error< "allocation of an object of abstract type %0">; - + +def err_multiple_final_overriders : Error< + "virtual function %q0 has more than one final overrider in %1">; +def note_final_overrider : Note<"final overrider of %q0 in %1">; + def err_type_defined_in_type_specifier : Error< "%0 can not be defined in a type specifier">; def err_type_defined_in_result_type : Error< @@ -432,6 +438,8 @@ def err_incompatible_exception_specs : Error< "target exception specification is not superset of source">; def err_deep_exception_specs_differ : Error< "exception specifications of %select{return|argument}0 types differ">; +def warn_missing_exception_specification : Warning< + "%0 is missing exception specification '%1'">; // C++ access checking def err_class_redeclared_with_different_access : Error< @@ -532,6 +540,7 @@ def err_implicit_object_parameter_init : Error< "of type %1">; def note_field_decl : Note<"member is declared here">; +def note_ivar_decl : Note<"ivar is declared here">; def note_bitfield_decl : Note<"bit-field is declared here">; def note_previous_decl : Note<"%0 declared here">; def note_member_synthesized_at : Note< @@ -776,8 +785,9 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< def warn_attribute_ignored : Warning<"%0 attribute ignored">; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">; -def warn_attribute_void_function : Warning< - "attribute %0 cannot be applied to functions without return value">; +def warn_attribute_void_function_method : Warning< + "attribute %0 cannot be applied to " + "%select{functions|Objective-C method}1 without return value">; def warn_attribute_weak_on_field : Warning< "__weak attribute cannot be specified on a field declaration">; def warn_attribute_weak_on_local : Warning< @@ -1199,26 +1209,40 @@ def err_template_arg_not_integral_or_enumeral : Error< def err_template_arg_not_ice : Error< "non-type template argument of type %0 is not an integral constant " "expression">; +def err_deduced_non_type_template_arg_type_mismatch : Error< + "deduced non-type template argument does not have the same type as the " + "its corresponding template parameter (%0 vs %1)">; def err_template_arg_not_convertible : Error< "non-type template argument of type %0 cannot be converted to a value " "of type %1">; -def err_template_arg_negative : Error< - "non-type template argument provides negative value '%0' for unsigned " - "template parameter of type %1">; -def err_template_arg_too_large : Error< - "non-type template argument value '%0' is too large for template " - "parameter of type %1">; +def warn_template_arg_negative : Warning< + "non-type template argument with value '%0' converted to '%1' for unsigned " + "template parameter of type %2">; +def warn_template_arg_too_large : Warning< + "non-type template argument value '%0' truncated to '%1' for " + "template parameter of type %2">; def err_template_arg_no_ref_bind : Error< "non-type template parameter of reference type %0 cannot bind to template " "argument of type %1">; def err_template_arg_ref_bind_ignores_quals : Error< "reference binding of non-type template parameter of type %0 to template " "argument of type %1 ignores qualifiers">; +def err_template_arg_unresolved_overloaded_function : Error< + "overloaded function cannot be resolved to a non-type template parameter of " + "type %0">; def err_template_arg_not_decl_ref : Error< "non-type template argument does not refer to any declaration">; def err_template_arg_not_object_or_func_form : Error< "non-type template argument does not directly refer to an object or " "function">; +def err_template_arg_not_address_of : Error< + "non-type template argument for template parameter of pointer type %0 must " + "have its address taken">; +def err_template_arg_address_of_non_pointer : Error< + "address taken in non-type template argument for template parameter of " + "reference type %0">; +def err_template_arg_reference_var : Error< + "non-type template argument of reference type %0 is not an object">; def err_template_arg_field : Error< "non-type template argument refers to non-static data member %0">; def err_template_arg_method : Error< @@ -1251,6 +1275,8 @@ def err_template_spec_decl_function_scope : Error< "explicit specialization of %0 in function scope">; def err_template_spec_decl_class_scope : Error< "explicit specialization of %0 in class scope">; +def err_template_spec_decl_friend : Error< + "cannot declare an explicit specialization in a friend">; def err_template_spec_decl_out_of_scope_global : Error< "%select{class template|class template partial|function template|member " "function|static data member|member class}0 specialization of %1 must " @@ -1372,13 +1398,13 @@ def note_default_function_arg_instantiation_here : Note< "for '%0' required here">; def note_explicit_template_arg_substitution_here : Note< "while substituting explicitly-specified template arguments into function " - "template %f, here">; + "template %0 %1">; def note_function_template_deduction_instantiation_here : Note< - "while substituting deduced template arguments into function template %0, " - "here">; + "while substituting deduced template arguments into function template %0 " + "%1">; def note_partial_spec_deduct_instantiation_here : Note< "during template argument deduction for class template partial " - "specialization %0, here">; + "specialization %0 %1">; def note_prior_template_arg_substitution : Note< "while substituting prior template arguments into %select{non-type|template}0" " template parameter%1 %2">; @@ -1537,7 +1563,8 @@ def err_forward_ref_enum : Error< "ISO C++ forbids forward references to 'enum' types">; def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; def err_duplicate_member : Error<"duplicate member %0">; -def err_misplaced_ivar : Error<"ivars may not be placed in categories">; +def err_misplaced_ivar : Error< + "ivars may not be placed in %select{categories|class extension}0">; def ext_enum_value_not_int : Extension< "ISO C restricts enumerator values to range of 'int' (%0 is too " "%select{small|large}1)">; @@ -1575,6 +1602,8 @@ def err_typecheck_invalid_restrict_invalid_pointee : Error< "pointer to function type %0 may not be 'restrict' qualified">; def ext_typecheck_zero_array_size : Extension< "zero size arrays are an extension">; +def err_typecheck_zero_array_size : Error< + "zero-length arrays are not permitted in C++">; def err_at_least_one_initializer_needed_to_size_array : Error< "at least one initializer value required to size array">; def err_array_size_non_int : Error<"size of array has non-integer type %0">; @@ -1664,7 +1693,7 @@ def err_field_declared_as_function : Error<"field %0 declared as a function">; def err_field_incomplete : Error<"field has incomplete type %0">; def ext_variable_sized_type_in_struct : ExtWarn< "field %0 with variable sized type %1 not at the end of a struct or class is" - " a GNU extension">; + " a GNU extension">, InGroup<GNU>; def err_flexible_array_empty_struct : Error< "flexible array %0 not allowed in otherwise empty struct">; @@ -2164,7 +2193,7 @@ def err_invalid_declarator_global_scope : Error< def err_invalid_declarator_in_function : Error< "definition or redeclaration of %0 not allowed inside a function">; def err_not_tag_in_scope : Error< - "%0 does not name a tag member in the specified scope">; + "no %select{struct|union|class|enum}0 named %1 in %2">; def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; @@ -2322,7 +2351,8 @@ def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn< def err_typecheck_choose_expr_requires_constant : Error< "'__builtin_choose_expr' requires a constant expression">; def ext_typecheck_expression_not_constant_but_accepted : Extension< - "expression is not a constant, but is accepted as one by GNU extensions">; + "expression is not a constant, but is accepted as one by GNU extensions">, + InGroup<GNU>; def warn_unused_expr : Warning<"expression result unused">, InGroup<UnusedValue>; def warn_unused_property_expr : Warning< @@ -2334,6 +2364,7 @@ def warn_unused_call : Warning< def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; +def err_expected_ident_or_lparen : Error<"expected identifier or '('">; // inline asm. def err_asm_wide_character : Error<"wide string is invalid in 'asm'">; @@ -2413,9 +2444,9 @@ def err_in_class_initializer_non_constant : Error< // C++ anonymous unions and GNU anonymous structs/unions def ext_anonymous_union : Extension< - "anonymous unions are a GNU extension in C">; + "anonymous unions are a GNU extension in C">, InGroup<GNU>; def ext_anonymous_struct : Extension< - "anonymous structs are a GNU extension">; + "anonymous structs are a GNU extension">, InGroup<GNU>; def err_anonymous_union_not_static : Error< "anonymous unions at namespace or global scope must be declared 'static'">; def err_anonymous_union_with_storage_spec : Error< @@ -2584,6 +2615,9 @@ def warn_printf_missing_format_string : Warning< def warn_printf_conversion_argument_type_mismatch : Warning< "conversion specifies type %0 but the argument has type %1">, InGroup<Format>; +def warn_printf_positional_arg_exceeds_data_args : Warning < + "data argument position '%0' exceeds the number of data arguments (%1)">, + InGroup<Format>; def warn_printf_zero_positional_specifier : Warning< "position arguments in format strings start counting at 1 (not 0)">, InGroup<Format>; diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index fb861dcf934d..89fae87ae8ef 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -15,19 +15,18 @@ #ifndef LLVM_CLANG_PARTIALDIAGNOSTIC_H #define LLVM_CLANG_PARTIALDIAGNOSTIC_H -#include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/System/DataTypes.h" +#include <cassert> namespace clang { -class DeclarationName; - class PartialDiagnostic { +public: struct Storage { - Storage() : NumDiagArgs(0), NumDiagRanges(0), NumCodeModificationHints(0) { - } + Storage() : NumDiagArgs(0), NumDiagRanges(0), NumFixItHints(0) { } enum { /// MaxArguments - The maximum number of arguments we can hold. We @@ -44,8 +43,8 @@ class PartialDiagnostic { unsigned char NumDiagRanges; /// \brief The number of code modifications hints in the - /// CodeModificationHints array. - unsigned char NumCodeModificationHints; + /// FixItHints array. + unsigned char NumFixItHints; /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum /// values, with one for each argument. This specifies whether the argument @@ -62,13 +61,49 @@ class PartialDiagnostic { /// only support 10 ranges, could easily be extended if needed. SourceRange DiagRanges[10]; - enum { MaxCodeModificationHints = 3 }; + enum { MaxFixItHints = 3 }; - /// CodeModificationHints - If valid, provides a hint with some code + /// FixItHints - If valid, provides a hint with some code /// to insert, remove, or modify at a particular position. - CodeModificationHint CodeModificationHints[MaxCodeModificationHints]; + FixItHint FixItHints[MaxFixItHints]; }; + /// \brief An allocator for Storage objects, which uses a small cache to + /// objects, used to reduce malloc()/free() traffic for partial diagnostics. + class StorageAllocator { + static const unsigned NumCached = 4; + Storage Cached[NumCached]; + Storage *FreeList[NumCached]; + unsigned NumFreeListEntries; + + public: + StorageAllocator(); + ~StorageAllocator(); + + /// \brief Allocate new storage. + Storage *Allocate() { + if (NumFreeListEntries == 0) + return new Storage; + + Storage *Result = FreeList[--NumFreeListEntries]; + Result->NumDiagArgs = 0; + Result->NumDiagRanges = 0; + Result->NumFixItHints = 0; + return Result; + } + + /// \brief Free the given storage object. + void Deallocate(Storage *S) { + if (S >= Cached && S <= Cached + NumCached) { + FreeList[NumFreeListEntries++] = S; + return; + } + + delete S; + } + }; + +private: // NOTE: Sema assumes that PartialDiagnostic is location-invariant // in the sense that its bits can be safely memcpy'ed and destructed // in the new location. @@ -76,22 +111,40 @@ class PartialDiagnostic { /// DiagID - The diagnostic ID. mutable unsigned DiagID; - /// DiagStorare - Storge for args and ranges. + /// DiagStorage - Storage for args and ranges. mutable Storage *DiagStorage; - void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const { - if (!DiagStorage) + /// \brief Allocator used to allocate storage for this diagnostic. + StorageAllocator *Allocator; + + /// \brief Retrieve storage for this particular diagnostic. + Storage *getStorage() const { + if (DiagStorage) + return DiagStorage; + + if (Allocator) + DiagStorage = Allocator->Allocate(); + else { + assert(Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))); DiagStorage = new Storage; + } + return DiagStorage; + } + + void freeStorage() { + if (!DiagStorage) + return; - assert(DiagStorage->NumDiagArgs < Storage::MaxArguments && - "Too many arguments to diagnostic!"); - DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind; - DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; + if (Allocator) + Allocator->Deallocate(DiagStorage); + else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) + delete DiagStorage; + DiagStorage = 0; } - + void AddSourceRange(const SourceRange &R) const { if (!DiagStorage) - DiagStorage = new Storage; + DiagStorage = getStorage(); assert(DiagStorage->NumDiagRanges < llvm::array_lengthof(DiagStorage->DiagRanges) && @@ -99,53 +152,70 @@ class PartialDiagnostic { DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R; } - void AddCodeModificationHint(const CodeModificationHint &Hint) const { + void AddFixItHint(const FixItHint &Hint) const { if (Hint.isNull()) return; if (!DiagStorage) - DiagStorage = new Storage; + DiagStorage = getStorage(); - assert(DiagStorage->NumCodeModificationHints < - Storage::MaxCodeModificationHints && + assert(DiagStorage->NumFixItHints < Storage::MaxFixItHints && "Too many code modification hints!"); - DiagStorage->CodeModificationHints[DiagStorage->NumCodeModificationHints++] + DiagStorage->FixItHints[DiagStorage->NumFixItHints++] = Hint; } public: - PartialDiagnostic(unsigned DiagID) - : DiagID(DiagID), DiagStorage(0) { } - + PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) + : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { } + PartialDiagnostic(const PartialDiagnostic &Other) - : DiagID(Other.DiagID), DiagStorage(0) + : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator) { - if (Other.DiagStorage) - DiagStorage = new Storage(*Other.DiagStorage); + if (Other.DiagStorage) { + DiagStorage = getStorage(); + *DiagStorage = *Other.DiagStorage; + } } + PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) + : DiagID(Other.DiagID), DiagStorage(DiagStorage), + Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) + { + if (Other.DiagStorage) + *this->DiagStorage = *Other.DiagStorage; + } + PartialDiagnostic &operator=(const PartialDiagnostic &Other) { DiagID = Other.DiagID; if (Other.DiagStorage) { - if (DiagStorage) - *DiagStorage = *Other.DiagStorage; - else - DiagStorage = new Storage(*Other.DiagStorage); + if (!DiagStorage) + DiagStorage = getStorage(); + + *DiagStorage = *Other.DiagStorage; } else { - delete DiagStorage; - DiagStorage = 0; + freeStorage(); } return *this; } ~PartialDiagnostic() { - delete DiagStorage; + freeStorage(); } - unsigned getDiagID() const { return DiagID; } + void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const { + if (!DiagStorage) + DiagStorage = getStorage(); + + assert(DiagStorage->NumDiagArgs < Storage::MaxArguments && + "Too many arguments to diagnostic!"); + DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind; + DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; + } + void Emit(const DiagnosticBuilder &DB) const { if (!DiagStorage) return; @@ -161,17 +231,19 @@ public: DB.AddSourceRange(DiagStorage->DiagRanges[i]); // Add all code modification hints - for (unsigned i = 0, e = DiagStorage->NumCodeModificationHints; i != e; ++i) - DB.AddCodeModificationHint(DiagStorage->CodeModificationHints[i]); + for (unsigned i = 0, e = DiagStorage->NumFixItHints; i != e; ++i) + DB.AddFixItHint(DiagStorage->FixItHints[i]); } - friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - QualType T) { - PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), - Diagnostic::ak_qualtype); - return PD; + /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID + /// and removing all of its arguments, ranges, and fix-it hints. + void Reset(unsigned DiagID = 0) { + this->DiagID = DiagID; + freeStorage(); } - + + bool hasStorage() const { return DiagStorage != 0; } + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, unsigned I) { PD.AddTaggedVal(I, Diagnostic::ak_uint); @@ -197,20 +269,13 @@ public: } friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - DeclarationName N); - - friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, - const CodeModificationHint &Hint) { - PD.AddCodeModificationHint(Hint); + const FixItHint &Hint) { + PD.AddFixItHint(Hint); return PD; } }; -inline PartialDiagnostic PDiag(unsigned DiagID = 0) { - return PartialDiagnostic(DiagID); -} - inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const PartialDiagnostic &PD) { PD.Emit(DB); @@ -219,4 +284,4 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, } // end namespace clang -#endif +#endif diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index f7ea331e1cc7..555e6f5a919a 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -28,7 +28,6 @@ namespace llvm { namespace clang { class SourceManager; -class FileEntry; /// FileID - This is an opaque identifier used by SourceManager which refers to /// a source file (MemoryBuffer) along with its #include path and #line data. diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h index 2c15f2a40576..617034292638 100644 --- a/include/clang/Checker/BugReporter/BugReporter.h +++ b/include/clang/Checker/BugReporter/BugReporter.h @@ -15,17 +15,12 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER #define LLVM_CLANG_ANALYSIS_BUGREPORTER -#include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Checker/BugReporter/BugType.h" -#include "clang/Checker/PathSensitive/ExplodedGraph.h" #include "clang/Checker/PathSensitive/GRState.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableList.h" #include "llvm/ADT/ImmutableSet.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallString.h" #include <list> namespace clang { @@ -35,6 +30,8 @@ class PathDiagnosticPiece; class PathDiagnosticClient; class ASTContext; class Diagnostic; +class ExplodedNode; +class ExplodedGraph; class BugReporter; class BugReporterContext; class GRExprEngine; diff --git a/include/clang/Checker/BugReporter/BugType.h b/include/clang/Checker/BugReporter/BugType.h index 4f1523a5440d..afc07c89e86f 100644 --- a/include/clang/Checker/BugReporter/BugType.h +++ b/include/clang/Checker/BugReporter/BugType.h @@ -14,15 +14,12 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE #define LLVM_CLANG_ANALYSIS_BUGTYPE -#include <llvm/ADT/FoldingSet.h> +#include "clang/Checker/BugReporter/BugReporter.h" +#include "llvm/ADT/FoldingSet.h" #include <string> namespace clang { -class BugReportEquivClass; -class BugReporter; -class BuiltinBugReport; -class BugReporterContext; class ExplodedNode; class GRExprEngine; diff --git a/include/clang/Checker/BugReporter/PathDiagnostic.h b/include/clang/Checker/BugReporter/PathDiagnostic.h index d380c45480cb..24c75ce7b228 100644 --- a/include/clang/Checker/BugReporter/PathDiagnostic.h +++ b/include/clang/Checker/BugReporter/PathDiagnostic.h @@ -168,7 +168,7 @@ public: private: const std::string str; - std::vector<CodeModificationHint> CodeModificationHints; + std::vector<FixItHint> FixItHints; const Kind kind; const DisplayHint Hint; std::vector<SourceRange> ranges; @@ -203,8 +203,8 @@ public: ranges.push_back(SourceRange(B,E)); } - void addCodeModificationHint(const CodeModificationHint& Hint) { - CodeModificationHints.push_back(Hint); + void addFixItHint(const FixItHint& Hint) { + FixItHints.push_back(Hint); } typedef const SourceRange* range_iterator; @@ -217,15 +217,15 @@ public: return ranges_begin() + ranges.size(); } - typedef const CodeModificationHint *code_modifications_iterator; + typedef const FixItHint *fixit_iterator; - code_modifications_iterator code_modifications_begin() const { - return CodeModificationHints.empty()? 0 : &CodeModificationHints[0]; + fixit_iterator fixit_begin() const { + return FixItHints.empty()? 0 : &FixItHints[0]; } - code_modifications_iterator code_modifications_end() const { - return CodeModificationHints.empty()? 0 - : &CodeModificationHints[0] + CodeModificationHints.size(); + fixit_iterator fixit_end() const { + return FixItHints.empty()? 0 + : &FixItHints[0] + FixItHints.size(); } static inline bool classof(const PathDiagnosticPiece* P) { diff --git a/include/clang/Checker/DomainSpecific/CocoaConventions.h b/include/clang/Checker/DomainSpecific/CocoaConventions.h index ee3d648b8608..4bbdab0e7fe1 100644 --- a/include/clang/Checker/DomainSpecific/CocoaConventions.h +++ b/include/clang/Checker/DomainSpecific/CocoaConventions.h @@ -14,7 +14,6 @@ #ifndef LLVM_CLANG_CHECKER_DS_COCOA #define LLVM_CLANG_CHECKER_DS_COCOA -#include "clang/Basic/IdentifierTable.h" #include "clang/AST/Type.h" namespace clang { diff --git a/include/clang/Checker/PathSensitive/BasicValueFactory.h b/include/clang/Checker/PathSensitive/BasicValueFactory.h index 2f0b6c2a0348..59dd9190d25e 100644 --- a/include/clang/Checker/PathSensitive/BasicValueFactory.h +++ b/include/clang/Checker/PathSensitive/BasicValueFactory.h @@ -16,7 +16,6 @@ #ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H #define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H -#include "clang/Checker/PathSensitive/SymbolManager.h" #include "clang/Checker/PathSensitive/SVals.h" #include "clang/AST/ASTContext.h" #include "llvm/ADT/FoldingSet.h" diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h index 2401a72741b2..8cb9cc8337c6 100644 --- a/include/clang/Checker/PathSensitive/Checker.h +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -14,21 +14,15 @@ #ifndef LLVM_CLANG_ANALYSIS_CHECKER #define LLVM_CLANG_ANALYSIS_CHECKER + #include "clang/Analysis/Support/SaveAndRestore.h" -#include "clang/Checker/PathSensitive/GRCoreEngine.h" -#include "clang/Checker/PathSensitive/GRState.h" #include "clang/Checker/PathSensitive/GRExprEngine.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h" //===----------------------------------------------------------------------===// // Checker interface. //===----------------------------------------------------------------------===// namespace clang { - class GRExprEngine; class CheckerContext { ExplodedNodeSet &Dst; diff --git a/include/clang/Checker/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h index 6051654f4855..b9bbebc652f2 100644 --- a/include/clang/Checker/PathSensitive/Environment.h +++ b/include/clang/Checker/PathSensitive/Environment.h @@ -18,11 +18,8 @@ // typedefs. #include "clang/Checker/PathSensitive/Store.h" -#include "llvm/ADT/ImmutableMap.h" -#include "llvm/ADT/SmallVector.h" #include "clang/Checker/PathSensitive/SVals.h" -#include "llvm/Support/Allocator.h" -#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableMap.h" namespace clang { diff --git a/include/clang/Checker/PathSensitive/ExplodedGraph.h b/include/clang/Checker/PathSensitive/ExplodedGraph.h index d6c4436c594c..c09c89312e10 100644 --- a/include/clang/Checker/PathSensitive/ExplodedGraph.h +++ b/include/clang/Checker/PathSensitive/ExplodedGraph.h @@ -9,6 +9,10 @@ // // This file defines the template classes ExplodedNode and ExplodedGraph, // which represent a path-sensitive, intra-procedural "exploded graph." +// See "Precise interprocedural dataflow analysis via graph reachability" +// by Reps, Horwitz, and Sagiv +// (http://portal.acm.org/citation.cfm?id=199462) for the definition of an +// exploded graph. // //===----------------------------------------------------------------------===// diff --git a/include/clang/Checker/PathSensitive/GRBlockCounter.h b/include/clang/Checker/PathSensitive/GRBlockCounter.h index 67ed9532db02..b7d0e8ae0c71 100644 --- a/include/clang/Checker/PathSensitive/GRBlockCounter.h +++ b/include/clang/Checker/PathSensitive/GRBlockCounter.h @@ -22,6 +22,8 @@ namespace llvm { namespace clang { +class StackFrameContext; + class GRBlockCounter { void* Data; @@ -30,7 +32,8 @@ class GRBlockCounter { public: GRBlockCounter() : Data(0) {} - unsigned getNumVisited(unsigned BlockID) const; + unsigned getNumVisited(const StackFrameContext *CallSite, + unsigned BlockID) const; class Factory { void* F; @@ -39,7 +42,9 @@ public: ~Factory(); GRBlockCounter GetEmptyCounter(); - GRBlockCounter IncrementCount(GRBlockCounter BC, unsigned BlockID); + GRBlockCounter IncrementCount(GRBlockCounter BC, + const StackFrameContext *CallSite, + unsigned BlockID); }; friend class Factory; diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index c5bf5138a63f..a3ff0dbedc7b 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -82,7 +82,7 @@ class GRCoreEngine { void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder); - bool ProcessBlockEntrance(CFGBlock* Blk, const GRState* State, + bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred, GRBlockCounter BC); @@ -174,7 +174,9 @@ public: GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} unsigned getCurrentBlockCount() const { - return getBlockCounter().getNumVisited(B.getBlockID()); + return getBlockCounter().getNumVisited( + Pred->getLocationContext()->getCurrentStackFrame(), + B.getBlockID()); } ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) { @@ -434,7 +436,9 @@ public: } unsigned getCurrentBlockCount() const { - return getBlockCounter().getNumVisited(B.getBlockID()); + return getBlockCounter().getNumVisited( + Pred->getLocationContext()->getCurrentStackFrame(), + B.getBlockID()); } ExplodedNode* generateNode(const GRState* State, const void *tag = 0, diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 916511e8bd09..161cb28df033 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -16,7 +16,6 @@ #ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE #define LLVM_CLANG_ANALYSIS_GREXPRENGINE -#include "clang/Checker/PathSensitive/AnalysisManager.h" #include "clang/Checker/PathSensitive/GRSubEngine.h" #include "clang/Checker/PathSensitive/GRCoreEngine.h" #include "clang/Checker/PathSensitive/GRState.h" @@ -28,11 +27,9 @@ #include "clang/AST/ExprCXX.h" namespace clang { - - class PathDiagnosticClient; - class Diagnostic; - class ObjCForCollectionStmt; - class Checker; +class AnalysisManager; +class Checker; +class ObjCForCollectionStmt; class GRExprEngine : public GRSubEngine { AnalysisManager &AMgr; @@ -153,7 +150,7 @@ public: /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue /// exploring the given path, and false otherwise. - bool ProcessBlockEntrance(CFGBlock* B, const GRState* St, + bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, GRBlockCounter BC); /// ProcessBranch - Called by GRCoreEngine. Used to generate successor @@ -216,7 +213,7 @@ public: const GRState* St, ProgramPoint::Kind K = ProgramPoint::PostStmtKind, const void *tag = 0); -protected: + /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, @@ -351,10 +348,21 @@ protected: void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest, ExplodedNode *Pred, ExplodedNodeSet &Dst); + + void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + + void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred, + ExplodedNodeSet &Dst); + /// Create a C++ temporary object for an rvalue. void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst); + /// Synthesize CXXThisRegion. + const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD, + const StackFrameContext *SFC); + /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) /// with those assumptions. diff --git a/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h index 383463b822cb..6d85e5fe6a90 100644 --- a/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h +++ b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h @@ -17,18 +17,9 @@ #define LLVM_CLANG_ANALYSIS_GRAPICHECKS #include "clang/Checker/PathSensitive/GRAuditor.h" -#include "clang/Checker/PathSensitive/GRState.h" namespace clang { -class Diagnostic; -class BugReporter; -class ASTContext; -class GRExprEngine; -class PathDiagnosticClient; -class ExplodedGraph; - - class GRSimpleAPICheck : public GRAuditor { public: GRSimpleAPICheck() {} diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h index 657266b7508d..25ba1f85fdff 100644 --- a/include/clang/Checker/PathSensitive/GRState.h +++ b/include/clang/Checker/PathSensitive/GRState.h @@ -14,30 +14,22 @@ #ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H #define LLVM_CLANG_ANALYSIS_VALUESTATE_H -// FIXME: Reduce the number of includes. - -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/Analysis/Analyses/LiveVariables.h" #include "clang/Checker/PathSensitive/ConstraintManager.h" #include "clang/Checker/PathSensitive/Environment.h" -#include "clang/Checker/PathSensitive/GRCoreEngine.h" #include "clang/Checker/PathSensitive/Store.h" #include "clang/Checker/PathSensitive/ValueManager.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/DataTypes.h" -#include <functional> -namespace clang { +namespace llvm { +class APSInt; +class BumpPtrAllocator; +class raw_ostream; +} +namespace clang { +class ASTContext; class GRStateManager; class Checker; @@ -302,6 +294,8 @@ public: template<typename T> const GRState *remove(typename GRStateTrait<T>::key_type K, typename GRStateTrait<T>::context_type C) const; + template <typename T> + const GRState *remove() const; template<typename T> const GRState *set(typename GRStateTrait<T>::data_type D) const; @@ -464,6 +458,7 @@ public: // Methods that manipulate the GDM. const GRState* addGDM(const GRState* St, void* Key, void* Data); + const GRState *removeGDM(const GRState *state, void *Key); // Methods that query & manipulate the Store. @@ -528,6 +523,10 @@ public: GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C))); } + template <typename T> + const GRState *remove(const GRState *st) { + return removeGDM(st, GRStateTrait<T>::GDMIndex()); + } void* FindGDMContext(void* index, void* (*CreateContext)(llvm::BumpPtrAllocator&), @@ -702,6 +701,11 @@ const GRState *GRState::remove(typename GRStateTrait<T>::key_type K, return getStateManager().remove<T>(this, K, C); } +template <typename T> +const GRState *GRState::remove() const { + return getStateManager().remove<T>(this); +} + template<typename T> const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const { return getStateManager().set<T>(this, D); diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index f2cd0486e326..d2e7457ea93d 100644 --- a/include/clang/Checker/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -20,6 +20,7 @@ namespace clang { class Stmt; class CFGBlock; class CFGElement; +class ExplodedNode; class GRState; class GRStateManager; class GRBlockCounter; @@ -47,7 +48,7 @@ public: /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue /// exploring the given path, and false otherwise. - virtual bool ProcessBlockEntrance(CFGBlock* B, const GRState* St, + virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, GRBlockCounter BC) = 0; /// ProcessBranch - Called by GRCoreEngine. Used to generate successor diff --git a/include/clang/Checker/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h index 04634effd587..13325edea778 100644 --- a/include/clang/Checker/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Checker/PathSensitive/GRTransferFuncs.h @@ -15,16 +15,18 @@ #ifndef LLVM_CLANG_ANALYSIS_GRTF #define LLVM_CLANG_ANALYSIS_GRTF -#include "clang/Checker/PathSensitive/SVals.h" -#include "clang/Checker/PathSensitive/GRCoreEngine.h" #include "clang/Checker/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/SVals.h" #include <vector> namespace clang { - +class ExplodedNode; +class ExplodedNodeSet; +class GREndPathNodeBuilder; class GRExprEngine; -class ObjCMessageExpr; +class GRStmtNodeBuilder; class GRStmtNodeBuilderRef; +class ObjCMessageExpr; class GRTransferFuncs { public: diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index be89d2a3eb88..57ea8a3f6d9d 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -18,17 +18,15 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" -#include "clang/Checker/PathSensitive/SymbolManager.h" #include "clang/Checker/PathSensitive/SVals.h" -#include "clang/AST/ASTContext.h" #include "llvm/Support/Casting.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/ImmutableList.h" -#include "llvm/ADT/ImmutableMap.h" -#include "llvm/Support/Allocator.h" #include <string> -namespace llvm { class raw_ostream; } +namespace llvm { +class BumpPtrAllocator; +class raw_ostream; +} namespace clang { diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index edc338012ada..72565f4d740d 100644 --- a/include/clang/Checker/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -18,9 +18,6 @@ #include "clang/Checker/PathSensitive/SVals.h" #include "clang/Checker/PathSensitive/ValueManager.h" #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h" namespace clang { diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h index b6630c3d97d2..dea877c0657f 100644 --- a/include/clang/Checker/PathSensitive/SymbolManager.h +++ b/include/clang/Checker/PathSensitive/SymbolManager.h @@ -17,14 +17,14 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" -#include "clang/Analysis/Analyses/LiveVariables.h" +#include "clang/Analysis/AnalysisContext.h" #include "llvm/System/DataTypes.h" -#include "llvm/Support/Allocator.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/DenseSet.h" namespace llvm { - class raw_ostream; +class BumpPtrAllocator; +class raw_ostream; } namespace clang { @@ -34,9 +34,6 @@ namespace clang { class TypedRegion; class VarRegion; class StackFrameContext; -} - -namespace clang { class SymExpr : public llvm::FoldingSetNode { public: @@ -247,6 +244,7 @@ public: QualType t) : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} + BinaryOperator::Opcode getOpcode() const { return Op; } const SymExpr *getLHS() const { return LHS; } const SymExpr *getRHS() const { return RHS; } diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index 85c6c3e3abcf..638ed516ed0b 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -15,7 +15,6 @@ #define LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H #include <string> -#include <vector> namespace clang { diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index feebbc78864f..124288a76305 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -156,6 +156,7 @@ def dependency_file : Separate<"-dependency-file">, HelpText<"Filename (or -) to write dependency output to">; def sys_header_deps : Flag<"-sys-header-deps">, HelpText<"Include system headers in dependency output">; +def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">; def MT : Separate<"-MT">, HelpText<"Specify target for dependency">; def MP : Flag<"-MP">, HelpText<"Create phony target for each dependency (other than main file)">; @@ -407,6 +408,8 @@ def fwritable_strings : Flag<"-fwritable-strings">, def nostdinc : Flag<"-nostdinc">, HelpText<"Disable standard #include directories">; +def nostdincxx : Flag<"-nostdinc++">, + HelpText<"Disable standard #include directories for the C++ standard library">; def nobuiltininc : Flag<"-nobuiltininc">, HelpText<"Disable builtin #include directories">; def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">, diff --git a/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt index f720d15d8ccc..ed9825b59df5 100644 --- a/include/clang/Driver/CMakeLists.txt +++ b/include/clang/Driver/CMakeLists.txt @@ -2,10 +2,10 @@ set(LLVM_TARGET_DEFINITIONS Options.td) tablegen(Options.inc -gen-opt-parser-defs) add_custom_target(ClangDriverOptions - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Options.inc) + DEPENDS Options.inc) set(LLVM_TARGET_DEFINITIONS CC1Options.td) tablegen(CC1Options.inc -gen-opt-parser-defs) add_custom_target(ClangCC1Options - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/CC1Options.inc) + DEPENDS CC1Options.inc) diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index f49c3b97c1c4..90c3a0dcdc18 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -64,6 +64,12 @@ public: /// The path to the compiler resource directory. std::string ResourceDir; + /// A prefix directory used to emulated a limited subset of GCC's '-Bprefix' + /// functionality. + /// FIXME: This type of customization should be removed in favor of the + /// universal driver when it is ready. + std::string PrefixDir; + /// Default host triple. std::string DefaultHostTriple; @@ -133,7 +139,8 @@ public: Driver(llvm::StringRef _Name, llvm::StringRef _Dir, llvm::StringRef _DefaultHostTriple, llvm::StringRef _DefaultImageName, - bool IsProduction, Diagnostic &_Diags); + bool IsProduction, bool CXXIsProduction, + Diagnostic &_Diags); ~Driver(); /// @name Accessors diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 71258f9814be..d088be04c03e 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -118,7 +118,7 @@ def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>; def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>, HelpText<"Print the commands to run for this compilation">; def A : JoinedOrSeparate<"-A">; -def B : JoinedOrSeparate<"-B">, Flags<[Unsupported]>; +def B : JoinedOrSeparate<"-B">; def CC : Flag<"-CC">; def C : Flag<"-C">; def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>; @@ -470,6 +470,7 @@ def noprebind : Flag<"-noprebind">; def noseglinkedit : Flag<"-noseglinkedit">; def nostartfiles : Flag<"-nostartfiles">; def nostdinc : Flag<"-nostdinc">; +def nostdincxx : Flag<"-nostdinc++">; def nostdlib : Flag<"-nostdlib">; def object : Flag<"-object">; def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput]>, diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index 690408547c0d..c6682451835a 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -71,13 +71,17 @@ public: /// Include the system standard include search directories. unsigned UseStandardIncludes : 1; + /// Include the system standard C++ library include search directories. + unsigned UseStandardCXXIncludes : 1; + /// Whether header search information should be output as for -v. unsigned Verbose : 1; public: HeaderSearchOptions(llvm::StringRef _Sysroot = "/") : Sysroot(_Sysroot), UseBuiltinIncludes(true), - UseStandardIncludes(true), Verbose(false) {} + UseStandardIncludes(true), UseStandardCXXIncludes(true), + Verbose(false) {} /// AddPath - Add the \arg Path path to the specified \arg Group list. void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group, diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index d09e51fd0184..157876b59d34 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -69,7 +69,7 @@ public: void EmitCaretDiagnostic(SourceLocation Loc, SourceRange *Ranges, unsigned NumRanges, SourceManager &SM, - const CodeModificationHint *Hints, + const FixItHint *Hints, unsigned NumHints, unsigned Columns); diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def index dd5018af82aa..3add99a941c4 100644 --- a/include/clang/Frontend/TypeXML.def +++ b/include/clang/Frontend/TypeXML.def @@ -233,7 +233,7 @@ NODE_XML(QualifiedNameType, "QualifiedNameType") TYPE_ATTRIBUTE_XML(getNamedType()) END_NODE_XML -NODE_XML(TypenameType, "TypenameType") +NODE_XML(DependentNameType, "DependentNameType") ID_ATTRIBUTE_XML END_NODE_XML diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index dd24fb7d7ba2..e891e94d4cbc 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -44,6 +44,12 @@ public: SrcMgr::CharacteristicKind FileType) { } + + /// EndOfMainFile - This callback is invoked when the end of the main file is + /// reach, no subsequent callbacks will be made. + virtual void EndOfMainFile() { + } + /// Ident - This callback is invoked when a #ident or #sccs directive is read. /// virtual void Ident(SourceLocation Loc, const std::string &str) { @@ -90,6 +96,11 @@ public: Second->FileChanged(Loc, Reason, FileType); } + virtual void EndOfMainFile() { + First->EndOfMainFile(); + Second->EndOfMainFile(); + } + virtual void Ident(SourceLocation Loc, const std::string &str) { First->Ident(Loc, str); Second->Ident(Loc, str); diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 23c118d1fc63..312a760e01d3 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -368,6 +368,10 @@ public: /// which implicitly adds the builtin defines etc. bool EnterMainSourceFile(); + /// EndSourceFile - Inform the preprocessor callbacks that processing is + /// complete. + void EndSourceFile(); + /// EnterSourceFile - Add a source file to the top of the include stack and /// start lexing tokens from it instead of the current buffer. Return true /// and fill in ErrorStr with the error information on failure. diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index 85c44c5a0b80..477a2130cf0e 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -21,6 +21,7 @@ namespace clang { +class FileEntry; class Preprocessor; class PreprocessorLexer { diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index b79e698d50c9..59cc0d218cec 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1761,7 +1761,8 @@ public: virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, DeclPtrTy TagDecl, SourceLocation LBrac, - SourceLocation RBrac) { + SourceLocation RBrac, + AttributeList *AttrList) { } //===---------------------------C++ Templates----------------------------===// |