diff options
author | Roman Divacky <rdivacky@FreeBSD.org> | 2009-11-18 14:59:57 +0000 |
---|---|---|
committer | Roman Divacky <rdivacky@FreeBSD.org> | 2009-11-18 14:59:57 +0000 |
commit | b3d5a323a5ca92ea73443499cee2f15db1ff0fb3 (patch) | |
tree | 60a1694bec5a44d15456acc880cb2f91619f66aa /include/clang | |
parent | 8f57cb0305232cb53fff00ef151ca716766f3437 (diff) | |
download | src-b3d5a323a5ca92ea73443499cee2f15db1ff0fb3.tar.gz src-b3d5a323a5ca92ea73443499cee2f15db1ff0fb3.zip |
Update clang to r89205.
Notes
Notes:
svn path=/vendor/clang/dist/; revision=199482
Diffstat (limited to 'include/clang')
91 files changed, 3317 insertions, 919 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 7392170be995..f9d2f71b1f28 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -37,6 +37,7 @@ namespace llvm { namespace clang { class FileManager; class ASTRecordLayout; + class BlockExpr; class Expr; class ExternalASTSource; class IdentifierTable; @@ -55,7 +56,6 @@ namespace clang { class TranslationUnitDecl; class TypeDecl; class TypedefDecl; - class UnresolvedUsingDecl; class UsingDecl; namespace Builtin { class Context; } @@ -204,7 +204,7 @@ class ASTContext { /// /// This mapping will contain an entry that maps from the UsingDecl in /// B<int> to the UnresolvedUsingDecl in B<T>. - llvm::DenseMap<UsingDecl *, UnresolvedUsingDecl *> + llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUnresolvedUsingDecl; llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; @@ -232,7 +232,7 @@ class ASTContext { llvm::DenseMap<const Decl *, std::string> DeclComments; public: - TargetInfo &Target; + const TargetInfo &Target; IdentifierTable &Idents; SelectorTable &Selectors; Builtin::Context &BuiltinInfo; @@ -284,12 +284,11 @@ public: /// \brief If this using decl is instantiated from an unresolved using decl, /// return it. - UnresolvedUsingDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); + NamedDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); /// \brief Note that the using decl \p Inst is an instantiation of /// the unresolved using decl \p Tmpl of a class template. - void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, - UnresolvedUsingDecl *Tmpl); + void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl); FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); @@ -319,7 +318,7 @@ public: CanQualType UndeducedAutoTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy; - ASTContext(const LangOptions& LOpts, SourceManager &SM, TargetInfo &t, + ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, bool FreeMemory = true, unsigned size_reserve=0); @@ -672,6 +671,10 @@ public: /// declaration. void getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, std::string &S); + /// getObjCEncodingForBlockDecl - Return the encoded type for this block + /// declaration. + void getObjCEncodingForBlock(const BlockExpr *Expr, std::string& S); + /// getObjCEncodingForPropertyDecl - Return the encoded type for /// this method declaration. If non-NULL, Container must be either /// an ObjCCategoryImplDecl or ObjCImplementationDecl; it should @@ -872,9 +875,9 @@ public: /// \brief Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. bool hasSameUnqualifiedType(QualType T1, QualType T2) { - T1 = getCanonicalType(T1); - T2 = getCanonicalType(T2); - return T1.getUnqualifiedType() == T2.getUnqualifiedType(); + CanQualType CT1 = getCanonicalType(T1); + CanQualType CT2 = getCanonicalType(T2); + return CT1.getUnqualifiedType() == CT2.getUnqualifiedType(); } /// \brief Retrieves the "canonical" declaration of @@ -925,6 +928,10 @@ public: /// types, values, and templates. TemplateName getCanonicalTemplateName(TemplateName Name); + /// \brief Determine whether the given template names refer to the same + /// template. + bool hasSameTemplateName(TemplateName X, TemplateName Y); + /// \brief Retrieve the "canonical" template argument. /// /// The canonical template argument is the simplest template argument diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index f7a47364a7f6..b36ff1229376 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -50,6 +50,7 @@ public: Annotate, AsmLabel, // Represent GCC asm label extension. Blocks, + CDecl, Cleanup, Const, Constructor, @@ -442,6 +443,7 @@ DEF_SIMPLE_ATTR(DLLImport); DEF_SIMPLE_ATTR(DLLExport); DEF_SIMPLE_ATTR(FastCall); DEF_SIMPLE_ATTR(StdCall); +DEF_SIMPLE_ATTR(CDecl); DEF_SIMPLE_ATTR(TransparentUnion); DEF_SIMPLE_ATTR(ObjCNSObject); DEF_SIMPLE_ATTR(ObjCException); diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index a7750517090e..9b1187770f6a 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -71,6 +71,9 @@ public: /// \brief Implicit conversion to a qualified type. operator QualType() const { return Stored; } + /// \brief Implicit conversion to bool. + operator bool() const { return !isNull(); } + bool isNull() const { return Stored.isNull(); } @@ -99,22 +102,22 @@ public: CanProxy<T> operator->() const; /// \brief Retrieve all qualifiers. - Qualifiers getQualifiers() const { return Stored.getQualifiers(); } + Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); } /// \brief Retrieve the const/volatile/restrict qualifiers. - unsigned getCVRQualifiers() const { return Stored.getCVRQualifiers(); } + unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); } /// \brief Determines whether this type has any qualifiers - bool hasQualifiers() const { return Stored.hasQualifiers(); } + bool hasQualifiers() const { return Stored.hasLocalQualifiers(); } bool isConstQualified() const { - return Stored.isConstQualified(); + return Stored.isLocalConstQualified(); } bool isVolatileQualified() const { - return Stored.isVolatileQualified(); + return Stored.isLocalVolatileQualified(); } bool isRestrictQualified() const { - return Stored.isRestrictQualified(); + return Stored.isLocalRestrictQualified(); } /// \brief Retrieve the unqualified form of this type. @@ -635,7 +638,7 @@ struct CanProxyAdaptor<ObjCObjectPointerType> //----------------------------------------------------------------------------// template<typename T> inline CanQual<T> CanQual<T>::getUnqualifiedType() const { - return CanQual<T>::CreateUnsafe(Stored.getUnqualifiedType()); + return CanQual<T>::CreateUnsafe(Stored.getLocalUnqualifiedType()); } template<typename T> diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 813e83accdb1..ac79a91792d7 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -232,6 +232,7 @@ public: void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; } virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; } + const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; } virtual SourceRange getSourceRange() const { return SourceRange(getLocation(), RBracLoc); @@ -552,6 +553,9 @@ public: } virtual VarDecl *getCanonicalDecl(); + const VarDecl *getCanonicalDecl() const { + return const_cast<VarDecl*>(this)->getCanonicalDecl(); + } /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. @@ -1424,6 +1428,9 @@ public: virtual SourceRange getSourceRange() const; virtual TagDecl* getCanonicalDecl(); + const TagDecl* getCanonicalDecl() const { + return const_cast<TagDecl*>(this)->getCanonicalDecl(); + } /// isDefinition - Return true if this decl has its body specified. bool isDefinition() const { @@ -1515,6 +1522,9 @@ public: EnumDecl *getCanonicalDecl() { return cast<EnumDecl>(TagDecl::getCanonicalDecl()); } + const EnumDecl *getCanonicalDecl() const { + return cast<EnumDecl>(TagDecl::getCanonicalDecl()); + } static EnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 10db7030db18..79f766356138 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -79,9 +79,11 @@ public: /// namespaces, labels, tags, members and ordinary /// identifiers. These are meant as bitmasks, so that searches in /// C++ can look into the "tag" namespace during ordinary lookup. We - /// use additional namespaces for Objective-C entities. We also - /// put C++ friend declarations (of previously-undeclared entities) in - /// shadow namespaces. + /// use additional namespaces for Objective-C entities. We also put + /// C++ friend declarations (of previously-undeclared entities) in + /// shadow namespaces, and 'using' declarations (as opposed to their + /// implicit shadow declarations) can be found in their own + /// namespace. enum IdentifierNamespace { IDNS_Label = 0x1, IDNS_Tag = 0x2, @@ -91,7 +93,8 @@ public: IDNS_ObjCImplementation = 0x20, IDNS_ObjCCategoryImpl = 0x40, IDNS_OrdinaryFriend = 0x80, - IDNS_TagFriend = 0x100 + IDNS_TagFriend = 0x100, + IDNS_Using = 0x200 }; /// ObjCDeclQualifier - Qualifier used on types in method declarations diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index c858c5c0df78..e5bf78cd10d2 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -432,6 +432,9 @@ public: virtual CXXRecordDecl *getCanonicalDecl() { return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); } + virtual const CXXRecordDecl *getCanonicalDecl() const { + return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); + } static CXXRecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -768,7 +771,7 @@ public: /// \param Base the base class we are searching for. /// /// \returns true if this class is derived from Base, false otherwise. - bool isDerivedFrom(CXXRecordDecl *Base); + bool isDerivedFrom(CXXRecordDecl *Base) const; /// \brief Determine whether this class is derived from the type \p Base. /// @@ -786,7 +789,7 @@ public: /// /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than /// tangling input and output in \p Paths - bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths); + bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const; /// \brief Function type used by lookupInBases() to determine whether a /// specific base class subobject matches the lookup criteria. @@ -801,7 +804,7 @@ public: /// lookupInBases(). /// /// \returns true if this base matched the search criteria, false otherwise. - typedef bool BaseMatchesCallback(CXXBaseSpecifier *Specifier, + typedef bool BaseMatchesCallback(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData); @@ -826,7 +829,7 @@ public: /// \returns true if there exists any path from this class to a base class /// subobject that matches the search criteria. bool lookupInBases(BaseMatchesCallback *BaseMatches, void *UserData, - CXXBasePaths &Paths); + CXXBasePaths &Paths) const; /// \brief Base-class lookup callback that determines whether the given /// base class specifier refers to a specific class declaration. @@ -835,8 +838,8 @@ public: /// a given derived class has is a base class subobject of a particular type. /// The user data pointer should refer to the canonical CXXRecordDecl of the /// base class that we are searching for. - static bool FindBaseClass(CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *BaseRecord); + static bool FindBaseClass(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *BaseRecord); /// \brief Base-class lookup callback that determines whether there exists /// a tag with the given name. @@ -844,8 +847,8 @@ public: /// This callback can be used with \c lookupInBases() to find tag members /// of the given name within a C++ class hierarchy. The user data pointer /// is an opaque \c DeclarationName pointer. - static bool FindTagMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *Name); + static bool FindTagMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *Name); /// \brief Base-class lookup callback that determines whether there exists /// a member with the given name. @@ -853,8 +856,8 @@ public: /// This callback can be used with \c lookupInBases() to find members /// of the given name within a C++ class hierarchy. The user data pointer /// is an opaque \c DeclarationName pointer. - static bool FindOrdinaryMember(CXXBaseSpecifier *Specifier, CXXBasePath &Path, - void *Name); + static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, void *Name); /// \brief Base-class lookup callback that determines whether there exists /// a member with the given name that can be used in a nested-name-specifier. @@ -862,7 +865,7 @@ public: /// This callback can be used with \c lookupInBases() to find membes of /// the given name within a C++ class hierarchy that can occur within /// nested-name-specifiers. - static bool FindNestedNameSpecifierMember(CXXBaseSpecifier *Specifier, + static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, void *UserData); @@ -1244,6 +1247,11 @@ public: /// used for user-defined conversions. bool isConvertingConstructor(bool AllowExplicit) const; + /// \brief Determine whether this is a member template specialization that + /// looks like a copy constructor. Such constructors are never used to copy + /// an object. + bool isCopyConstructorLikeSpecialization() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == CXXConstructor; @@ -1261,13 +1269,6 @@ public: /// }; /// @endcode class CXXDestructorDecl : public CXXMethodDecl { -public: - enum KindOfObjectToDestroy { - VBASE = 0x1, - DRCTNONVBASE = 0x2, - ANYBASE = 0x3 - }; -private: /// ImplicitlyDefined - Whether this destructor was implicitly /// defined by the compiler. When false, the destructor was defined /// by the user. In C++03, this flag will have the same value as @@ -1276,24 +1277,15 @@ private: /// @c !Implicit && ImplicitlyDefined. bool ImplicitlyDefined : 1; - /// Support for base and member destruction. - /// BaseOrMemberDestructions - The arguments used to destruct the base - /// or member. Each uintptr_t value represents one of base classes (either - /// virtual or direct non-virtual base), or non-static data member - /// to be destroyed. The low two bits encode the kind of object - /// being destroyed. - uintptr_t *BaseOrMemberDestructions; - unsigned NumBaseOrMemberDestructions; - + FunctionDecl *OperatorDelete; + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, bool isImplicitlyDeclared) : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline), - ImplicitlyDefined(false), - BaseOrMemberDestructions(0), NumBaseOrMemberDestructions(0) { + ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } - virtual void Destroy(ASTContext& C); public: static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, @@ -1319,95 +1311,8 @@ public: ImplicitlyDefined = ID; } - /// destr_iterator - Iterates through the member/base destruction list. - - /// destr_const_iterator - Iterates through the member/base destruction list. - typedef uintptr_t const destr_const_iterator; - - /// destr_begin() - Retrieve an iterator to the first destructed member/base. - uintptr_t* destr_begin() { - return BaseOrMemberDestructions; - } - /// destr_begin() - Retrieve an iterator to the first destructed member/base. - uintptr_t* destr_begin() const { - return BaseOrMemberDestructions; - } - - /// destr_end() - Retrieve an iterator past the last destructed member/base. - uintptr_t* destr_end() { - return BaseOrMemberDestructions + NumBaseOrMemberDestructions; - } - /// destr_end() - Retrieve an iterator past the last destructed member/base. - uintptr_t* destr_end() const { - return BaseOrMemberDestructions + NumBaseOrMemberDestructions; - } - - /// getNumBaseOrMemberDestructions - Number of base and non-static members - /// to destroy. - unsigned getNumBaseOrMemberDestructions() const { - return NumBaseOrMemberDestructions; - } - - /// setNumBaseOrMemberDestructions - Set number of base and non-static members - /// to destroy. - void setNumBaseOrMemberDestructions(unsigned numBaseOrMemberDestructions) { - NumBaseOrMemberDestructions = numBaseOrMemberDestructions; - } - - /// getBaseOrMemberToDestroy - get the generic 'member' representing either - /// the field or a base class. - uintptr_t* getBaseOrMemberToDestroy() const { - return BaseOrMemberDestructions; - } - - /// setBaseOrMemberToDestroy - set the generic 'member' representing either - /// the field or a base class. - void setBaseOrMemberDestructions(uintptr_t* baseOrMemberDestructions) { - BaseOrMemberDestructions = baseOrMemberDestructions; - } - - /// isVbaseToDestroy - returns true, if object is virtual base. - bool isVbaseToDestroy(uintptr_t Vbase) const { - return (Vbase & VBASE) != 0; - } - /// isDirectNonVBaseToDestroy - returns true, if object is direct non-virtual - /// base. - bool isDirectNonVBaseToDestroy(uintptr_t DrctNonVbase) const { - return (DrctNonVbase & DRCTNONVBASE) != 0; - } - /// isAnyBaseToDestroy - returns true, if object is any base (virtual or - /// direct non-virtual) - bool isAnyBaseToDestroy(uintptr_t AnyBase) const { - return (AnyBase & ANYBASE) != 0; - } - /// isMemberToDestroy - returns true if object is a non-static data member. - bool isMemberToDestroy(uintptr_t Member) const { - return (Member & ANYBASE) == 0; - } - /// getAnyBaseClassToDestroy - Get the type for the given base class object. - Type *getAnyBaseClassToDestroy(uintptr_t Base) const { - if (isAnyBaseToDestroy(Base)) - return reinterpret_cast<Type*>(Base & ~0x03); - return 0; - } - /// getMemberToDestroy - Get the member for the given object. - FieldDecl *getMemberToDestroy(uintptr_t Member) const { - if (isMemberToDestroy(Member)) - return reinterpret_cast<FieldDecl *>(Member); - return 0; - } - /// getVbaseClassToDestroy - Get the virtual base. - Type *getVbaseClassToDestroy(uintptr_t Vbase) const { - if (isVbaseToDestroy(Vbase)) - return reinterpret_cast<Type*>(Vbase & ~0x01); - return 0; - } - /// getDirectNonVBaseClassToDestroy - Get the virtual base. - Type *getDirectNonVBaseClassToDestroy(uintptr_t Base) const { - if (isDirectNonVBaseToDestroy(Base)) - return reinterpret_cast<Type*>(Base & ~0x02); - return 0; - } + void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; } + const FunctionDecl *getOperatorDelete() const { return OperatorDelete; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { @@ -1739,6 +1644,56 @@ public: static bool classof(const NamespaceAliasDecl *D) { return true; } }; +/// UsingShadowDecl - Represents a shadow declaration introduced into +/// a scope by a (resolved) using declaration. For example, +/// +/// namespace A { +/// void foo(); +/// } +/// namespace B { +/// using A::foo(); // <- a UsingDecl +/// // Also creates a UsingShadowDecl for A::foo in B +/// } +/// +class UsingShadowDecl : public NamedDecl { + /// The referenced declaration. + NamedDecl *Underlying; + + /// The using declaration which introduced this decl. + UsingDecl *Using; + + UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using, + NamedDecl *Target) + : NamedDecl(UsingShadow, DC, Loc, Target->getDeclName()), + Underlying(Target), Using(Using) { + IdentifierNamespace = Target->getIdentifierNamespace(); + setImplicit(); + } + +public: + static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation Loc, UsingDecl *Using, + NamedDecl *Target) { + return new (C) UsingShadowDecl(DC, Loc, Using, Target); + } + + /// Gets the underlying declaration which has been brought into the + /// local scope. + NamedDecl *getTargetDecl() const { + return Underlying; + } + + /// Gets the using declaration to which this declaration is tied. + UsingDecl *getUsingDecl() const { + return Using; + } + + static bool classof(const Decl *D) { + return D->getKind() == Decl::UsingShadow; + } + static bool classof(const UsingShadowDecl *D) { return true; } +}; + /// UsingDecl - Represents a C++ using-declaration. For example: /// using someNameSpace::someIdentifier; class UsingDecl : public NamedDecl { @@ -1746,29 +1701,26 @@ class UsingDecl : public NamedDecl { /// preceding the declaration name. SourceRange NestedNameRange; - /// \brief The source location of the target declaration name. - SourceLocation TargetNameLocation; - /// \brief The source location of the "using" location itself. SourceLocation UsingLocation; - /// \brief Target declaration. - NamedDecl* TargetDecl; - /// \brief Target nested name specifier. - NestedNameSpecifier* TargetNestedNameDecl; + NestedNameSpecifier* TargetNestedName; + + /// \brief The collection of shadow declarations associated with + /// this using declaration. This set can change as a class is + /// processed. + llvm::SmallPtrSet<UsingShadowDecl*, 8> Shadows; // \brief Has 'typename' keyword. bool IsTypeName; UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR, - SourceLocation TargetNL, SourceLocation UL, NamedDecl* Target, - NestedNameSpecifier* TargetNNS, bool IsTypeNameArg) - : NamedDecl(Decl::Using, DC, L, Target->getDeclName()), - NestedNameRange(NNR), TargetNameLocation(TargetNL), - UsingLocation(UL), TargetDecl(Target), - TargetNestedNameDecl(TargetNNS), IsTypeName(IsTypeNameArg) { - this->IdentifierNamespace = TargetDecl->getIdentifierNamespace(); + SourceLocation UL, NestedNameSpecifier* TargetNNS, + DeclarationName Name, bool IsTypeNameArg) + : NamedDecl(Decl::Using, DC, L, Name), + NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), + IsTypeName(IsTypeNameArg) { } public: @@ -1776,28 +1728,37 @@ public: /// preceding the namespace name. SourceRange getNestedNameRange() { return NestedNameRange; } - /// \brief Returns the source location of the target declaration name. - SourceLocation getTargetNameLocation() { return TargetNameLocation; } - /// \brief Returns the source location of the "using" location itself. SourceLocation getUsingLocation() { return UsingLocation; } - /// \brief getTargetDecl - Returns target specified by using-decl. - NamedDecl *getTargetDecl() { return TargetDecl; } - const NamedDecl *getTargetDecl() const { return TargetDecl; } - /// \brief Get target nested name declaration. NestedNameSpecifier* getTargetNestedNameDecl() { - return TargetNestedNameDecl; + return TargetNestedName; } /// isTypeName - Return true if using decl has 'typename'. bool isTypeName() const { return IsTypeName; } + typedef llvm::SmallPtrSet<UsingShadowDecl*,8>::const_iterator shadow_iterator; + shadow_iterator shadow_begin() const { return Shadows.begin(); } + shadow_iterator shadow_end() const { return Shadows.end(); } + + void addShadowDecl(UsingShadowDecl *S) { + assert(S->getUsingDecl() == this); + if (!Shadows.insert(S)) { + assert(false && "declaration already in set"); + } + } + void removeShadowDecl(UsingShadowDecl *S) { + assert(S->getUsingDecl() == this); + if (!Shadows.erase(S)) { + assert(false && "declaration not in set"); + } + } + static UsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, SourceRange NNR, SourceLocation TargetNL, - SourceLocation UL, NamedDecl* Target, - NestedNameSpecifier* TargetNNS, bool IsTypeNameArg); + SourceLocation IdentL, SourceRange NNR, SourceLocation UsingL, + NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg); static bool classof(const Decl *D) { return D->getKind() == Decl::Using; @@ -1805,31 +1766,88 @@ public: static bool classof(const UsingDecl *D) { return true; } }; -/// UnresolvedUsingDecl - Represents a using declaration whose name can not -/// yet be resolved. -class UnresolvedUsingDecl : public NamedDecl { +/// UnresolvedUsingValueDecl - Represents a dependent using +/// declaration which was not marked with 'typename'. Unlike +/// non-dependent using declarations, these *only* bring through +/// non-types; otherwise they would break two-phase lookup. +/// +/// template <class T> class A : public Base<T> { +/// using Base<T>::foo; +/// }; +class UnresolvedUsingValueDecl : public ValueDecl { /// \brief The source range that covers the nested-name-specifier /// preceding the declaration name. SourceRange TargetNestedNameRange; - /// \brief The source location of the target declaration name. - SourceLocation TargetNameLocation; + /// \brief The source location of the 'using' keyword + SourceLocation UsingLocation; NestedNameSpecifier *TargetNestedNameSpecifier; - DeclarationName TargetName; + UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, + SourceLocation UsingLoc, SourceRange TargetNNR, + NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, + DeclarationName TargetName) + : ValueDecl(Decl::UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty), + TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), + TargetNestedNameSpecifier(TargetNNS) + { } - // \brief Has 'typename' keyword. - bool IsTypeName; +public: + /// \brief Returns the source range that covers the nested-name-specifier + /// preceding the namespace name. + SourceRange getTargetNestedNameRange() const { return TargetNestedNameRange; } - UnresolvedUsingDecl(DeclContext *DC, SourceLocation UsingLoc, - SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, DeclarationName TargetName, - bool IsTypeNameArg) - : NamedDecl(Decl::UnresolvedUsing, DC, UsingLoc, TargetName), - TargetNestedNameRange(TargetNNR), TargetNameLocation(TargetNameLoc), - TargetNestedNameSpecifier(TargetNNS), TargetName(TargetName), - IsTypeName(IsTypeNameArg) { } + /// \brief Get target nested name declaration. + NestedNameSpecifier* getTargetNestedNameSpecifier() { + return TargetNestedNameSpecifier; + } + + /// \brief Returns the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } + + static UnresolvedUsingValueDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, DeclarationName TargetName); + + static bool classof(const Decl *D) { + return D->getKind() == Decl::UnresolvedUsingValue; + } + static bool classof(const UnresolvedUsingValueDecl *D) { return true; } +}; + +/// UnresolvedUsingTypenameDecl - Represents a dependent using +/// declaration which was marked with 'typename'. +/// +/// template <class T> class A : public Base<T> { +/// using typename Base<T>::foo; +/// }; +/// +/// The type associated with a unresolved using typename decl is +/// currently always a typename type. +class UnresolvedUsingTypenameDecl : public TypeDecl { + /// \brief The source range that covers the nested-name-specifier + /// preceding the declaration name. + SourceRange TargetNestedNameRange; + + /// \brief The source location of the 'using' keyword + SourceLocation UsingLocation; + + /// \brief The source location of the 'typename' keyword + SourceLocation TypenameLocation; + + NestedNameSpecifier *TargetNestedNameSpecifier; + + UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc, + SourceLocation TypenameLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, IdentifierInfo *TargetName) + : TypeDecl(Decl::UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), + TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), + TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) + { } public: /// \brief Returns the source range that covers the nested-name-specifier @@ -1841,26 +1859,22 @@ public: return TargetNestedNameSpecifier; } - /// \brief Returns the source location of the target declaration name. - SourceLocation getTargetNameLocation() const { return TargetNameLocation; } + /// \brief Returns the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } - /// \brief Returns the source location of the target declaration name. - DeclarationName getTargetName() const { return TargetName; } - - bool isTypeName() const { return IsTypeName; } + /// \brief Returns the source location of the 'typename' keyword. + SourceLocation getTypenameLoc() const { return TypenameLocation; } - static UnresolvedUsingDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation UsingLoc, - SourceRange TargetNNR, - NestedNameSpecifier *TargetNNS, - SourceLocation TargetNameLoc, - DeclarationName TargetName, - bool IsTypeNameArg); + static UnresolvedUsingTypenameDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, + SourceLocation TypenameLoc, + SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, + SourceLocation TargetNameLoc, DeclarationName TargetName); static bool classof(const Decl *D) { - return D->getKind() == Decl::UnresolvedUsing; + return D->getKind() == Decl::UnresolvedUsingTypename; } - static bool classof(const UnresolvedUsingDecl *D) { return true; } + static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } }; /// StaticAssertDecl - Represents a C++0x static_assert declaration. diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index d9e40d478907..c2b48cee36f4 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -14,8 +14,9 @@ #ifndef LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H #define LLVM_CLANG_AST_DECLCONTEXTINTERNALS_H -#include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/DeclCXX.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index 3ef3cc3f0975..ec1b3b055cab 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -81,6 +81,7 @@ ABSTRACT_DECL(Named, Decl) DECL(NamespaceAlias, NamedDecl) ABSTRACT_DECL(Type, NamedDecl) DECL(Typedef, TypeDecl) + DECL(UnresolvedUsingTypename, TypeDecl) ABSTRACT_DECL(Tag, TypeDecl) DECL(Enum, TagDecl) DECL(Record, TagDecl) @@ -91,6 +92,7 @@ ABSTRACT_DECL(Named, Decl) DECL(TemplateTypeParm, TypeDecl) ABSTRACT_DECL(Value, NamedDecl) DECL(EnumConstant, ValueDecl) + DECL(UnresolvedUsingValue, ValueDecl) ABSTRACT_DECL(Declarator, ValueDecl) DECL(Function, DeclaratorDecl) DECL(CXXMethod, FunctionDecl) @@ -109,7 +111,7 @@ ABSTRACT_DECL(Named, Decl) DECL(ClassTemplate, TemplateDecl) DECL(TemplateTemplateParm, TemplateDecl) DECL(Using, NamedDecl) - DECL(UnresolvedUsing, NamedDecl) + DECL(UsingShadow, NamedDecl) DECL(ObjCMethod, NamedDecl) DECL(ObjCContainer, NamedDecl) DECL(ObjCCategory, ObjCContainerDecl) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index bcd28eab039f..13193ffab55e 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -718,10 +718,22 @@ public: /// @class NSCursor, NSImage, NSPasteboard, NSWindow; /// class ObjCClassDecl : public Decl { - ObjCList<ObjCInterfaceDecl> ForwardDecls; +public: + class ObjCClassRef { + ObjCInterfaceDecl *ID; + SourceLocation L; + public: + ObjCClassRef(ObjCInterfaceDecl *d, SourceLocation l) : ID(d), L(l) {} + SourceLocation getLocation() const { return L; } + ObjCInterfaceDecl *getInterface() const { return ID; } + }; +private: + ObjCClassRef *ForwardDecls; + unsigned NumDecls; ObjCClassDecl(DeclContext *DC, SourceLocation L, - ObjCInterfaceDecl *const *Elts, unsigned nElts, ASTContext &C); + ObjCInterfaceDecl *const *Elts, const SourceLocation *Locs, + unsigned nElts, ASTContext &C); virtual ~ObjCClassDecl() {} public: @@ -730,17 +742,19 @@ public: static ObjCClassDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, ObjCInterfaceDecl *const *Elts = 0, + const SourceLocation *Locs = 0, unsigned nElts = 0); + + virtual SourceRange getSourceRange() const; - typedef ObjCList<ObjCInterfaceDecl>::iterator iterator; - iterator begin() const { return ForwardDecls.begin(); } - iterator end() const { return ForwardDecls.end(); } - unsigned size() const { return ForwardDecls.size(); } + typedef const ObjCClassRef* iterator; + iterator begin() const { return ForwardDecls; } + iterator end() const { return ForwardDecls + NumDecls; } + unsigned size() const { return NumDecls; } /// setClassList - Set the list of forward classes. - void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, unsigned Num) { - ForwardDecls.set(List, Num, C); - } + void setClassList(ASTContext &C, ObjCInterfaceDecl*const*List, + const SourceLocation *Locs, unsigned Num); static bool classof(const Decl *D) { return D->getKind() == ObjCClass; } static bool classof(const ObjCClassDecl *D) { return true; } diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index f1a27933a1b3..14f666005cd6 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -699,13 +699,13 @@ class TemplateTemplateParmDecl : public TemplateDecl, protected TemplateParmPosition { /// \brief The default template argument, if any. - Expr *DefaultArgument; + TemplateArgumentLoc DefaultArgument; TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), DefaultArgument(0) + TemplateParmPosition(D, P), DefaultArgument() { } public: @@ -720,16 +720,17 @@ public: /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return DefaultArgument; } + bool hasDefaultArgument() const { + return !DefaultArgument.getArgument().isNull(); + } /// \brief Retrieve the default argument, if any. - Expr *getDefaultArgument() const { return DefaultArgument; } - - /// \brief Retrieve the location of the default argument, if any. - SourceLocation getDefaultArgumentLoc() const; + const TemplateArgumentLoc &getDefaultArgument() const { + return DefaultArgument; + } /// \brief Set the default argument for this template parameter. - void setDefaultArgument(Expr *DefArg) { + void setDefaultArgument(const TemplateArgumentLoc &DefArg) { DefaultArgument = DefArg; } diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index ed4ac6b5d4e7..a30f6e860dde 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -176,7 +176,6 @@ public: /// getNameKind - Determine what kind of name this is. NameKind getNameKind() const; - /// getName - Retrieve the human-readable string for this name. std::string getAsString() const; @@ -249,6 +248,8 @@ public: static DeclarationName getTombstoneMarker() { return DeclarationName(uintptr_t(-2)); } + + void dump() const; }; /// Ordering on two declaration names. If both names are identifiers, diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2a87f5883588..dfc5b13f28d3 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -87,7 +87,7 @@ public: // type. Additionally, inspect Expr::isLvalue to determine whether // an expression that is adjusted in this manner should be // considered an lvalue. - assert((TR.isNull() || !TR->isReferenceType()) && + assert((t.isNull() || !t->isReferenceType()) && "Expressions can't have reference type"); TR = t; @@ -250,6 +250,12 @@ public: /// folded, but discard the result. bool isEvaluatable(ASTContext &Ctx) const; + /// HasSideEffects - This routine returns true for all those expressions + /// which must be evaluated each time and must not be optimization away + /// or evaluated at compile time. Example is a function call, volatile + /// variable read. + bool HasSideEffects(ASTContext &Ctx) const; + /// EvaluateAsInt - Call Evaluate and return the folded integer. This /// must be called on an expression that constant folds to an integer. llvm::APSInt EvaluateAsInt(ASTContext &Ctx) const; @@ -1513,6 +1519,9 @@ public: /// CK_NoOp - Used for const_cast. CK_NoOp, + /// CK_BaseToDerived - Base to derived class casts. + CK_BaseToDerived, + /// CK_DerivedToBase - Derived to base class casts. CK_DerivedToBase, diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 5931a3fcf984..9e6fd4fd065b 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -95,6 +95,8 @@ public: /// operation would return "x". Expr *getImplicitObjectArgument(); + virtual SourceRange getSourceRange() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXMemberCallExprClass; } diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 5f318ba0b33b..9b1c640a40b2 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -15,6 +15,8 @@ #define LLVM_CLANG_AST_LAYOUTINFO_H #include "llvm/System/DataTypes.h" +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/DeclCXX.h" namespace clang { class ASTContext; diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 1e6871ff3b9c..867932332d09 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_REDECLARABLE_H #include "llvm/ADT/PointerIntPair.h" +#include <iterator> namespace clang { @@ -23,6 +24,8 @@ template<typename decl_type> class Redeclarable { protected: + // FIXME: PointerIntPair is a value class that should not be inherited from. + // This should change to using containment. struct DeclLink : public llvm::PointerIntPair<decl_type *, 1, bool> { DeclLink(decl_type *D, bool isLatest) : llvm::PointerIntPair<decl_type *, 1, bool>(D, isLatest) { } diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index bb14c62d7770..6db095872b0e 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -18,6 +18,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/Support/ErrorHandling.h" #include "clang/AST/Type.h" +#include "clang/AST/TemplateName.h" namespace llvm { class FoldingSetNodeID; @@ -48,21 +49,27 @@ class TemplateArgument { public: /// \brief The type of template argument we're storing. enum ArgKind { + /// \brief Represents an empty template argument, e.g., one that has not + /// been deduced. Null = 0, /// The template argument is a type. Its value is stored in the /// TypeOrValue field. - Type = 1, - /// The template argument is a declaration - Declaration = 2, - /// The template argument is an integral value stored in an llvm::APSInt. - Integral = 3, + Type, + /// The template argument is a declaration that was provided for a pointer + /// or reference non-type template parameter. + Declaration, + /// The template argument is an integral value stored in an llvm::APSInt + /// that was provided for an integral non-type template parameter. + Integral, + /// The template argument is a template name that was provided for a + /// template template parameter. + Template, /// The template argument is a value- or type-dependent expression /// stored in an Expr*. - Expression = 4, - + Expression, /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. - Pack = 5 + Pack } Kind; /// \brief Construct an empty, invalid template argument. @@ -82,12 +89,21 @@ public: } /// \brief Construct an integral constant template argument. - TemplateArgument(const llvm::APSInt &Value, QualType Type) - : Kind(Integral) { + TemplateArgument(const llvm::APSInt &Value, QualType Type) : Kind(Integral) { new (Integer.Value) llvm::APSInt(Value); Integer.Type = Type.getAsOpaquePtr(); } + /// \brief Construct a template argument that is a template. + /// + /// This form of template argument is generally used for template template + /// parameters. However, the template name could be a dependent template + /// name that ends up being instantiated to a function template whose address + /// is taken. + TemplateArgument(TemplateName Name) : Kind(Template) { + TypeOrValue = reinterpret_cast<uintptr_t>(Name.getAsVoidPointer()); + } + /// \brief Construct a template argument that is an expression. /// /// This form of template argument only occurs in template argument @@ -172,6 +188,15 @@ public: return reinterpret_cast<Decl *>(TypeOrValue); } + /// \brief Retrieve the template argument as a template name. + TemplateName getAsTemplate() const { + if (Kind != Template) + return TemplateName(); + + return TemplateName::getFromVoidPointer( + reinterpret_cast<void *> (TypeOrValue)); + } + /// \brief Retrieve the template argument as an integral value. llvm::APSInt *getAsIntegral() { if (Kind != Integral) @@ -242,13 +267,18 @@ private: union { Expr *Expression; DeclaratorInfo *Declarator; + struct { + unsigned QualifierRange[2]; + unsigned TemplateNameLoc; + } Template; }; #ifndef NDEBUG enum Kind { K_None, K_DeclaratorInfo, - K_Expression + K_Expression, + K_Template } Kind; #endif @@ -273,6 +303,17 @@ public: , Kind(K_Expression) #endif {} + + TemplateArgumentLocInfo(SourceRange QualifierRange, + SourceLocation TemplateNameLoc) +#ifndef NDEBUG + : Kind(K_Template) +#endif + { + Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); + Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); + } DeclaratorInfo *getAsDeclaratorInfo() const { assert(Kind == K_DeclaratorInfo); @@ -284,6 +325,18 @@ public: return Expression; } + SourceRange getTemplateQualifierRange() const { + assert(Kind == K_Template); + return SourceRange( + SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), + SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + } + + SourceLocation getTemplateNameLoc() const { + assert(Kind == K_Template); + return SourceLocation::getFromRawEncoding(Template.TemplateNameLoc); + } + #ifndef NDEBUG void validateForArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { @@ -294,6 +347,9 @@ public: case TemplateArgument::Declaration: assert(Kind == K_Expression); break; + case TemplateArgument::Template: + assert(Kind == K_Template); + break; case TemplateArgument::Integral: case TemplateArgument::Pack: assert(Kind == K_None); @@ -329,8 +385,18 @@ public: assert(Argument.getKind() == TemplateArgument::Expression); } - /// \brief - Fetches the start location of the argument. + TemplateArgumentLoc(const TemplateArgument &Argument, + SourceRange QualifierRange, + SourceLocation TemplateNameLoc) + : Argument(Argument), LocInfo(QualifierRange, TemplateNameLoc) { + assert(Argument.getKind() == TemplateArgument::Template); + } + + /// \brief - Fetches the primary location of the argument. SourceLocation getLocation() const { + if (Argument.getKind() == TemplateArgument::Template) + return getTemplateNameLoc(); + return getSourceRange().getBegin(); } @@ -359,6 +425,16 @@ public: assert(Argument.getKind() == TemplateArgument::Declaration); return LocInfo.getAsExpr(); } + + SourceRange getTemplateQualifierRange() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateQualifierRange(); + } + + SourceLocation getTemplateNameLoc() const { + assert(Argument.getKind() == TemplateArgument::Template); + return LocInfo.getTemplateNameLoc(); + } }; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index daa814739182..c28bafe9a30f 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -396,10 +396,6 @@ class QualType { llvm::PointerIntPair<llvm::PointerUnion<const Type*,const ExtQuals*>, Qualifiers::FastWidth> Value; - bool hasExtQuals() const { - return Value.getPointer().is<const ExtQuals*>(); - } - const ExtQuals *getExtQualsUnsafe() const { return Value.getPointer().get<const ExtQuals*>(); } @@ -408,6 +404,8 @@ class QualType { return Value.getPointer().get<const Type*>(); } + QualType getUnqualifiedTypeSlow() const; + friend class QualifierCollector; public: QualType() {} @@ -417,14 +415,14 @@ public: QualType(const ExtQuals *Ptr, unsigned Quals) : Value(Ptr, Quals) {} - unsigned getFastQualifiers() const { return Value.getInt(); } - void setFastQualifiers(unsigned Quals) { Value.setInt(Quals); } + unsigned getLocalFastQualifiers() const { return Value.getInt(); } + void setLocalFastQualifiers(unsigned Quals) { Value.setInt(Quals); } /// Retrieves a pointer to the underlying (unqualified) type. /// This should really return a const Type, but it's not worth /// changing all the users right now. Type *getTypePtr() const { - if (hasNonFastQualifiers()) + if (hasLocalNonFastQualifiers()) return const_cast<Type*>(getExtQualsUnsafe()->getBaseType()); return const_cast<Type*>(getTypePtrUnsafe()); } @@ -452,41 +450,81 @@ public: return Value.getPointer().isNull(); } - bool isConstQualified() const { - return (getFastQualifiers() & Qualifiers::Const); - } - bool isRestrictQualified() const { - return (getFastQualifiers() & Qualifiers::Restrict); - } - bool isVolatileQualified() const { - return (hasNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile()); - } - - // Determines whether this type has any direct qualifiers. - bool hasQualifiers() const { - return getFastQualifiers() || hasNonFastQualifiers(); - } - - bool hasNonFastQualifiers() const { - return hasExtQuals(); + /// \brief Determine whether this particular QualType instance has the + /// "const" qualifier set, without looking through typedefs that may have + /// added "const" at a different level. + bool isLocalConstQualified() const { + return (getLocalFastQualifiers() & Qualifiers::Const); + } + + /// \brief Determine whether this type is const-qualified. + bool isConstQualified() const; + + /// \brief Determine whether this particular QualType instance has the + /// "restrict" qualifier set, without looking through typedefs that may have + /// added "restrict" at a different level. + bool isLocalRestrictQualified() const { + return (getLocalFastQualifiers() & Qualifiers::Restrict); + } + + /// \brief Determine whether this type is restrict-qualified. + bool isRestrictQualified() const; + + /// \brief Determine whether this particular QualType instance has the + /// "volatile" qualifier set, without looking through typedefs that may have + /// added "volatile" at a different level. + bool isLocalVolatileQualified() const { + return (hasLocalNonFastQualifiers() && getExtQualsUnsafe()->hasVolatile()); + } + + /// \brief Determine whether this type is volatile-qualified. + bool isVolatileQualified() const; + + /// \brief Determine whether this particular QualType instance has any + /// qualifiers, without looking through any typedefs that might add + /// qualifiers at a different level. + bool hasLocalQualifiers() const { + return getLocalFastQualifiers() || hasLocalNonFastQualifiers(); + } + + /// \brief Determine whether this type has any qualifiers. + bool hasQualifiers() const; + + /// \brief Determine whether this particular QualType instance has any + /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType + /// instance. + bool hasLocalNonFastQualifiers() const { + return Value.getPointer().is<const ExtQuals*>(); } - // Retrieves the set of qualifiers belonging to this type. - Qualifiers getQualifiers() const { + /// \brief Retrieve the set of qualifiers local to this particular QualType + /// instance, not including any qualifiers acquired through typedefs or + /// other sugar. + Qualifiers getLocalQualifiers() const { Qualifiers Quals; - if (hasNonFastQualifiers()) + if (hasLocalNonFastQualifiers()) Quals = getExtQualsUnsafe()->getQualifiers(); - Quals.addFastQualifiers(getFastQualifiers()); + Quals.addFastQualifiers(getLocalFastQualifiers()); return Quals; } - // Retrieves the CVR qualifiers of this type. - unsigned getCVRQualifiers() const { - unsigned CVR = getFastQualifiers(); - if (isVolatileQualified()) CVR |= Qualifiers::Volatile; + /// \brief Retrieve the set of qualifiers applied to this type. + Qualifiers getQualifiers() const; + + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// local to this particular QualType instance, not including any qualifiers + /// acquired through typedefs or other sugar. + unsigned getLocalCVRQualifiers() const { + unsigned CVR = getLocalFastQualifiers(); + if (isLocalVolatileQualified()) + CVR |= Qualifiers::Volatile; return CVR; } + /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// applied to this type. + unsigned getCVRQualifiers() const; + bool isConstant(ASTContext& Ctx) const { return QualType::isConstant(*this, Ctx); } @@ -508,6 +546,9 @@ public: Value.setInt(Value.getInt() | TQs); } + // FIXME: The remove* functions are semantically broken, because they might + // not remove a qualifier stored on a typedef. Most of the with* functions + // have the same problem. void removeConst(); void removeVolatile(); void removeRestrict(); @@ -540,8 +581,21 @@ public: return T; } - QualType getUnqualifiedType() const { return QualType(getTypePtr(), 0); } + /// \brief Return this type with all of the instance-specific qualifiers + /// removed, but without removing any qualifiers that may have been applied + /// through typedefs. + QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); } + /// \brief Return the unqualified form of the given type, which might be + /// desugared to eliminate qualifiers introduced via typedefs. + QualType getUnqualifiedType() const { + QualType T = getLocalUnqualifiedType(); + if (!T.hasQualifiers()) + return T; + + return getUnqualifiedTypeSlow(); + } + bool isMoreQualifiedThan(QualType Other) const; bool isAtLeastAsQualifiedAs(QualType Other) const; QualType getNonReferenceType() const; @@ -892,8 +946,6 @@ public: QualType getCanonicalTypeInternal() const { return CanonicalType; } void dump() const; - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const = 0; static bool classof(const Type *) { return true; } }; @@ -963,8 +1015,21 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; + bool isInteger() const { + return TypeKind >= Bool && TypeKind <= Int128; + } + + bool isSignedInteger() const { + return TypeKind >= Char_S && TypeKind <= Int128; + } + + bool isUnsignedInteger() const { + return TypeKind >= Bool && TypeKind <= UInt128; + } + + bool isFloatingPoint() const { + return TypeKind >= Float && TypeKind <= LongDouble; + } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } static bool classof(const BuiltinType *) { return true; } @@ -988,9 +1053,6 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == FixedWidthInt; } static bool classof(const FixedWidthIntType *) { return true; } }; @@ -1008,9 +1070,6 @@ class ComplexType : public Type, public llvm::FoldingSetNode { public: QualType getElementType() const { return ElementType; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1036,9 +1095,6 @@ class PointerType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these. public: - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - QualType getPointeeType() const { return PointeeType; } bool isSugared() const { return false; } @@ -1071,9 +1127,6 @@ public: // Get the pointee type. Pointee is required to always be a function type. QualType getPointeeType() const { return PointeeType; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1157,9 +1210,6 @@ class LValueReferenceType : public ReferenceType { {} friend class ASTContext; // ASTContext creates these public: - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1177,9 +1227,6 @@ class RValueReferenceType : public ReferenceType { } friend class ASTContext; // ASTContext creates these public: - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1209,9 +1256,6 @@ public: const Type *getClass() const { return Class; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1302,9 +1346,6 @@ protected: friend class ASTContext; // ASTContext creates these. public: const llvm::APInt &getSize() const { return Size; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1336,9 +1377,6 @@ class IncompleteArrayType : public ArrayType { : ArrayType(IncompleteArray, et, can, sm, tq) {} friend class ASTContext; // ASTContext creates these. public: - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1402,9 +1440,6 @@ public: SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1458,9 +1493,6 @@ public: SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1510,9 +1542,6 @@ public: QualType getElementType() const { return ElementType; } SourceLocation getAttributeLoc() const { return loc; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1555,9 +1584,6 @@ public: QualType getElementType() const { return ElementType; } unsigned getNumElements() const { return NumElements; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1633,9 +1659,6 @@ public: return unsigned(idx-1) < NumElements; return false; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1699,9 +1722,6 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { public: // No additional state past what FunctionType provides. - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1812,9 +1832,6 @@ public: return exception_begin() + NumExceptions; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -1856,9 +1873,6 @@ public: bool isSugared() const { return true; } QualType desugar() const; - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == Typedef; } static bool classof(const TypedefType *) { return true; } }; @@ -1879,9 +1893,6 @@ public: /// \brief Returns whether this type directly provides sugar. bool isSugared() const { return true; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } static bool classof(const TypeOfExprType *) { return true; } }; @@ -1924,9 +1935,6 @@ public: /// \brief Returns whether this type directly provides sugar. bool isSugared() const { return true; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } static bool classof(const TypeOfType *) { return true; } }; @@ -1953,9 +1961,6 @@ public: /// \brief Returns whether this type directly provides sugar. bool isSugared() const { return !isDependentType(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } static bool classof(const DecltypeType *) { return true; } }; @@ -2000,9 +2005,6 @@ public: bool isBeingDefined() const { return decl.getInt(); } void setBeingDefined(bool Def) const { decl.setInt(Def? 1 : 0); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - static bool classof(const Type *T) { return T->getTypeClass() >= TagFirst && T->getTypeClass() <= TagLast; } @@ -2117,9 +2119,6 @@ public: } } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getUnderlyingType(), getTagKind()); } @@ -2155,9 +2154,6 @@ public: bool isParameterPack() const { return ParameterPack; } IdentifierInfo *getName() const { return Name; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2211,9 +2207,6 @@ public: return getCanonicalTypeInternal(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return true; } QualType desugar() const { return getReplacementType(); } @@ -2309,9 +2302,6 @@ public: /// \precondition @c isArgType(Arg) const TemplateArgument &getArg(unsigned Idx) const; - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return !isDependentType(); } QualType desugar() const { return getCanonicalTypeInternal(); } @@ -2363,9 +2353,6 @@ public: /// \brief Returns whether this type directly provides sugar. bool isSugared() const { return true; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, NNS, NamedType); } @@ -2440,9 +2427,6 @@ public: return Name.dyn_cast<const TemplateSpecializationType *>(); } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2493,9 +2477,6 @@ public: qual_iterator qual_end() const { return Protocols.end(); } bool qual_empty() const { return Protocols.size() == 0; } - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; - bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2581,8 +2562,6 @@ public: void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, QualType T, ObjCProtocolDecl **protocols, unsigned NumProtocols); - virtual void getAsStringInternal(std::string &InnerString, - const PrintingPolicy &Policy) const; static bool classof(const Type *T) { return T->getTypeClass() == ObjCObjectPointer; } @@ -2604,8 +2583,8 @@ public: /// Collect any qualifiers on the given type and return an /// unqualified type. const Type *strip(QualType QT) { - addFastQualifiers(QT.getFastQualifiers()); - if (QT.hasNonFastQualifiers()) { + addFastQualifiers(QT.getLocalFastQualifiers()); + if (QT.hasLocalNonFastQualifiers()) { const ExtQuals *EQ = QT.getExtQualsUnsafe(); Context = &EQ->getContext(); addQualifiers(EQ->getQualifiers()); @@ -2627,18 +2606,51 @@ public: inline bool QualType::isCanonical() const { const Type *T = getTypePtr(); - if (hasQualifiers()) + if (hasLocalQualifiers()) return T->isCanonicalUnqualified() && !isa<ArrayType>(T); return T->isCanonicalUnqualified(); } inline bool QualType::isCanonicalAsParam() const { - if (hasQualifiers()) return false; + if (hasLocalQualifiers()) return false; const Type *T = getTypePtr(); return T->isCanonicalUnqualified() && !isa<FunctionType>(T) && !isa<ArrayType>(T); } +inline bool QualType::isConstQualified() const { + return isLocalConstQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalConstQualified(); +} + +inline bool QualType::isRestrictQualified() const { + return isLocalRestrictQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalRestrictQualified(); +} + + +inline bool QualType::isVolatileQualified() const { + return isLocalVolatileQualified() || + getTypePtr()->getCanonicalTypeInternal().isLocalVolatileQualified(); +} + +inline bool QualType::hasQualifiers() const { + return hasLocalQualifiers() || + getTypePtr()->getCanonicalTypeInternal().hasLocalQualifiers(); +} + +inline Qualifiers QualType::getQualifiers() const { + Qualifiers Quals = getLocalQualifiers(); + Quals.addQualifiers( + getTypePtr()->getCanonicalTypeInternal().getLocalQualifiers()); + return Quals; +} + +inline unsigned QualType::getCVRQualifiers() const { + return getLocalCVRQualifiers() | + getTypePtr()->getCanonicalTypeInternal().getLocalCVRQualifiers(); +} + inline void QualType::removeConst() { removeFastQualifiers(Qualifiers::Const); } @@ -2673,14 +2685,14 @@ inline void QualType::removeCVRQualifiers(unsigned Mask) { /// getAddressSpace - Return the address space of this type. inline unsigned QualType::getAddressSpace() const { - if (hasNonFastQualifiers()) { + if (hasLocalNonFastQualifiers()) { const ExtQuals *EQ = getExtQualsUnsafe(); if (EQ->hasAddressSpace()) return EQ->getAddressSpace(); } QualType CT = getTypePtr()->getCanonicalTypeInternal(); - if (CT.hasNonFastQualifiers()) { + if (CT.hasLocalNonFastQualifiers()) { const ExtQuals *EQ = CT.getExtQualsUnsafe(); if (EQ->hasAddressSpace()) return EQ->getAddressSpace(); @@ -2695,14 +2707,14 @@ inline unsigned QualType::getAddressSpace() const { /// getObjCGCAttr - Return the gc attribute of this type. inline Qualifiers::GC QualType::getObjCGCAttr() const { - if (hasNonFastQualifiers()) { + if (hasLocalNonFastQualifiers()) { const ExtQuals *EQ = getExtQualsUnsafe(); if (EQ->hasObjCGCAttr()) return EQ->getObjCGCAttr(); } QualType CT = getTypePtr()->getCanonicalTypeInternal(); - if (CT.hasNonFastQualifiers()) { + if (CT.hasLocalNonFastQualifiers()) { const ExtQuals *EQ = CT.getExtQualsUnsafe(); if (EQ->hasObjCGCAttr()) return EQ->getObjCGCAttr(); @@ -2780,28 +2792,26 @@ inline const ObjCInterfaceType *Type::getAsPointerToObjCInterfaceType() const { return 0; } -// NOTE: All of these methods use "getUnqualifiedType" to strip off address -// space qualifiers if present. inline bool Type::isFunctionType() const { - return isa<FunctionType>(CanonicalType.getUnqualifiedType()); + return isa<FunctionType>(CanonicalType); } inline bool Type::isPointerType() const { - return isa<PointerType>(CanonicalType.getUnqualifiedType()); + return isa<PointerType>(CanonicalType); } inline bool Type::isAnyPointerType() const { return isPointerType() || isObjCObjectPointerType(); } inline bool Type::isBlockPointerType() const { - return isa<BlockPointerType>(CanonicalType.getUnqualifiedType()); + return isa<BlockPointerType>(CanonicalType); } inline bool Type::isReferenceType() const { - return isa<ReferenceType>(CanonicalType.getUnqualifiedType()); + return isa<ReferenceType>(CanonicalType); } inline bool Type::isLValueReferenceType() const { - return isa<LValueReferenceType>(CanonicalType.getUnqualifiedType()); + return isa<LValueReferenceType>(CanonicalType); } inline bool Type::isRValueReferenceType() const { - return isa<RValueReferenceType>(CanonicalType.getUnqualifiedType()); + return isa<RValueReferenceType>(CanonicalType); } inline bool Type::isFunctionPointerType() const { if (const PointerType* T = getAs<PointerType>()) @@ -2810,7 +2820,7 @@ inline bool Type::isFunctionPointerType() const { return false; } inline bool Type::isMemberPointerType() const { - return isa<MemberPointerType>(CanonicalType.getUnqualifiedType()); + return isa<MemberPointerType>(CanonicalType); } inline bool Type::isMemberFunctionPointerType() const { if (const MemberPointerType* T = getAs<MemberPointerType>()) @@ -2819,37 +2829,37 @@ inline bool Type::isMemberFunctionPointerType() const { return false; } inline bool Type::isArrayType() const { - return isa<ArrayType>(CanonicalType.getUnqualifiedType()); + return isa<ArrayType>(CanonicalType); } inline bool Type::isConstantArrayType() const { - return isa<ConstantArrayType>(CanonicalType.getUnqualifiedType()); + return isa<ConstantArrayType>(CanonicalType); } inline bool Type::isIncompleteArrayType() const { - return isa<IncompleteArrayType>(CanonicalType.getUnqualifiedType()); + return isa<IncompleteArrayType>(CanonicalType); } inline bool Type::isVariableArrayType() const { - return isa<VariableArrayType>(CanonicalType.getUnqualifiedType()); + return isa<VariableArrayType>(CanonicalType); } inline bool Type::isDependentSizedArrayType() const { - return isa<DependentSizedArrayType>(CanonicalType.getUnqualifiedType()); + return isa<DependentSizedArrayType>(CanonicalType); } inline bool Type::isRecordType() const { - return isa<RecordType>(CanonicalType.getUnqualifiedType()); + return isa<RecordType>(CanonicalType); } inline bool Type::isAnyComplexType() const { - return isa<ComplexType>(CanonicalType.getUnqualifiedType()); + return isa<ComplexType>(CanonicalType); } inline bool Type::isVectorType() const { - return isa<VectorType>(CanonicalType.getUnqualifiedType()); + return isa<VectorType>(CanonicalType); } inline bool Type::isExtVectorType() const { - return isa<ExtVectorType>(CanonicalType.getUnqualifiedType()); + return isa<ExtVectorType>(CanonicalType); } inline bool Type::isObjCObjectPointerType() const { - return isa<ObjCObjectPointerType>(CanonicalType.getUnqualifiedType()); + return isa<ObjCObjectPointerType>(CanonicalType); } inline bool Type::isObjCInterfaceType() const { - return isa<ObjCInterfaceType>(CanonicalType.getUnqualifiedType()); + return isa<ObjCInterfaceType>(CanonicalType); } inline bool Type::isObjCQualifiedIdType() const { if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) @@ -2875,7 +2885,7 @@ inline bool Type::isObjCBuiltinType() const { return isObjCIdType() || isObjCClassType(); } inline bool Type::isTemplateTypeParmType() const { - return isa<TemplateTypeParmType>(CanonicalType.getUnqualifiedType()); + return isa<TemplateTypeParmType>(CanonicalType); } inline bool Type::isSpecificBuiltinType(unsigned K) const { @@ -2911,8 +2921,21 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, return DB; } +// 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, + bool isArrayType = (llvm::is_same<T, ArrayType>::value || + llvm::is_base_of<ArrayType, T>::value)> +struct ArrayType_cannot_be_used_with_getAs { }; + +template<typename T> +struct ArrayType_cannot_be_used_with_getAs<T, true>; + /// Member-template getAs<specific type>'. template <typename T> const T *Type::getAs() const { + ArrayType_cannot_be_used_with_getAs<T> at; + (void)at; + // If this is directly a T type, return it. if (const T *Ty = dyn_cast<T>(this)) return Ty; diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index da7857822e9c..f08ca6bf469b 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -58,7 +58,7 @@ public: : Ty(ty), Data(opaqueData) { } TypeLocClass getTypeLocClass() const { - if (getType().hasQualifiers()) return Qualified; + if (getType().hasLocalQualifiers()) return Qualified; return (TypeLocClass) getType()->getTypeClass(); } @@ -155,7 +155,7 @@ public: } static bool classof(const TypeLoc *TL) { - return !TL->getType().hasQualifiers(); + return !TL->getType().hasLocalQualifiers(); } static bool classof(const UnqualTypeLoc *TL) { return true; } }; @@ -196,11 +196,11 @@ public: /// \brief Returns the size of the type source info data block. unsigned getFullDataSize() const { return getLocalDataSize() + - getFullDataSizeForType(getType().getUnqualifiedType()); + getFullDataSizeForType(getType().getLocalUnqualifiedType()); } static bool classof(const TypeLoc *TL) { - return TL->getType().hasQualifiers(); + return TL->getType().hasLocalQualifiers(); } static bool classof(const QualifiedTypeLoc *TL) { return true; } }; @@ -919,6 +919,10 @@ public: Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0); break; + case TemplateArgument::Template: + Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation()); + break; + case TemplateArgument::Integral: case TemplateArgument::Pack: case TemplateArgument::Null: diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h index 4e1fbaaf4c5e..00e2b7f83219 100644 --- a/include/clang/AST/TypeLocBuilder.h +++ b/include/clang/AST/TypeLocBuilder.h @@ -17,6 +17,7 @@ #include "clang/AST/TypeLoc.h" #include "llvm/ADT/SmallVector.h" +#include "clang/AST/ASTContext.h" namespace clang { diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 17f772da0c6d..867494396020 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -88,11 +88,11 @@ public: /// dumpLiveness - Print to stderr the liveness information encoded /// by a specified bitvector. - void dumpLiveness(const ValTy& V, SourceManager& M) const; + void dumpLiveness(const ValTy& V, const SourceManager& M) const; /// dumpBlockLiveness - Print to stderr the liveness information /// associated with each basic block. - void dumpBlockLiveness(SourceManager& M) const; + void dumpBlockLiveness(const SourceManager& M) const; /// getNumDecls - Return the number of variables (declarations) that /// whose liveness status is being tracked by the dataflow diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index f505bca9519c..cbf7010bfdb5 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -16,6 +16,7 @@ #include "clang/Analysis/CFG.h" #include "clang/Analysis/ProgramPoint.h" +#include "clang/Analysis/FlowSensitive/DataflowValues.h" #include "llvm/ADT/SmallPtrSet.h" #include "functional" // STL diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h index 1da15fbae6c4..8c70e4fc7b6c 100644 --- a/include/clang/Analysis/LocalCheckers.h +++ b/include/clang/Analysis/LocalCheckers.h @@ -50,10 +50,12 @@ void CheckObjCInstMethSignature(const ObjCImplementationDecl *ID, void CheckObjCUnusedIvar(const ObjCImplementationDecl *D, BugReporter& BR); void RegisterAppleChecks(GRExprEngine& Eng, const Decl &D); +void RegisterExperimentalChecks(GRExprEngine &Eng); +void RegisterExperimentalInternalChecks(GRExprEngine &Eng); void CheckSecuritySyntaxOnly(const Decl *D, BugReporter &BR); - +void CheckSizeofPointer(const Decl *D, BugReporter &BR); } // end namespace clang #endif diff --git a/include/clang/Analysis/ManagerRegistry.h b/include/clang/Analysis/ManagerRegistry.h new file mode 100644 index 000000000000..972993855c28 --- /dev/null +++ b/include/clang/Analysis/ManagerRegistry.h @@ -0,0 +1,53 @@ +//===-- ManagerRegistry.h - Pluggable analyzer module registry --*- 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 the ManagerRegistry and Register* classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H +#define LLVM_CLANG_ANALYSIS_MANAGER_REGISTRY_H + +#include "clang/Analysis/PathSensitive/GRState.h" + +namespace clang { + +/// ManagerRegistry - This class records manager creators registered at +/// runtime. The information is communicated to AnalysisManager through static +/// members. Better design is expected. + +class ManagerRegistry { +public: + static StoreManagerCreator StoreMgrCreator; + static ConstraintManagerCreator ConstraintMgrCreator; +}; + +/// RegisterConstraintManager - This class is used to setup the constraint +/// manager of the static analyzer. The constructor takes a creator function +/// pointer for creating the constraint manager. +/// +/// It is used like this: +/// +/// class MyConstraintManager {}; +/// ConstraintManager* CreateMyConstraintManager(GRStateManager& statemgr) { +/// return new MyConstraintManager(statemgr); +/// } +/// RegisterConstraintManager X(CreateMyConstraintManager); + +class RegisterConstraintManager { +public: + RegisterConstraintManager(ConstraintManagerCreator CMC) { + assert(ManagerRegistry::ConstraintMgrCreator == 0 + && "ConstraintMgrCreator already set!"); + ManagerRegistry::ConstraintMgrCreator = CMC; + } +}; + +} +#endif diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index 66e850a91444..9b58f745f0a5 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -15,6 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H +#include "clang/AST/Stmt.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/DenseMap.h" diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index 488334623b34..18eae9ac9f14 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -37,7 +37,6 @@ class AnalysisManager : public BugReporterData { enum AnalysisScope { ScopeTU, ScopeDecl } AScope; - bool DisplayedFunction; bool VisualizeEGDot; bool VisualizeEGUbi; bool PurgeDead; @@ -62,7 +61,7 @@ public: : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), - AScope(ScopeDecl), DisplayedFunction(!displayProgress), + AScope(ScopeDecl), VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge), EagerlyAssume(eager), TrimGraph(trim) {} @@ -120,8 +119,6 @@ public: bool shouldEagerlyAssume() const { return EagerlyAssume; } - void DisplayFunction(Decl *D); - CFG *getCFG(Decl const *D) { return AnaCtxMgr.getContext(D)->getCFG(); } diff --git a/include/clang/Analysis/PathSensitive/BugReporter.h b/include/clang/Analysis/PathSensitive/BugReporter.h index 914118cb430d..f4297350ec70 100644 --- a/include/clang/Analysis/PathSensitive/BugReporter.h +++ b/include/clang/Analysis/PathSensitive/BugReporter.h @@ -81,10 +81,10 @@ public: getOriginalNode(const ExplodedNode* N) = 0; }; - BugReport(BugType& bt, const char* desc, const ExplodedNode *n) + BugReport(BugType& bt, llvm::StringRef desc, const ExplodedNode *n) : BT(bt), Description(desc), EndNode(n) {} - BugReport(BugType& bt, const char* shortDesc, const char* desc, + BugReport(BugType& bt, llvm::StringRef shortDesc, llvm::StringRef desc, const ExplodedNode *n) : BT(bt), ShortDescription(shortDesc), Description(desc), EndNode(n) {} @@ -193,11 +193,11 @@ public: class RangedBugReport : public BugReport { std::vector<SourceRange> Ranges; public: - RangedBugReport(BugType& D, const char* description, ExplodedNode *n) + RangedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n) : BugReport(D, description, n) {} - RangedBugReport(BugType& D, const char *shortDescription, - const char *description, ExplodedNode *n) + RangedBugReport(BugType& D, llvm::StringRef shortDescription, + llvm::StringRef description, ExplodedNode *n) : BugReport(D, shortDescription, description, n) {} ~RangedBugReport(); @@ -229,11 +229,11 @@ private: Creators creators; public: - EnhancedBugReport(BugType& D, const char* description, ExplodedNode *n) + EnhancedBugReport(BugType& D, llvm::StringRef description, ExplodedNode *n) : RangedBugReport(D, description, n) {} - EnhancedBugReport(BugType& D, const char *shortDescription, - const char *description, ExplodedNode *n) + EnhancedBugReport(BugType& D, llvm::StringRef shortDescription, + llvm::StringRef description, ExplodedNode *n) : RangedBugReport(D, shortDescription, description, n) {} ~EnhancedBugReport() {} diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h index 242b8e9afebe..8303dee49afa 100644 --- a/include/clang/Analysis/PathSensitive/BugType.h +++ b/include/clang/Analysis/PathSensitive/BugType.h @@ -23,6 +23,7 @@ class BugReportEquivClass; class BugReporter; class BuiltinBugReport; class BugReporterContext; +class ExplodedNode; class GRExprEngine; class BugType { @@ -59,21 +60,27 @@ public: }; class BuiltinBug : public BugType { - GRExprEngine &Eng; + GRExprEngine *Eng; protected: const std::string desc; public: + BuiltinBug(const char *name, const char *description) + : BugType(name, "Logic error"), Eng(0), desc(description) {} + + BuiltinBug(const char *name) + : BugType(name, "Logic error"), Eng(0), desc(name) {} + BuiltinBug(GRExprEngine *eng, const char* n, const char* d) - : BugType(n, "Logic error"), Eng(*eng), desc(d) {} + : BugType(n, "Logic error"), Eng(eng), desc(d) {} BuiltinBug(GRExprEngine *eng, const char* n) - : BugType(n, "Logic error"), Eng(*eng), desc(n) {} + : BugType(n, "Logic error"), Eng(eng), desc(n) {} const std::string &getDescription() const { return desc; } virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {} - void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); } + void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, *Eng); } virtual void registerInitialVisitors(BugReporterContext& BRC, const ExplodedNode* N, diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index 4fc0a617ecf0..b7ed20fab250 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -39,22 +39,19 @@ class CheckerContext { SaveAndRestore<const void*> OldTag; SaveAndRestore<ProgramPoint::Kind> OldPointKind; SaveOr OldHasGen; + const GRState *state; public: - CheckerContext(ExplodedNodeSet &dst, - GRStmtNodeBuilder &builder, - GRExprEngine &eng, - ExplodedNode *pred, - const void *tag, bool preVisit) + CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder, + GRExprEngine &eng, ExplodedNode *pred, + const void *tag, ProgramPoint::Kind K, + const GRState *st = 0) : Dst(dst), B(builder), Eng(eng), Pred(pred), - OldSink(B.BuildSinks), OldTag(B.Tag), - OldPointKind(B.PointKind), OldHasGen(B.HasGeneratedNode) { - //assert(Dst.empty()); // This is a fake assertion. - // See GRExprEngine::CheckerVisit(), CurrSet is repeatedly used. - B.Tag = tag; - if (preVisit) - B.PointKind = ProgramPoint::PreStmtKind; - } + OldSink(B.BuildSinks), + OldTag(B.Tag, tag), + OldPointKind(B.PointKind, K), + OldHasGen(B.HasGeneratedNode), + state(st) {} ~CheckerContext() { if (!B.BuildSinks && !B.HasGeneratedNode) @@ -64,10 +61,15 @@ public: ConstraintManager &getConstraintManager() { return Eng.getConstraintManager(); } + + StoreManager &getStoreManager() { + return Eng.getStoreManager(); + } + ExplodedNodeSet &getNodeSet() { return Dst; } GRStmtNodeBuilder &getNodeBuilder() { return B; } ExplodedNode *&getPredecessor() { return Pred; } - const GRState *getState() { return B.GetState(Pred); } + const GRState *getState() { return state ? state : B.GetState(Pred); } ASTContext &getASTContext() { return Eng.getContext(); @@ -76,6 +78,10 @@ public: BugReporter &getBugReporter() { return Eng.getBugReporter(); } + + SourceManager &getSourceManager() { + return getBugReporter().getSourceManager(); + } ExplodedNode *GenerateNode(const Stmt *S, bool markAsSink = false) { return GenerateNode(S, getState(), markAsSink); @@ -104,50 +110,69 @@ class Checker { private: friend class GRExprEngine; + // FIXME: Remove the 'tag' option. void GR_Visit(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, GRExprEngine &Eng, - const Stmt *stmt, + const Stmt *S, ExplodedNode *Pred, void *tag, bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit); - assert(isPrevisit && "Only previsit supported for now."); - _PreVisit(C, stmt); + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isPrevisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind); + if (isPrevisit) + _PreVisit(C, S); + else + _PostVisit(C, S); } + // FIXME: Remove the 'tag' option. void GR_VisitBind(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, GRExprEngine &Eng, const Stmt *AssignE, const Stmt *StoreE, ExplodedNode *Pred, void *tag, SVal location, SVal val, bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit); + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isPrevisit ? ProgramPoint::PreStmtKind : + ProgramPoint::PostStmtKind); assert(isPrevisit && "Only previsit supported for now."); PreVisitBind(C, AssignE, StoreE, location, val); } - -public: - virtual ~Checker() {} - virtual void _PreVisit(CheckerContext &C, const Stmt *ST) {} - // This is a previsit which takes a node returns a node. - virtual ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, - const GRState *state, SVal V, - GRExprEngine &Eng) { - return Pred; + // FIXME: Remove the 'tag' option. + void GR_VisitLocation(ExplodedNodeSet &Dst, + GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, + const Stmt *S, + ExplodedNode *Pred, const GRState *state, + SVal location, + void *tag, bool isLoad) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + isLoad ? ProgramPoint::PreLoadKind : + ProgramPoint::PreStoreKind, state); + VisitLocation(C, S, location); } - - virtual void PreVisitBind(CheckerContext &C, - const Stmt *AssignE, const Stmt *StoreE, - SVal location, SVal val) {} - - virtual ExplodedNode *CheckType(QualType T, ExplodedNode *Pred, - const GRState *state, Stmt *S, - GRExprEngine &Eng) { - return Pred; + + void GR_EvalDeadSymbols(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, + SymbolReaper &SymReaper, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, + ProgramPoint::PostPurgeDeadSymbolsKind, Pred->getState()); + EvalDeadSymbols(C, S, SymReaper); } +public: + virtual ~Checker() {} + virtual void _PreVisit(CheckerContext &C, const Stmt *S) {} + virtual void _PostVisit(CheckerContext &C, const Stmt *S) {} + virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {} + virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE, + const Stmt *StoreE, SVal location, SVal val) {} + virtual void EvalDeadSymbols(CheckerContext &C, const Stmt *S, + SymbolReaper &SymReaper) {} + virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag, + GRExprEngine &Eng) {} }; - } // end clang namespace #endif diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.def b/include/clang/Analysis/PathSensitive/CheckerVisitor.def index ff6528dae8f5..090a5d397549 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.def +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.def @@ -11,8 +11,19 @@ // //===---------------------------------------------------------------------===// +#ifdef PREVISIT +PREVISIT(ArraySubscriptExpr) +PREVISIT(BinaryOperator) PREVISIT(CallExpr) +PREVISIT(CastExpr) +PREVISIT(DeclStmt) PREVISIT(ObjCMessageExpr) -PREVISIT(BinaryOperator) - +PREVISIT(ReturnStmt) #undef PREVISIT +#endif + +#ifdef POSTVISIT +POSTVISIT(CallExpr) +#undef POSTVISIT +#endif + diff --git a/include/clang/Analysis/PathSensitive/CheckerVisitor.h b/include/clang/Analysis/PathSensitive/CheckerVisitor.h index e74f49c9a761..7cef17eb6591 100644 --- a/include/clang/Analysis/PathSensitive/CheckerVisitor.h +++ b/include/clang/Analysis/PathSensitive/CheckerVisitor.h @@ -27,8 +27,12 @@ namespace clang { template<typename ImplClass> class CheckerVisitor : public Checker { public: - virtual void _PreVisit(CheckerContext &C, const Stmt *stmt) { - PreVisit(C, stmt); + virtual void _PreVisit(CheckerContext &C, const Stmt *S) { + PreVisit(C, S); + } + + virtual void _PostVisit(CheckerContext &C, const Stmt *S) { + PostVisit(C, S); } void PreVisit(CheckerContext &C, const Stmt *S) { @@ -36,10 +40,19 @@ public: default: assert(false && "Unsupport statement."); return; + + case Stmt::ImplicitCastExprClass: + case Stmt::ExplicitCastExprClass: + case Stmt::CStyleCastExprClass: + static_cast<ImplClass*>(this)->PreVisitCastExpr(C, + static_cast<const CastExpr*>(S)); + break; + case Stmt::CompoundAssignOperatorClass: static_cast<ImplClass*>(this)->PreVisitBinaryOperator(C, static_cast<const BinaryOperator*>(S)); break; + #define PREVISIT(NAME) \ case Stmt::NAME ## Class:\ static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\ @@ -47,13 +60,30 @@ break; #include "clang/Analysis/PathSensitive/CheckerVisitor.def" } } + + void PostVisit(CheckerContext &C, const Stmt *S) { + switch (S->getStmtClass()) { + default: + assert(false && "Unsupport statement."); + return; +#define POSTVISIT(NAME) \ +case Stmt::NAME ## Class:\ +static_cast<ImplClass*>(this)->\ +PostVisit ## NAME(C,static_cast<const NAME*>(S));\ +break; +#include "clang/Analysis/PathSensitive/CheckerVisitor.def" + } + } #define PREVISIT(NAME) \ void PreVisit ## NAME(CheckerContext &C, const NAME* S) {} #include "clang/Analysis/PathSensitive/CheckerVisitor.def" + +#define POSTVISIT(NAME) \ +void PostVisit ## NAME(CheckerContext &C, const NAME* S) {} +#include "clang/Analysis/PathSensitive/CheckerVisitor.def" }; } // end clang namespace #endif - diff --git a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h index 688cf641491d..a84183e7f27f 100644 --- a/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h +++ b/include/clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h @@ -16,38 +16,16 @@ #ifndef LLVM_CLANG_DEREFCHECKER #define LLVM_CLANG_DEREFCHECKER -#include "clang/Analysis/PathSensitive/Checker.h" -#include "clang/Analysis/PathSensitive/BugType.h" +#include <utility> namespace clang { +class GRExprEngine; class ExplodedNode; -class NullDerefChecker : public Checker { - BuiltinBug *BT; - llvm::SmallVector<ExplodedNode*, 2> ImplicitNullDerefNodes; - -public: - NullDerefChecker() : BT(0) {} - ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, - const GRState *state, SVal V,GRExprEngine &Eng); - - static void *getTag(); - typedef llvm::SmallVectorImpl<ExplodedNode*>::iterator iterator; - iterator implicit_nodes_begin() { return ImplicitNullDerefNodes.begin(); } - iterator implicit_nodes_end() { return ImplicitNullDerefNodes.end(); } -}; - -class UndefDerefChecker : public Checker { - BuiltinBug *BT; -public: - UndefDerefChecker() : BT(0) {} - - ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred, - const GRState *state, SVal V, GRExprEngine &Eng); - - static void *getTag(); -}; +std::pair<ExplodedNode * const *, ExplodedNode * const *> +GetImplicitNullDereferences(GRExprEngine &Eng); } // end clang namespace + #endif diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 25e47038d72c..1b6d0bdf9c10 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -111,14 +111,6 @@ public: // was larger than sizeof(void *) (an undefined value). ErrorNodes NilReceiverLargerThanVoidPtrRetImplicit; - /// RetsStackAddr - Nodes in the ExplodedGraph that result from returning - /// the address of a stack variable. - ErrorNodes RetsStackAddr; - - /// RetsUndef - Nodes in the ExplodedGraph that result from returning - /// an undefined value. - ErrorNodes RetsUndef; - /// UndefBranches - Nodes in the ExplodedGraph that result from /// taking a branch based on an undefined value. ErrorNodes UndefBranches; @@ -131,22 +123,10 @@ public: // calling a function with the attribute "noreturn". ErrorNodes NoReturnCalls; - /// ImplicitBadSizedVLA - Nodes in the ExplodedGraph that result from - /// constructing a zero-sized VLA where the size may be zero. - ErrorNodes ImplicitBadSizedVLA; - - /// ExplicitBadSizedVLA - Nodes in the ExplodedGraph that result from - /// constructing a zero-sized VLA where the size must be zero. - ErrorNodes ExplicitBadSizedVLA; - /// UndefResults - Nodes in the ExplodedGraph where the operands are defined /// by the result is not. Excludes divide-by-zero errors. ErrorNodes UndefResults; - /// BadCalls - Nodes in the ExplodedGraph resulting from calls to function - /// pointers that are NULL (or other constants) or Undefined. - ErrorNodes BadCalls; - /// UndefReceiver - Nodes in the ExplodedGraph resulting from message /// ObjC message expressions where the receiver is undefined (uninitialized). ErrorNodes UndefReceivers; @@ -156,14 +136,6 @@ public: /// value. UndefArgsTy MsgExprUndefArgs; - /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from - /// out-of-bound memory accesses where the index MAY be out-of-bound. - ErrorNodes ImplicitOOBMemAccesses; - - /// OutOfBoundMemAccesses - Nodes in the ExplodedGraph resulting from - /// out-of-bound memory accesses where the index MUST be out-of-bound. - ErrorNodes ExplicitOOBMemAccesses; - public: GRExprEngine(AnalysisManager &mgr); @@ -223,58 +195,10 @@ public: return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag())); } - bool isRetStackAddr(const ExplodedNode* N) const { - return N->isSink() && RetsStackAddr.count(const_cast<ExplodedNode*>(N)) != 0; - } - - bool isUndefControlFlow(const ExplodedNode* N) const { - return N->isSink() && UndefBranches.count(const_cast<ExplodedNode*>(N)) != 0; - } - - bool isUndefStore(const ExplodedNode* N) const { - return N->isSink() && UndefStores.count(const_cast<ExplodedNode*>(N)) != 0; - } - - bool isImplicitNullDeref(const ExplodedNode* N) const { - return false; - } - - bool isExplicitNullDeref(const ExplodedNode* N) const { - return false; - } - - bool isUndefDeref(const ExplodedNode* N) const { - return false; - } - bool isNoReturnCall(const ExplodedNode* N) const { return N->isSink() && NoReturnCalls.count(const_cast<ExplodedNode*>(N)) != 0; } - bool isUndefResult(const ExplodedNode* N) const { - return N->isSink() && UndefResults.count(const_cast<ExplodedNode*>(N)) != 0; - } - - bool isBadCall(const ExplodedNode* N) const { - return false; - } - - bool isUndefArg(const ExplodedNode* N) const { - return false; - } - - bool isUndefReceiver(const ExplodedNode* N) const { - return N->isSink() && UndefReceivers.count(const_cast<ExplodedNode*>(N)) != 0; - } - - typedef ErrorNodes::iterator ret_stackaddr_iterator; - ret_stackaddr_iterator ret_stackaddr_begin() { return RetsStackAddr.begin(); } - ret_stackaddr_iterator ret_stackaddr_end() { return RetsStackAddr.end(); } - - typedef ErrorNodes::iterator ret_undef_iterator; - ret_undef_iterator ret_undef_begin() { return RetsUndef.begin(); } - ret_undef_iterator ret_undef_end() { return RetsUndef.end(); } - typedef ErrorNodes::iterator undef_branch_iterator; undef_branch_iterator undef_branches_begin() { return UndefBranches.begin(); } undef_branch_iterator undef_branches_end() { return UndefBranches.end(); } @@ -305,10 +229,6 @@ public: undef_result_iterator undef_results_begin() { return UndefResults.begin(); } undef_result_iterator undef_results_end() { return UndefResults.end(); } - typedef ErrorNodes::iterator bad_calls_iterator; - bad_calls_iterator bad_calls_begin() { return BadCalls.begin(); } - bad_calls_iterator bad_calls_end() { return BadCalls.end(); } - typedef UndefArgsTy::iterator undef_arg_iterator; undef_arg_iterator msg_expr_undef_arg_begin() { return MsgExprUndefArgs.begin(); @@ -327,20 +247,6 @@ public: return UndefReceivers.end(); } - typedef ErrorNodes::iterator oob_memacc_iterator; - oob_memacc_iterator implicit_oob_memacc_begin() { - return ImplicitOOBMemAccesses.begin(); - } - oob_memacc_iterator implicit_oob_memacc_end() { - return ImplicitOOBMemAccesses.end(); - } - oob_memacc_iterator explicit_oob_memacc_begin() { - return ExplicitOOBMemAccesses.begin(); - } - oob_memacc_iterator explicit_oob_memacc_end() { - return ExplicitOOBMemAccesses.end(); - } - void AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C); void AddCheck(GRSimpleAPICheck* A); @@ -368,10 +274,7 @@ public: /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path /// nodes when the control reaches the end of a function. - void ProcessEndPath(GREndPathNodeBuilder& builder) { - getTF().EvalEndPath(*this, builder); - StateMgr.EndPath(builder.getState()); - } + void ProcessEndPath(GREndPathNodeBuilder& builder); GRStateManager& getStateManager() { return StateMgr; } const GRStateManager& getStateManager() const { return StateMgr; } @@ -516,9 +419,6 @@ protected: void VisitUnaryOperator(UnaryOperator* B, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); - const GRState* CheckDivideZero(Expr* Ex, const GRState* St, ExplodedNode* Pred, - SVal Denom); - /// 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. @@ -553,15 +453,11 @@ public: } protected: - void EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L, ExplodedNode* Pred); - void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) { assert (Builder && "GRStmtNodeBuilder must be defined."); getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred); } - void EvalReturn(ExplodedNodeSet& Dst, ReturnStmt* s, ExplodedNode* Pred); - const GRState* MarkBranch(const GRState* St, Stmt* Terminator, bool branchTaken); @@ -573,16 +469,22 @@ protected: bool atDeclInit = false); public: + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. void EvalLoad(ExplodedNodeSet& Dst, Expr* Ex, ExplodedNode* Pred, - const GRState* St, SVal location, const void *tag = 0); + const GRState* St, SVal location, const void *tag = 0, + QualType LoadTy = QualType()); - ExplodedNode* EvalLocation(Stmt* Ex, ExplodedNode* Pred, + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. + void EvalLocation(ExplodedNodeSet &Dst, Stmt *S, ExplodedNode* Pred, const GRState* St, SVal location, - const void *tag = 0); + const void *tag, bool isLoad); + // FIXME: 'tag' should be removed, and a LocationContext should be used + // instead. void EvalStore(ExplodedNodeSet& Dst, Expr* AssignE, Expr* StoreE, - ExplodedNode* Pred, - const GRState* St, SVal TargetLV, SVal Val, + ExplodedNode* Pred, const GRState* St, SVal TargetLV, SVal Val, const void *tag = 0); }; diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index 8678ca9b5b9b..ef0c36c44d9f 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -195,6 +195,9 @@ public: // const GRState *Assume(DefinedOrUnknownSVal cond, bool assumption) const; + + std::pair<const GRState*, const GRState*> + Assume(DefinedOrUnknownSVal cond) const; const GRState *AssumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, @@ -330,12 +333,6 @@ public: void printStdErr() const; void printDOT(llvm::raw_ostream& Out) const; - - // Tags used for the Generic Data Map. - struct NullDerefTag { - static int TagInt; - typedef const SVal* data_type; - }; }; class GRStateSet { @@ -403,10 +400,6 @@ private: /// Alloc - A BumpPtrAllocator to allocate states. llvm::BumpPtrAllocator& Alloc; - /// CurrentStmt - The block-level statement currently being visited. This - /// is set by GRExprEngine. - Stmt* CurrentStmt; - /// TF - Object that represents a bundle of transfer functions /// for manipulating and creating SVals. GRTransferFuncs* TF; @@ -583,6 +576,15 @@ inline const GRState *GRState::Assume(DefinedOrUnknownSVal Cond, return getStateManager().ConstraintMgr->Assume(this, cast<DefinedSVal>(Cond), Assumption); } + +inline std::pair<const GRState*, const GRState*> +GRState::Assume(DefinedOrUnknownSVal Cond) const { + if (Cond.isUnknown()) + return std::make_pair(this, this); + + return getStateManager().ConstraintMgr->AssumeDual(this, + cast<DefinedSVal>(Cond)); +} inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx, DefinedOrUnknownSVal UpperBound, diff --git a/include/clang/Analysis/PathSensitive/GRWorkList.h b/include/clang/Analysis/PathSensitive/GRWorkList.h index 17b83fdf9fdc..857fa316911f 100644 --- a/include/clang/Analysis/PathSensitive/GRWorkList.h +++ b/include/clang/Analysis/PathSensitive/GRWorkList.h @@ -16,16 +16,19 @@ #define LLVM_CLANG_ANALYSIS_GRWORKLIST #include "clang/Analysis/PathSensitive/GRBlockCounter.h" +#include <cstddef> namespace clang { - + +class CFGBlock; +class ExplodedNode; class ExplodedNodeImpl; class GRWorkListUnit { ExplodedNode* Node; GRBlockCounter Counter; CFGBlock* Block; - unsigned BlockIdx; + unsigned BlockIdx; // This is the index of the next statement. public: GRWorkListUnit(ExplodedNode* N, GRBlockCounter C, diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 0e487691a891..06d0d976df01 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -77,6 +77,8 @@ public: const MemRegion *getBaseRegion() const; + const MemRegion *StripCasts() const; + bool hasStackStorage() const; bool hasParametersStorage() const; diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h index 4ba3c7396822..8b5cf40e29cb 100644 --- a/include/clang/Analysis/PathSensitive/SVals.h +++ b/include/clang/Analysis/PathSensitive/SVals.h @@ -96,6 +96,8 @@ public: return getRawKind() > UnknownKind; } + bool isConstant() const; + bool isZeroConstant() const; /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true; @@ -434,7 +436,7 @@ public: return static_cast<MemRegion*>(Data); } - const MemRegion* getBaseRegion() const; + const MemRegion* StripCasts() const; template <typename REGION> const REGION* getRegionAs() const { diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 6ca2e9e9aa68..55fa83d9ecc3 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -102,7 +102,8 @@ public: virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0; // FIXME: Make out-of-line. - virtual SVal getSizeInElements(const GRState *state, const MemRegion *region){ + virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, + const MemRegion *region) { return UnknownVal(); } @@ -180,8 +181,7 @@ protected: /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted /// as another region. - SValuator::CastResult CastRetrievedVal(SVal val, const GRState *state, - const TypedRegion *R, QualType castTy); + SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy); }; // FIXME: Do we still need this? diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 7aaae9c86653..78827dfabe2f 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -33,13 +33,10 @@ public: BlockEntranceKind, BlockExitKind, PreStmtKind, - // Keep the following together and in this order. PostStmtKind, - PostLocationChecksSucceedKind, - PostOutOfBoundsCheckFailedKind, - PostNullCheckFailedKind, - PostUndefLocationCheckFailedKind, + PreLoadKind, PostLoadKind, + PreStoreKind, PostStoreKind, PostPurgeDeadSymbolsKind, PostStmtCustomKind, @@ -194,17 +191,6 @@ public: } }; -class PostLocationChecksSucceed : public PostStmt { -public: - PostLocationChecksSucceed(const Stmt* S, const LocationContext *L, - const void *tag = 0) - : PostStmt(S, PostLocationChecksSucceedKind, L, tag) {} - - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostLocationChecksSucceedKind; - } -}; - class PostStmtCustom : public PostStmt { public: PostStmtCustom(const Stmt* S, @@ -226,36 +212,36 @@ public: } }; -class PostOutOfBoundsCheckFailed : public PostStmt { -public: - PostOutOfBoundsCheckFailed(const Stmt* S, const LocationContext *L, - const void *tag = 0) - : PostStmt(S, PostOutOfBoundsCheckFailedKind, L, tag) {} - - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostOutOfBoundsCheckFailedKind; + +class LocationCheck : public StmtPoint { +protected: + LocationCheck(const Stmt *S, const LocationContext *L, + ProgramPoint::Kind K, const void *tag) + : StmtPoint(S, NULL, K, L, tag) {} + + static bool classof(const ProgramPoint *location) { + unsigned k = location->getKind(); + return k == PreLoadKind || k == PreStoreKind; } }; - -class PostUndefLocationCheckFailed : public PostStmt { + +class PreLoad : public LocationCheck { public: - PostUndefLocationCheckFailed(const Stmt* S, const LocationContext *L, - const void *tag = 0) - : PostStmt(S, PostUndefLocationCheckFailedKind, L, tag) {} - - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostUndefLocationCheckFailedKind; + PreLoad(const Stmt *S, const LocationContext *L, const void *tag = 0) + : LocationCheck(S, L, PreLoadKind, tag) {} + + static bool classof(const ProgramPoint *location) { + return location->getKind() == PreLoadKind; } }; -class PostNullCheckFailed : public PostStmt { +class PreStore : public LocationCheck { public: - PostNullCheckFailed(const Stmt* S, const LocationContext *L, - const void *tag = 0) - : PostStmt(S, PostNullCheckFailedKind, L, tag) {} - - static bool classof(const ProgramPoint* Location) { - return Location->getKind() == PostNullCheckFailedKind; + PreStore(const Stmt *S, const LocationContext *L, const void *tag = 0) + : LocationCheck(S, L, PreStoreKind, tag) {} + + static bool classof(const ProgramPoint *location) { + return location->getKind() == PreStoreKind; } }; diff --git a/include/clang/Analysis/Support/Optional.h b/include/clang/Analysis/Support/Optional.h index 3940007bb574..40f38be020a9 100644 --- a/include/clang/Analysis/Support/Optional.h +++ b/include/clang/Analysis/Support/Optional.h @@ -39,6 +39,9 @@ public: } //end clang namespace namespace llvm { + +template<typename T> struct simplify_type; + template <typename T> struct simplify_type<const ::clang::Optional<T> > { typedef const T* SimpleType; diff --git a/include/clang/Analysis/Support/SaveAndRestore.h b/include/clang/Analysis/Support/SaveAndRestore.h index 4720c22d990e..f720639490d9 100644 --- a/include/clang/Analysis/Support/SaveAndRestore.h +++ b/include/clang/Analysis/Support/SaveAndRestore.h @@ -22,6 +22,9 @@ namespace clang { template<typename T> struct SaveAndRestore { SaveAndRestore(T& x) : X(x), old_value(x) {} + SaveAndRestore(T& x, const T &new_value) : X(x), old_value(x) { + X = new_value; + } ~SaveAndRestore() { X = old_value; } T get() { return old_value; } private: diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 77a2079b766d..3a70e134b82b 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -32,6 +32,7 @@ namespace clang { class IdentifierInfo; class LangOptions; class PartialDiagnostic; + class Preprocessor; class SourceRange; // Import the diagnostic enums themselves. @@ -105,6 +106,10 @@ public: /// modification is known. CodeModificationHint() : RemoveRange(), InsertionLoc() { } + bool isNull() const { + return !RemoveRange.isValid() && !InsertionLoc.isValid(); + } + /// \brief Create a code modification hint that inserts the given /// code string at a specific location. static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc, @@ -382,6 +387,7 @@ public: /// @c Pos represents the source location associated with the diagnostic, /// which can be an invalid location if no position information is available. inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID); + inline DiagnosticBuilder Report(unsigned DiagID); /// \brief Clear out the current diagnostic. void Clear() { CurDiagID = ~0U; } @@ -586,6 +592,9 @@ public: } void AddCodeModificationHint(const CodeModificationHint &Hint) const { + if (Hint.isNull()) + return; + assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints && "Too many code modification hints!"); if (DiagObj) @@ -664,6 +673,9 @@ inline DiagnosticBuilder Diagnostic::Report(FullSourceLoc Loc, unsigned DiagID){ CurDiagID = DiagID; return DiagnosticBuilder(this); } +inline DiagnosticBuilder Diagnostic::Report(unsigned DiagID) { + return Report(FullSourceLoc(), DiagID); +} //===----------------------------------------------------------------------===// // DiagnosticInfo @@ -780,7 +792,8 @@ public: /// \arg LO - The language options for the source file being processed. /// \arg PP - The preprocessor object being used for the source; this optional /// and may not be present, for example when processing AST source files. - virtual void BeginSourceFile(const LangOptions &LangOpts) {} + virtual void BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP = 0) {} /// EndSourceFile - Callback to inform the diagnostic client that processing /// of a source file has ended. The diagnostic client should assume that any diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index bb251ad73bd8..9a342b592ca5 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -52,4 +52,11 @@ def warn_integer_too_large_for_signed : Warning< def note_invalid_subexpr_in_ice : Note< "subexpression not valid in an integer constant expression">; +// Targets + +def err_target_unknown_triple : Error< + "unknown target triple '%0', please use -triple or -arch">; +def err_target_unknown_abi : Error<"unknown target ABI '%0'">; +def err_target_invalid_feature : Error<"invalid target feature '%0'">; + } diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index ae8b92394443..e9b351ffe995 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -9,19 +9,33 @@ let Component = "Frontend" in { -def err_fe_unknown_triple : Error< - "unknown target triple '%0', please use -triple or -arch">; -def err_fe_unknown_target_abi : Error<"unknown target ABI '%0'">; def err_fe_error_opening : Error<"error opening '%0': %1">; def err_fe_error_reading : Error<"error reading '%0'">; def err_fe_error_reading_stdin : Error<"error reading stdin">; def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal; def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal; -def err_fe_invalid_code_complete_file +def err_fe_invalid_code_complete_file : Error<"cannot locate code-completion file %0">, DefaultFatal; def err_fe_dependency_file_requires_MT : Error< "-dependency-file requires at least one -MT option">; +def err_fe_incompatible_options : Error< + "'%0' cannot be used with '%1'">, DefaultFatal; +def err_fe_no_fixit_and_codegen : Error< + "FIX-ITs cannot be applied when generating code">; +def err_fe_unable_to_find_fixit_file : Error< + "FIX-IT could not find file '%0'">; +def err_fe_invalid_plugin_name : Error< + "unable to find plugin '%0'">; + +def err_verify_bogus_characters : Error< + "bogus characters before '{{' in expected string">; +def err_verify_missing_start : Error< + "cannot find start ('{{') of expected string">; +def err_verify_missing_end : Error< + "cannot find end ('}}') of expected string">; +def err_verify_inconsistent_diags : Error< + "'%0' diagnostics %select{expected|seen}1 but not %select{seen|expected}1: %2">; def note_fixit_applied : Note<"FIX-IT applied suggested code changes">; def note_fixit_in_macro : Note< @@ -162,6 +176,9 @@ def warn_pch_access_control : Error< def warn_pch_char_signed : Error< "char was %select{unsigned|signed}0 in the PCH file but " "is currently %select{unsigned|signed}1">; +def warn_pch_short_wchar : Error< + "-fshort-wchar was %select{disabled|enabled}0 in the PCH file but " + "is currently %select{disabled|enabled}1">; def err_not_a_pch_file : Error< "'%0' does not appear to be a precompiled header file">, DefaultFatal; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 8cfdd4095027..93c655b50500 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -28,7 +28,7 @@ def : DiagGroup<"cast-align">; def : DiagGroup<"cast-qual">; def : DiagGroup<"char-align">; def Comment : DiagGroup<"comment">; -def : DiagGroup<"conversion">; +def : DiagGroup<"ctor-dtor-privacy">; def : DiagGroup<"declaration-after-statement">; def : DiagGroup<"disabled-optimization">; def : DiagGroup<"discard-qual">; @@ -40,6 +40,7 @@ def FormatExtraArgs : DiagGroup<"format-extra-args">; def FormatZeroLength : DiagGroup<"format-zero-length">; def FourByteMultiChar : DiagGroup<"four-char-constants">; +def : DiagGroup<"idiomatic-parentheses">; def : DiagGroup<"import">; def : DiagGroup<"init-self">; def : DiagGroup<"inline">; @@ -58,19 +59,21 @@ def MismatchedTags : DiagGroup<"mismatched-tags">; def : DiagGroup<"missing-field-initializers">; def NonNull : DiagGroup<"nonnull">; def : DiagGroup<"nonportable-cfstrings">; +def : DiagGroup<"non-virtual-dtor">; def : DiagGroup<"old-style-definition">; def : DiagGroup<"overflow">; def : DiagGroup<"overloaded-virtual">; def : DiagGroup<"packed">; -def Parentheses : DiagGroup<"parentheses">; def PointerArith : DiagGroup<"pointer-arith">; def : DiagGroup<"pointer-to-int-cast">; def : DiagGroup<"redundant-decls">; def ReturnType : DiagGroup<"return-type">; +def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; def : DiagGroup<"sequence-point">; def : DiagGroup<"shadow">; def : DiagGroup<"shorten-64-to-32">; -def : DiagGroup<"sign-compare">; +def SignCompare : DiagGroup<"sign-compare">; +def : DiagGroup<"synth">; // Preprocessor warnings. def : DiagGroup<"builtin-macro-redefined">; @@ -114,6 +117,14 @@ def CharSubscript : DiagGroup<"char-subscripts">; // Aggregation warning settings. +// -Widiomatic-parentheses contains warnings about 'idiomatic' +// missing parentheses; it is off by default. +def Parentheses : DiagGroup<"parentheses", [DiagGroup<"idiomatic-parentheses">]>; + +// -Wconversion has its own warnings, but we split this one out for +// legacy reasons. +def Conversion : DiagGroup<"conversion", + [DiagGroup<"shorten-64-to-32">]>; def Unused : DiagGroup<"unused", [UnusedArgument, UnusedFunction, UnusedLabel, @@ -127,8 +138,9 @@ def FormatY2K : DiagGroup<"format-y2k", [Format]>; def Format2 : DiagGroup<"format=2", [FormatNonLiteral, FormatSecurity, FormatY2K]>; - def Extra : DiagGroup<"extra", [ + SemiBeforeMethodBody, + SignCompare, UnusedParameter ]>; @@ -158,3 +170,7 @@ def : DiagGroup<"all", [Most, Parentheses]>; def : DiagGroup<"", [Extra]>; // -W = -Wextra def : DiagGroup<"endif-labels", [ExtraTokens]>; // endif-labels = endif-tokens +// A warning group for warnings that we want to have on by default in clang, +// but which aren't on by default in GCC. +def NonGCC : DiagGroup<"non-gcc", + [SignCompare, Conversion]>; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index bbc551373d96..7f3f4ea1fca0 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -90,6 +90,14 @@ def warn_octal_escape_too_large : ExtWarn<"octal escape sequence out of range">; def warn_hex_escape_too_large : ExtWarn<"hex escape sequence out of range">; //===----------------------------------------------------------------------===// +// PTH Diagnostics +//===----------------------------------------------------------------------===// +def err_pth_cannot_read : Error< + "PTH file '%0' could not be read">; +def err_invalid_pth_file : Error< + "invalid or corrupt PTH file '%0'">; + +//===----------------------------------------------------------------------===// // Preprocessor Diagnostics //===----------------------------------------------------------------------===// def pp_hash_warning : Warning<"#warning%0">, InGroup<DiagGroup<"#warnings">>; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index e173cffdfd2b..28c46cd2d707 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -201,9 +201,9 @@ def warn_expected_implementation : Warning< "@end must appear in an @implementation context">; def error_property_ivar_decl : Error< "property synthesize requires specification of an ivar">; -def warn_semicolon_before_method_nody : Warning< +def warn_semicolon_before_method_body : Warning< "semicolon before method body is ignored">, - InGroup<DiagGroup<"semicolon-before-method-body">>; + InGroup<DiagGroup<"semicolon-before-method-body">>, DefaultIgnore; def err_expected_field_designator : Error< "expected a field designator, such as '.field = 4'">; @@ -230,7 +230,7 @@ def ext_ellipsis_exception_spec : Extension< def err_expected_catch : Error<"expected catch">; def err_expected_lbrace_or_comma : Error<"expected '{' or ','">; def err_using_namespace_in_class : Error< - "'using namespace' in class not allowed">; + "'using namespace' is not allowed in classes">; def err_ident_in_pseudo_dtor_not_a_type : Error< "identifier %0 in pseudo-destructor expression does not name a type">; @@ -289,6 +289,10 @@ def err_explicit_spec_non_template : Error< def err_variadic_templates : Error< "variadic templates are only allowed in C++0x">; +def err_default_template_template_parameter_not_template : Error< + "default template argument for a template template parameter must be a class " + "template">; + // C++ declarations def err_friend_decl_defines_class : Error< "cannot define a type in a friend declaration">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 2309908df7b4..78a3ae5d47b7 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -103,6 +103,8 @@ def err_using_requires_qualname : Error< "using declaration requires a qualified name">; def err_using_typename_non_type : Error< "'typename' keyword used on a non-type">; +def err_using_dependent_value_is_type : Error< + "dependent using declaration resolved to type without 'typename'">; def err_using_decl_nested_name_specifier_is_not_a_base_class : Error< "using declaration refers into '%0', which is not a base class of %1">; def err_using_decl_can_not_refer_to_class_member : Error< @@ -115,6 +117,8 @@ def err_using_decl_destructor : Error< "using declaration can not refer to a destructor">; def err_using_decl_template_id : Error< "using declaration can not refer to a template specialization">; +def note_using_decl_target : Note< + "target of using declaration">; def err_invalid_thread : Error< "'__thread' is only allowed on variable declarations">; @@ -251,6 +255,7 @@ def warn_accessor_property_type_mismatch : Warning< def note_declared_at : Note<"declared at">; def err_setter_type_void : Error<"type of setter must be void">; def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; +def warn_missing_atend : Warning<"'@end' is missing in implementation context">; def err_objc_var_decl_inclass : Error<"cannot declare variable inside @interface or @protocol">; def error_missing_method_context : Error< @@ -269,6 +274,9 @@ def warn_property_attr_mismatch : Warning< def warn_objc_property_copy_missing_on_block : Warning< "'copy' attribute must be specified for the block property " "when -fobjc-gc-only is specified">; +def warn_atomic_property_rule : Warning< + "writable atomic property %0 cannot pair a synthesized setter/getter " + "with a user defined setter/getter">; def err_use_continuation_class : Error< "property declaration in continuation class of %0 is to change a 'readonly' " "property to 'readwrite'">; @@ -397,7 +405,9 @@ def note_ambig_member_ref_scope : Note< "lookup from the current scope refers here">; def err_qualified_member_nonclass : Error< "qualified member access refers to a member in %0">; - +def err_incomplete_member_access : Error< + "member access into incomplete type %0">; + // C++ class members def err_storageclass_invalid_for_member : Error< "storage class specified for a member declaration">; @@ -430,9 +440,15 @@ def err_implicit_object_parameter_init : Error< "cannot initialize object parameter of type %0 with an expression " "of type %1">; -def err_missing_default_constructor : Error< - "default constructor for %1 is missing in initialization of " - "%select{base class|member}0">; +def note_field_decl : Note<"member is declared here">; +def note_previous_class_decl : Note< + "%0 declared here">; +def note_ctor_synthesized_at : Note< + "implicit default constructor for %0 first required here">; +def err_missing_default_ctor : Error< + "%select{|implicit default }0constructor for %1 must explicitly initialize " + "the %select{base class|member}2 %3 which does not have a default " + "constructor">; def err_illegal_union_member : Error< "union member %0 has a non-trivial %select{constructor|" "copy constructor|copy assignment operator|destructor}1">; @@ -632,6 +648,25 @@ def err_cconv_knr : Error< def err_cconv_varargs : Error< "variadic function cannot use '%0' calling convention">; +def warn_impcast_vector_scalar : Warning< + "implicit cast turns vector to scalar: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_complex_scalar : Warning< + "implicit cast discards imaginary component: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_float_precision : Warning< + "implicit cast loses floating-point precision: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_float_integer : Warning< + "implicit cast turns floating-point number into integer: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_integer_precision : Warning< + "implicit cast loses integer precision: %0 to %1">, + InGroup<DiagGroup<"conversion">>, DefaultIgnore; +def warn_impcast_integer_64_32 : Warning< + "implicit cast loses integer precision: %0 to %1">, + InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore; + def warn_attribute_ignored_for_field_of_type : Warning< "%0 attribute ignored for field of type %1">; def warn_transparent_union_attribute_field_size_align : Warning< @@ -744,27 +779,18 @@ def err_param_default_argument_member_template_redecl : Error< "default arguments cannot be added to an out-of-line definition of a member " "of a %select{class template|class template partial specialization|nested " "class in a template}0">; -def note_field_decl : Note<"member is declared here">; -def err_defining_default_ctor : Error< - "cannot define the implicit default constructor for %0, because %select{base class|member's type}1 " - "%2 does not have any default constructor">; -def note_previous_class_decl : Note< - "%0 declared here">; def err_uninitialized_member_for_assign : Error< "cannot define the implicit default assignment operator for %0, because " "non-static %select{reference|const}1 member %2 can't use default " "assignment operator">; def note_first_required_here : Note< "synthesized method is first required here">; -def err_unintialized_member : Error< - "cannot define the implicit default constructor for %0, because " - "%select{reference|const}1 member %2 cannot be default-initialized">; def err_null_intialized_reference_member : Error< "cannot initialize the member to null in default constructor because " "reference member %0 cannot be null-initialized">; def err_unintialized_member_in_ctor : Error< - "constructor for %0 must explicitly initialize the " - "%select{reference|const}1 member %2 ">; + "%select{|implicit default }0constructor for %1 must explicitly initialize " + "the %select{reference|const}2 member %3">; def err_use_of_default_argument_to_function_declared_later : Error< "use of default argument to function %0 that is declared later in class %1">; @@ -993,6 +1019,9 @@ def err_template_spec_friend : Error< def err_template_spec_default_arg : Error< "default argument not permitted on an explicit " "%select{instantiation|specialization}0 of function %1">; +def err_not_class_template_specialization : Error< + "cannot specialize a %select{dependent template|template template " + "parameter}0">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< @@ -1083,6 +1112,12 @@ def note_function_template_deduction_instantiation_here : Note< def note_partial_spec_deduct_instantiation_here : Note< "during template argument deduction for class template partial " "specialization %0, here">; +def note_prior_template_arg_substitution : Note< + "while substituting prior template arguments into %select{non-type|template}0" + " template parameter%1 %2">; +def note_template_default_arg_checking : Note< + "while checking a default template argument used here">; + def err_field_instantiates_to_function : Error< "data member instantiated with function type %0">; def err_nested_name_spec_non_tag : Error< @@ -1447,8 +1482,9 @@ def err_typecheck_member_reference_type : Error< "cannot refer to type member %0 with '%select{.|->}1'">; def err_typecheck_member_reference_unknown : Error< "cannot refer to member %0 with '%select{.|->}1'">; -def note_member_reference_needs_call : Note< - "perhaps you meant to call this function with '()'?">; +def err_member_reference_needs_call : Error< + "base of member reference has function type %0; perhaps you meant to call " + "this function with '()'?">; def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, InGroup<CharSubscript>, DefaultIgnore; @@ -1488,6 +1524,9 @@ def err_tentative_def_incomplete_type_arr : Error< "tentative definition has array of type %0 that is never completed">; def warn_tentative_incomplete_array : Warning< "tentative array definition assumed to have one element">; +def err_typecheck_incomplete_array_needs_initializer : Error< + "definition of variable with array type needs an explicit size " + "or an initializer">; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; def err_typecheck_sclass_fscope : Error< @@ -1539,10 +1578,10 @@ def err_stmtexpr_file_scope : Error< "statement expression not allowed at file scope">; def warn_mixed_sign_comparison : Warning< "comparison of integers of different signs: %0 and %1">, - InGroup<DiagGroup<"sign-compare">>; + InGroup<DiagGroup<"sign-compare">>, DefaultIgnore; def warn_mixed_sign_conditional : Warning< "operands of ? are integers of different signs: %0 and %1">, - InGroup<DiagGroup<"sign-compare">>; + InGroup<DiagGroup<"sign-compare">>, DefaultIgnore; def err_invalid_this_use : Error< "invalid use of 'this' outside of a nonstatic member function">; @@ -1707,6 +1746,10 @@ def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete " "expression of type %0 to a pointer">; def warn_delete_incomplete : Warning< "deleting pointer to incomplete type %0 may cause undefined behaviour">; +def err_no_suitable_delete_member_function_found : Error< + "no suitable member %0 in %1">; +def note_delete_member_function_declared_here : Note< + "%0 declared here">; def err_decrement_bool : Error<"cannot decrement expression of type bool">; def warn_increment_bool : Warning< "incrementing expression of type bool is deprecated">; @@ -1786,9 +1829,13 @@ def err_incomplete_object_call : Error< def warn_condition_is_assignment : Warning<"using the result of an " "assignment as a condition without parentheses">, InGroup<Parentheses>; +// Completely identical except off by default. +def warn_condition_is_idiomatic_assignment : Warning<"using the result " + "of an assignment as a condition without parentheses">, + InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore; -def warn_value_always_zero : Warning<"%0 is always zero in this context">; -def warn_value_always_false : Warning<"%0 is always false in this context">; +def warn_value_always_zero : Warning< + "%0 is always %select{zero|false|NULL}1 in this context">; // assignment related diagnostics (also for argument passing, returning, etc). // FIXME: %2 is an english string here. @@ -1816,6 +1863,8 @@ def ext_typecheck_convert_incompatible_pointer : ExtWarn< "incompatible pointer types %2 %1, expected %0">; def ext_typecheck_convert_discards_qualifiers : ExtWarn< "%2 %1 discards qualifiers, expected %0">; +def ext_nested_pointer_qualifier_mismatch : ExtWarn< + "%2, %0 and %1 have different qualifiers in nested pointer types">; def warn_incompatible_vectors : Warning< "incompatible vector types %2 %1, expected %0">, InGroup<VectorConversions>, DefaultIgnore; @@ -2086,6 +2135,10 @@ def err_operator_overload_needs_class_or_enum : Error< def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">; def err_operator_overload_static : Error< "overloaded %0 cannot be a static member function">; +def err_operator_new_param_type : Error< + "%0 takes type size_t (%1) as first parameter">; +def err_operator_new_result_type : Error< + "%0 must return type %1">; def err_operator_overload_default_arg : Error< "parameter of overloaded %0 cannot have a default argument">; def err_operator_overload_must_be : Error< @@ -2328,7 +2381,7 @@ def error_private_ivar_access : Error<"instance variable %0 is private">, NoSFINAE; def error_protected_ivar_access : Error<"instance variable %0 is protected">, NoSFINAE; -def warn_maynot_respond : Warning<"%0 may not respond to %1">; +def warn_maynot_respond : Warning<"%0 may not respond to %1">; def warn_attribute_method_def : Warning< "method attribute can only be specified on method declarations">; def ext_typecheck_base_super : Warning< diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index d4d3fe50eba0..99c100d55e7e 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -55,6 +55,7 @@ public: unsigned POSIXThreads : 1; // Compiling with POSIX thread support // (-pthread) unsigned Blocks : 1; // block extension to C + unsigned BlockIntrospection: 1; // block have ObjC type encodings. unsigned EmitAllDecls : 1; // Emit all declarations, even if // they are unused. unsigned MathErrno : 1; // Math functions must respect errno @@ -83,6 +84,7 @@ public: unsigned AccessControl : 1; // Whether C++ access control should // be enabled. unsigned CharIsSigned : 1; // Whether char is a signed or unsigned type + unsigned ShortWChar : 1; // Force wchar_t to be unsigned short int. unsigned OpenCL : 1; // OpenCL C99 language extensions. @@ -125,7 +127,8 @@ public: ObjCConstantStringClass = 0; C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = 0; - Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0; + Exceptions = Freestanding = NoBuiltin = 0; + NeXTRuntime = 1; Rtti = 1; LaxVectorConversions = 1; HeinousExtensions = 0; @@ -137,6 +140,7 @@ public: ThreadsafeStatics = 0; POSIXThreads = 0; Blocks = 0; + BlockIntrospection = 0; EmitAllDecls = 0; MathErrno = 1; @@ -159,6 +163,7 @@ public: NoInline = 0; CharIsSigned = 1; + ShortWChar = 0; MainFileName = 0; } diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile index 6ed5fefb7e64..b85eb0725ef0 100644 --- a/include/clang/Basic/Makefile +++ b/include/clang/Basic/Makefile @@ -9,12 +9,14 @@ TABLEGEN_INC_FILES_COMMON = 1 include $(LEVEL)/Makefile.common +INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td) + $(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN) $(Echo) "Building Clang $(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) diagnostic tables with tblgen" $(Verb) -$(MKDIR) $(@D) $(Verb) $(TableGen) -gen-clang-diags-defs -clang-component=$(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) -o $(call SYSPATH, $@) $< -$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(wildcard Diagnostic*.td) $(TBLGEN) +$(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN) $(Echo) "Building Clang diagnostic groups with tblgen" $(Verb) -$(MKDIR) $(@D) $(Verb) $(TableGen) -gen-clang-diag-groups -o $(call SYSPATH, $@) $< diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index e61ef9265cfb..695f51d2c4c9 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -28,11 +28,12 @@ class StringRef; } namespace clang { - class Diagnostic; +class LangOptions; class SourceLocation; class SourceManager; -class LangOptions; +class TargetOptions; + namespace Builtin { struct Info; } /// TargetInfo - This class exposes information about the current target. @@ -44,16 +45,12 @@ protected: // values are specified by the TargetInfo constructor. bool TLSSupported; unsigned char PointerWidth, PointerAlign; - unsigned char WCharWidth, WCharAlign; - unsigned char Char16Width, Char16Align; - unsigned char Char32Width, Char32Align; unsigned char IntWidth, IntAlign; unsigned char FloatWidth, FloatAlign; unsigned char DoubleWidth, DoubleAlign; unsigned char LongDoubleWidth, LongDoubleAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; - unsigned char IntMaxTWidth; const char *DescriptionString; const char *UserLabelPrefix; const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat; @@ -63,9 +60,9 @@ protected: TargetInfo(const std::string &T); public: - /// CreateTargetInfo - Return the target info object for the specified target - /// triple. - static TargetInfo* CreateTargetInfo(const std::string &Triple); + /// CreateTargetInfo - Construct a target for the given options. + static TargetInfo* CreateTargetInfo(Diagnostic &Diags, + const TargetOptions &Opts); virtual ~TargetInfo(); @@ -103,6 +100,10 @@ public: /// enum. For example, SignedInt -> getIntWidth(). unsigned getTypeWidth(IntType T) const; + /// getTypeAlign - Return the alignment (in bits) of the specified integer + /// type enum. For example, SignedInt -> getIntAlign(). + unsigned getTypeAlign(IntType T) const; + /// isTypeSigned - Return whether an integer types is signed. Returns true if /// the type is signed; false otherwise. bool isTypeSigned(IntType T) const; @@ -146,18 +147,18 @@ public: /// getWCharWidth/Align - Return the size of 'wchar_t' for this target, in /// bits. - unsigned getWCharWidth() const { return WCharWidth; } - unsigned getWCharAlign() const { return WCharAlign; } + unsigned getWCharWidth() const { return getTypeWidth(WCharType); } + unsigned getWCharAlign() const { return getTypeAlign(WCharType); } /// getChar16Width/Align - Return the size of 'char16_t' for this target, in /// bits. - unsigned getChar16Width() const { return Char16Width; } - unsigned getChar16Align() const { return Char16Align; } + unsigned getChar16Width() const { return getTypeWidth(Char16Type); } + unsigned getChar16Align() const { return getTypeAlign(Char16Type); } /// getChar32Width/Align - Return the size of 'char32_t' for this target, in /// bits. - unsigned getChar32Width() const { return Char32Width; } - unsigned getChar32Align() const { return Char32Align; } + unsigned getChar32Width() const { return getTypeWidth(Char32Type); } + unsigned getChar32Align() const { return getTypeAlign(Char32Type); } /// getFloatWidth/Align/Format - Return the size/align/format of 'float'. unsigned getFloatWidth() const { return FloatWidth; } @@ -180,7 +181,7 @@ public: /// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this /// target, in bits. unsigned getIntMaxTWidth() const { - return IntMaxTWidth; + return getTypeWidth(IntMaxType); } /// getUserLabelPrefix - This returns the default value of the @@ -341,10 +342,10 @@ public: return ""; } - /// getDefaultLangOptions - Allow the target to specify default settings for - /// various language options. These may be overridden by command line - /// options. - virtual void getDefaultLangOptions(LangOptions &Opts) {} + /// setForcedLangOptions - Set forced language options. + /// Apply changes to the target information with respect to certain + /// language options which change the target configuration. + virtual void setForcedLangOptions(LangOptions &Opts); /// getDefaultFeatures - Get the default set of target features for /// the \args CPU; this should include all legal feature strings on @@ -375,9 +376,10 @@ public: return false; } - /// HandleTargetOptions - Perform initialization based on the user - /// configured set of features. - virtual void HandleTargetFeatures(const llvm::StringMap<bool> &Features) { + /// HandleTargetOptions - Perform initialization based on the user configured + /// set of features (e.g., +sse4). The list is guaranteed to have at most one + /// entry per feature. + virtual void HandleTargetFeatures(const std::vector<std::string> &Features) { } // getRegParmMax - Returns maximal number of args passed in registers. diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h new file mode 100644 index 000000000000..eeaab1558fd1 --- /dev/null +++ b/include/clang/Basic/TargetOptions.h @@ -0,0 +1,39 @@ +//===--- TargetOptions.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H +#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// TargetOptions - Options for controlling the target. +class TargetOptions { +public: + + /// If given, the name of the target triple to compile for. If not given the + /// target will be selected to match the host. + std::string Triple; + + /// If given, the name of the target CPU to generate code for. + std::string CPU; + + /// If given, the name of the target ABI to use. + std::string ABI; + + /// The list of target specific features to enable or disable -- this should + /// be a list of strings starting with by '+' or '-'. + std::vector<std::string> Features; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h new file mode 100644 index 000000000000..02679cd99895 --- /dev/null +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -0,0 +1,75 @@ +//===--- CodeGenOptions.h ---------------------------------------*- 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 the CodeGenOptions interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H +#define LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// CodeGenOptions - Track various options which control how the code +/// is optimized and passed to the backend. +class CodeGenOptions { +public: + enum InliningMethod { + NoInlining, // Perform no inlining whatsoever. + NormalInlining, // Use the standard function inlining pass. + OnlyAlwaysInlining // Only run the always inlining pass. + }; + + unsigned DebugInfo : 1; /// Should generate deubg info (-g). + unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in + /// getting .bc files that correspond to the + /// internal state before optimizations are + /// done. + unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. + unsigned MergeAllConstants : 1; /// Merge identical constants. + unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. + unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. + unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. + unsigned OptimizeSize : 1; /// If -Os is specified. + unsigned SimplifyLibCalls : 1; /// Should standard library calls be treated + /// specially. + unsigned TimePasses : 1; /// Set when -ftime-report is enabled. + unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization + /// selection. + unsigned UnrollLoops : 1; /// Control whether loops are unrolled. + unsigned VerifyModule : 1; /// Control whether the module should be run + /// through the LLVM Verifier. + + /// Inlining - The kind of inlining to perform. + InliningMethod Inlining; + +public: + CodeGenOptions() { + OptimizationLevel = 0; + OptimizeSize = 0; + DebugInfo = 0; + UnitAtATime = 1; + SimplifyLibCalls = UnrollLoops = 0; + VerifyModule = 1; + TimePasses = 0; + NoCommon = 0; + Inlining = NoInlining; + DisableRedZone = 0; + NoImplicitFloat = 0; + MergeAllConstants = 1; + DisableLLVMOpts = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index 1871c8f206f3..2a3aa6a90404 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -25,7 +25,7 @@ namespace llvm { namespace clang { class Diagnostic; class LangOptions; - class CompileOptions; + class CodeGenOptions; class CodeGenerator : public ASTConsumer { public: @@ -35,7 +35,7 @@ namespace clang { CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags, const std::string &ModuleName, - const CompileOptions &CO, + const CodeGenOptions &CGO, llvm::LLVMContext& C); } diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index c0327a2f1d1c..d3ab1153371a 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -48,7 +48,7 @@ class Driver { public: // Diag - Forwarding function for diagnostics. DiagnosticBuilder Diag(unsigned DiagID) const { - return Diags.Report(FullSourceLoc(), DiagID); + return Diags.Report(DiagID); } // FIXME: Privatize once interface is stable. diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def index 5370114ee824..2b66b3506b01 100644 --- a/include/clang/Driver/Options.def +++ b/include/clang/Driver/Options.def @@ -368,6 +368,7 @@ OPTION("-fastcp", fastcp, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fastf", fastf, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fast", fast, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fasynchronous-unwind-tables", fasynchronous_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0) +OPTION("-fblock-introspection", fblock_introspection, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fblocks", fblocks, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fbootclasspath=", fbootclasspath_EQ, Joined, f_Group, INVALID, "", 0, 0, 0) OPTION("-fbuiltin-strcat", fbuiltin_strcat, Flag, f_Group, INVALID, "", 0, 0, 0) @@ -430,6 +431,7 @@ OPTION("-fno-inline", fno_inline, Flag, clang_ignored_f_Group, INVALID, "", 0, 0 OPTION("-fno-keep-inline-functions", fno_keep_inline_functions, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-merge-all-constants", fno_merge_all_constants, Flag, f_Group, INVALID, "", 0, 0, 0) +OPTION("-fno-ms-extensions", fno_ms_extensions, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-omit-frame-pointer", fno_omit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-rtti", fno_rtti, Flag, f_Group, INVALID, "", 0, 0, 0) @@ -448,7 +450,6 @@ OPTION("-fobjc-gc", fobjc_gc, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fobjc-new-property", fobjc_new_property, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) OPTION("-fobjc-nonfragile-abi", fobjc_nonfragile_abi, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fobjc-sender-dependent-dispatch", fobjc_sender_dependent_dispatch, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fobjc-tight-layout", fobjc_tight_layout, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fobjc", fobjc, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fomit-frame-pointer", fomit_frame_pointer, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fopenmp", fopenmp, Flag, f_Group, INVALID, "", 0, 0, 0) @@ -463,6 +464,7 @@ OPTION("-fprofile-arcs", fprofile_arcs, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fprofile-generate", fprofile_generate, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0) OPTION("-frtti", frtti, Flag, f_Group, INVALID, "", 0, 0, 0) +OPTION("-fshort-wchar", fshort_wchar, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0) diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index b7630d8afdb8..df651a6c3d00 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -90,6 +90,17 @@ public: /// default. virtual bool IsMathErrnoDefault() const = 0; + /// IsBlocksDefault - Does this tool chain enable -fblocks by default. + virtual bool IsBlocksDefault() const { return false; } + + /// IsObjCNonFragileABIDefault - Does this tool chain set + /// -fobjc-nonfragile-abi by default. + virtual bool IsObjCNonFragileABIDefault() const { return false; } + + /// GetDefaultStackProtectorLevel - Get the default stack protector level for + /// this tool chain (0=off, 1=on, 2=all). + virtual unsigned GetDefaultStackProtectorLevel() const { return 0; } + /// IsUnwindTablesDefault - Does this tool chain use -funwind-tables /// by default. virtual bool IsUnwindTablesDefault() const = 0; diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index 92520a77b33b..3a343b385e7a 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -62,6 +62,9 @@ namespace types { /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers). bool isCXX(ID Id); + /// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers). + bool isObjC(ID Id); + /// lookupTypeForExtension - Lookup the type to use for the file /// extension \arg Ext. ID lookupTypeForExtension(const char *Ext); diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 742813c66907..0e7d55e6e45b 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -25,11 +25,12 @@ namespace llvm { namespace clang { class ASTConsumer; +class CodeGenOptions; class Diagnostic; class FileManager; -class Preprocessor; -class CompileOptions; class LangOptions; +class Preprocessor; +class TargetOptions; // AST pretty-printer: prints out the AST in a format that is close to the // original C code. The output is intended to be in a format such that @@ -69,7 +70,7 @@ ASTConsumer *CreateObjCRewriter(const std::string &InFile, bool SilenceRewriteMacroWarning); // LLVM code generator: uses the code generation backend to generate LLVM -// assembly. This runs optimizations depending on the CompileOptions +// assembly. This runs optimizations depending on the CodeGenOptions // parameter. The output depends on the Action parameter. enum BackendAction { Backend_EmitAssembly, // Emit native assembly @@ -80,7 +81,8 @@ enum BackendAction { ASTConsumer *CreateBackendConsumer(BackendAction Action, Diagnostic &Diags, const LangOptions &Features, - const CompileOptions &CompileOpts, + const CodeGenOptions &CodeGenOpts, + const TargetOptions &TargetOpts, const std::string &ModuleID, llvm::raw_ostream *OS, llvm::LLVMContext& C); diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def index d5e408020a98..7d55673a612f 100644 --- a/include/clang/Frontend/Analyses.def +++ b/include/clang/Frontend/Analyses.def @@ -48,6 +48,9 @@ ANALYSIS(WarnObjCUnusedIvars, "warn-objc-unused-ivars", ANALYSIS(CheckerCFRef, "checker-cfref", "Run the [Core] Foundation reference count checker", Code) +ANALYSIS(WarnSizeofPointer, "warn-sizeof-pointer", + "Warn about unintended use of sizeof() on pointer expressions", Code) + ANALYSIS(InlineCall, "inline-call", "Experimental transfer function inling callees when its definition" " is available.", TranslationUnit) diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h index 34054a7aa00e..7a324331ecdc 100644 --- a/include/clang/Frontend/AnalysisConsumer.h +++ b/include/clang/Frontend/AnalysisConsumer.h @@ -1,4 +1,4 @@ -//===--- AnalysisConsumer.h - Front-end hooks for the analysis engine------===// +//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,6 +12,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H +#define LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H + #include <string> #include <vector> @@ -50,19 +53,37 @@ enum AnalysisDiagClients { NUM_ANALYSIS_DIAG_CLIENTS }; -struct AnalyzerOptions { +class AnalyzerOptions { +public: std::vector<Analyses> AnalysisList; AnalysisStores AnalysisStoreOpt; AnalysisConstraints AnalysisConstraintsOpt; AnalysisDiagClients AnalysisDiagOpt; - bool VisualizeEGDot; - bool VisualizeEGUbi; - bool AnalyzeAll; - bool AnalyzerDisplayProgress; - bool PurgeDead; - bool EagerlyAssume; std::string AnalyzeSpecificFunction; - bool TrimGraph; + unsigned AnalyzeAll : 1; + unsigned AnalyzerDisplayProgress : 1; + unsigned EagerlyAssume : 1; + unsigned PurgeDead : 1; + unsigned TrimGraph : 1; + unsigned VisualizeEGDot : 1; + unsigned VisualizeEGUbi : 1; + unsigned EnableExperimentalChecks : 1; + unsigned EnableExperimentalInternalChecks : 1; +public: + AnalyzerOptions() { + AnalysisStoreOpt = BasicStoreModel; + AnalysisConstraintsOpt = RangeConstraintsModel; + AnalysisDiagOpt = PD_HTML; + AnalyzeAll = 0; + AnalyzerDisplayProgress = 0; + EagerlyAssume = 0; + PurgeDead = 0; + TrimGraph = 0; + VisualizeEGDot = 0; + VisualizeEGUbi = 0; + EnableExperimentalChecks = 0; + EnableExperimentalInternalChecks = 0; + } }; /// CreateAnalysisConsumer - Creates an ASTConsumer to run various code @@ -73,3 +94,5 @@ ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp, const AnalyzerOptions& Opts); } + +#endif diff --git a/include/clang/Frontend/ChainedDiagnosticClient.h b/include/clang/Frontend/ChainedDiagnosticClient.h new file mode 100644 index 000000000000..2d5e128dac37 --- /dev/null +++ b/include/clang/Frontend/ChainedDiagnosticClient.h @@ -0,0 +1,58 @@ +//===--- ChainedDiagnosticClient.h - Chain Diagnostic Clients ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCLIENT_H +#define LLVM_CLANG_FRONTEND_CHAINEDDIAGNOSTICCLIENT_H + +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/OwningPtr.h" + +namespace clang { +class LangOptions; + +/// ChainedDiagnosticClient - Chain two diagnostic clients so that diagnostics +/// go to the first client and then the second. The first diagnostic client +/// should be the "primary" client, and will be used for computing whether the +/// diagnostics should be included in counts. +class ChainedDiagnosticClient : public DiagnosticClient { + llvm::OwningPtr<DiagnosticClient> Primary; + llvm::OwningPtr<DiagnosticClient> Secondary; + +public: + ChainedDiagnosticClient(DiagnosticClient *_Primary, + DiagnosticClient *_Secondary) { + Primary.reset(_Primary); + Secondary.reset(_Secondary); + } + + virtual void BeginSourceFile(const LangOptions &LO, + const Preprocessor *PP) { + Primary->BeginSourceFile(LO, PP); + Secondary->BeginSourceFile(LO, PP); + } + + virtual void EndSourceFile() { + Secondary->EndSourceFile(); + Primary->EndSourceFile(); + } + + virtual bool IncludeInDiagnosticCounts() const { + return Primary->IncludeInDiagnosticCounts(); + } + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info) { + Primary->HandleDiagnostic(DiagLevel, Info); + Secondary->HandleDiagnostic(DiagLevel, Info); + } +}; + +} // end namspace clang + +#endif diff --git a/include/clang/Frontend/CommandLineSourceLoc.h b/include/clang/Frontend/CommandLineSourceLoc.h index 59f70ede9129..d5a0598dfab2 100644 --- a/include/clang/Frontend/CommandLineSourceLoc.h +++ b/include/clang/Frontend/CommandLineSourceLoc.h @@ -1,3 +1,4 @@ + //===--- CommandLineSourceLoc.h - Parsing for source locations-*- C++ -*---===// // // The LLVM Compiler Infrastructure @@ -37,7 +38,7 @@ namespace llvm { class parser<clang::ParsedSourceLocation> : public basic_parser<clang::ParsedSourceLocation> { public: - bool parse(Option &O, StringRef ArgName, StringRef ArgValue, + inline bool parse(Option &O, StringRef ArgName, StringRef ArgValue, clang::ParsedSourceLocation &Val); }; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h new file mode 100644 index 000000000000..ed280508778a --- /dev/null +++ b/include/clang/Frontend/CompilerInstance.h @@ -0,0 +1,523 @@ +//===-- CompilerInstance.h - Clang Compiler Instance ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ +#define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ + +#include "clang/Frontend/CompilerInvocation.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/OwningPtr.h" +#include <cassert> +#include <list> +#include <string> + +namespace llvm { +class LLVMContext; +class raw_ostream; +class raw_fd_ostream; +} + +namespace clang { +class ASTContext; +class ASTConsumer; +class CodeCompleteConsumer; +class Diagnostic; +class DiagnosticClient; +class ExternalASTSource; +class FileManager; +class Preprocessor; +class Source; +class SourceManager; +class TargetInfo; + +/// CompilerInstance - Helper class for managing a single instance of the Clang +/// compiler. +/// +/// The CompilerInstance serves two purposes: +/// (1) It manages the various objects which are necessary to run the compiler, +/// for example the preprocessor, the target information, and the AST +/// context. +/// (2) It provides utility routines for constructing and manipulating the +/// common Clang objects. +/// +/// The compiler instance generally owns the instance of all the objects that it +/// manages. However, clients can still share objects by manually setting the +/// object and retaking ownership prior to destroying the CompilerInstance. +/// +/// The compiler instance is intended to simplify clients, but not to lock them +/// in to the compiler instance for everything. When possible, utility functions +/// come in two forms; a short form that reuses the CompilerInstance objects, +/// and a long form that takes explicit instances of any required objects. +class CompilerInstance { + /// The LLVM context used for this instance. + llvm::LLVMContext *LLVMContext; + bool OwnsLLVMContext; + + /// The options used in this compiler instance. + CompilerInvocation Invocation; + + /// The diagnostics engine instance. + llvm::OwningPtr<Diagnostic> Diagnostics; + + /// The diagnostics client instance. + llvm::OwningPtr<DiagnosticClient> DiagClient; + + /// The target being compiled for. + llvm::OwningPtr<TargetInfo> Target; + + /// The file manager. + llvm::OwningPtr<FileManager> FileMgr; + + /// The source manager. + llvm::OwningPtr<SourceManager> SourceMgr; + + /// The preprocessor. + llvm::OwningPtr<Preprocessor> PP; + + /// The AST context. + llvm::OwningPtr<ASTContext> Context; + + /// The AST consumer. + llvm::OwningPtr<ASTConsumer> Consumer; + + /// The code completion consumer. + llvm::OwningPtr<CodeCompleteConsumer> CompletionConsumer; + + /// The list of active output files. + std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles; + +public: + /// Create a new compiler instance with the given LLVM context, optionally + /// taking ownership of it. + CompilerInstance(llvm::LLVMContext *_LLVMContext = 0, + bool _OwnsLLVMContext = true); + ~CompilerInstance(); + + /// @name LLVM Context + /// { + + bool hasLLVMContext() const { return LLVMContext != 0; } + + llvm::LLVMContext &getLLVMContext() const { + assert(LLVMContext && "Compiler instance has no LLVM context!"); + return *LLVMContext; + } + + /// setLLVMContext - Replace the current LLVM context and take ownership of + /// \arg Value. + void setLLVMContext(llvm::LLVMContext *Value, bool TakeOwnership = true) { + LLVMContext = Value; + OwnsLLVMContext = TakeOwnership; + } + + /// } + /// @name Compiler Invocation and Options + /// { + + CompilerInvocation &getInvocation() { return Invocation; } + const CompilerInvocation &getInvocation() const { return Invocation; } + void setInvocation(const CompilerInvocation &Value) { Invocation = Value; } + + /// } + /// @name Forwarding Methods + /// { + + AnalyzerOptions &getAnalyzerOpts() { + return Invocation.getAnalyzerOpts(); + } + const AnalyzerOptions &getAnalyzerOpts() const { + return Invocation.getAnalyzerOpts(); + } + + CodeGenOptions &getCodeGenOpts() { + return Invocation.getCodeGenOpts(); + } + const CodeGenOptions &getCodeGenOpts() const { + return Invocation.getCodeGenOpts(); + } + + DependencyOutputOptions &getDependencyOutputOpts() { + return Invocation.getDependencyOutputOpts(); + } + const DependencyOutputOptions &getDependencyOutputOpts() const { + return Invocation.getDependencyOutputOpts(); + } + + DiagnosticOptions &getDiagnosticOpts() { + return Invocation.getDiagnosticOpts(); + } + const DiagnosticOptions &getDiagnosticOpts() const { + return Invocation.getDiagnosticOpts(); + } + + FrontendOptions &getFrontendOpts() { + return Invocation.getFrontendOpts(); + } + const FrontendOptions &getFrontendOpts() const { + return Invocation.getFrontendOpts(); + } + + HeaderSearchOptions &getHeaderSearchOpts() { + return Invocation.getHeaderSearchOpts(); + } + const HeaderSearchOptions &getHeaderSearchOpts() const { + return Invocation.getHeaderSearchOpts(); + } + + LangOptions &getLangOpts() { + return Invocation.getLangOpts(); + } + const LangOptions &getLangOpts() const { + return Invocation.getLangOpts(); + } + + PreprocessorOptions &getPreprocessorOpts() { + return Invocation.getPreprocessorOpts(); + } + const PreprocessorOptions &getPreprocessorOpts() const { + return Invocation.getPreprocessorOpts(); + } + + PreprocessorOutputOptions &getPreprocessorOutputOpts() { + return Invocation.getPreprocessorOutputOpts(); + } + const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { + return Invocation.getPreprocessorOutputOpts(); + } + + TargetOptions &getTargetOpts() { + return Invocation.getTargetOpts(); + } + const TargetOptions &getTargetOpts() const { + return Invocation.getTargetOpts(); + } + + /// } + /// @name Diagnostics Engine + /// { + + bool hasDiagnostics() const { return Diagnostics != 0; } + + Diagnostic &getDiagnostics() const { + assert(Diagnostics && "Compiler instance has no diagnostics!"); + return *Diagnostics; + } + + /// takeDiagnostics - Remove the current diagnostics engine and give ownership + /// to the caller. + Diagnostic *takeDiagnostics() { return Diagnostics.take(); } + + /// setDiagnostics - Replace the current diagnostics engine; the compiler + /// instance takes ownership of \arg Value. + void setDiagnostics(Diagnostic *Value); + + DiagnosticClient &getDiagnosticClient() const { + assert(Target && "Compiler instance has no diagnostic client!"); + return *DiagClient; + } + + /// takeDiagnosticClient - Remove the current diagnostics client and give + /// ownership to the caller. + DiagnosticClient *takeDiagnosticClient() { return DiagClient.take(); } + + /// setDiagnosticClient - Replace the current diagnostics client; the compiler + /// instance takes ownership of \arg Value. + void setDiagnosticClient(DiagnosticClient *Value); + + /// } + /// @name Target Info + /// { + + bool hasTarget() const { return Target != 0; } + + TargetInfo &getTarget() const { + assert(Target && "Compiler instance has no target!"); + return *Target; + } + + /// takeTarget - Remove the current diagnostics engine and give ownership + /// to the caller. + TargetInfo *takeTarget() { return Target.take(); } + + /// setTarget - Replace the current diagnostics engine; the compiler + /// instance takes ownership of \arg Value. + void setTarget(TargetInfo *Value); + + /// } + /// @name File Manager + /// { + + bool hasFileManager() const { return FileMgr != 0; } + + FileManager &getFileManager() const { + assert(FileMgr && "Compiler instance has no file manager!"); + return *FileMgr; + } + + /// takeFileManager - Remove the current file manager and give ownership to + /// the caller. + FileManager *takeFileManager() { return FileMgr.take(); } + + /// setFileManager - Replace the current file manager; the compiler instance + /// takes ownership of \arg Value. + void setFileManager(FileManager *Value); + + /// } + /// @name Source Manager + /// { + + bool hasSourceManager() const { return SourceMgr != 0; } + + SourceManager &getSourceManager() const { + assert(SourceMgr && "Compiler instance has no source manager!"); + return *SourceMgr; + } + + /// takeSourceManager - Remove the current source manager and give ownership + /// to the caller. + SourceManager *takeSourceManager() { return SourceMgr.take(); } + + /// setSourceManager - Replace the current source manager; the compiler + /// instance takes ownership of \arg Value. + void setSourceManager(SourceManager *Value); + + /// } + /// @name Preprocessor + /// { + + bool hasPreprocessor() const { return PP != 0; } + + Preprocessor &getPreprocessor() const { + assert(PP && "Compiler instance has no preprocessor!"); + return *PP; + } + + /// takePreprocessor - Remove the current preprocessor and give ownership to + /// the caller. + Preprocessor *takePreprocessor() { return PP.take(); } + + /// setPreprocessor - Replace the current preprocessor; the compiler instance + /// takes ownership of \arg Value. + void setPreprocessor(Preprocessor *Value); + + /// } + /// @name ASTContext + /// { + + bool hasASTContext() const { return Context != 0; } + + ASTContext &getASTContext() const { + assert(Context && "Compiler instance has no AST context!"); + return *Context; + } + + /// takeASTContext - Remove the current AST context and give ownership to the + /// caller. + ASTContext *takeASTContext() { return Context.take(); } + + /// setASTContext - Replace the current AST context; the compiler instance + /// takes ownership of \arg Value. + void setASTContext(ASTContext *Value); + + /// } + /// @name ASTConsumer + /// { + + bool hasASTConsumer() const { return Consumer != 0; } + + ASTConsumer &getASTConsumer() const { + assert(Consumer && "Compiler instance has no AST consumer!"); + return *Consumer; + } + + /// takeASTConsumer - Remove the current AST consumer and give ownership to + /// the caller. + ASTConsumer *takeASTConsumer() { return Consumer.take(); } + + /// setASTConsumer - Replace the current AST consumer; the compiler instance + /// takes ownership of \arg Value. + void setASTConsumer(ASTConsumer *Value); + + /// } + /// @name Code Completion + /// { + + bool hasCodeCompletionConsumer() const { return CompletionConsumer != 0; } + + CodeCompleteConsumer &getCodeCompletionConsumer() const { + assert(CompletionConsumer && + "Compiler instance has no code completion consumer!"); + return *CompletionConsumer; + } + + /// takeCodeCompletionConsumer - Remove the current code completion consumer + /// and give ownership to the caller. + CodeCompleteConsumer *takeCodeCompletionConsumer() { + return CompletionConsumer.take(); + } + + /// setCodeCompletionConsumer - Replace the current code completion consumer; + /// the compiler instance takes ownership of \arg Value. + void setCodeCompletionConsumer(CodeCompleteConsumer *Value); + + /// } + /// @name Output Files + /// { + + /// getOutputFileList - Get the list of (path, output stream) pairs of output + /// files; the path may be empty but the stream will always be non-null. + const std::list< std::pair<std::string, + llvm::raw_ostream*> > &getOutputFileList() const; + + /// addOutputFile - Add an output file onto the list of tracked output files. + /// + /// \param Path - The path to the output file, or empty. + /// \param OS - The output stream, which should be non-null. + void addOutputFile(llvm::StringRef Path, llvm::raw_ostream *OS); + + /// ClearOutputFiles - Clear the output file list, destroying the contained + /// output streams. + /// + /// \param EraseFiles - If true, attempt to erase the files from disk. + void ClearOutputFiles(bool EraseFiles); + + /// } + /// @name Construction Utility Methods + /// { + + /// Create the diagnostics engine using the invocation's diagnostic options + /// and replace any existing one with it. + /// + /// Note that this routine also replaces the diagnostic client. + void createDiagnostics(int Argc, char **Argv); + + /// Create a Diagnostic object with a the TextDiagnosticPrinter. + /// + /// The \arg Argc and \arg Argv arguments are used only for logging purposes, + /// when the diagnostic options indicate that the compiler should output + /// logging information. + /// + /// Note that this creates an unowned DiagnosticClient, if using directly the + /// caller is responsible for releaseing the returned Diagnostic's client + /// eventually. + /// + /// \return The new object on success, or null on failure. + static Diagnostic *createDiagnostics(const DiagnosticOptions &Opts, + int Argc, char **Argv); + + /// Create the file manager and replace any existing one with it. + void createFileManager(); + + /// Create the source manager and replace any existing one with it. + void createSourceManager(); + + /// Create the preprocessor, using the invocation, file, and source managers, + /// and replace any existing one with it. + void createPreprocessor(); + + /// Create a Preprocessor object. + /// + /// Note that this also creates a new HeaderSearch object which will be owned + /// by the resulting Preprocessor. + /// + /// \return The new object on success, or null on failure. + static Preprocessor *createPreprocessor(Diagnostic &, const LangOptions &, + const PreprocessorOptions &, + const HeaderSearchOptions &, + const DependencyOutputOptions &, + const TargetInfo &, + SourceManager &, FileManager &); + + /// Create the AST context. + void createASTContext(); + + /// Create an external AST source to read a PCH file and attach it to the AST + /// context. + void createPCHExternalASTSource(llvm::StringRef Path); + + /// Create an external AST source to read a PCH file. + /// + /// \return - The new object on success, or null on failure. + static ExternalASTSource * + createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot, + Preprocessor &PP, ASTContext &Context); + + /// Create a code completion consumer using the invocation; note that this + /// will cause the source manager to truncate the input source file at the + /// completion point. + void createCodeCompletionConsumer(); + + /// Create a code completion consumer to print code completion results, at + /// \arg Filename, \arg Line, and \arg Column, to the given output stream \arg + /// OS. + static CodeCompleteConsumer * + createCodeCompletionConsumer(Preprocessor &PP, const std::string &Filename, + unsigned Line, unsigned Column, + bool UseDebugPrinter, bool ShowMacros, + llvm::raw_ostream &OS); + + /// Create the default output file (from the invocation's options) and add it + /// to the list of tracked output files. + llvm::raw_fd_ostream * + createDefaultOutputFile(bool Binary = true, llvm::StringRef BaseInput = "", + llvm::StringRef Extension = ""); + + /// Create a new output file and add it to the list of tracked output files, + /// optionally deriving the output path name. + llvm::raw_fd_ostream * + createOutputFile(llvm::StringRef OutputPath, bool Binary = true, + llvm::StringRef BaseInput = "", + llvm::StringRef Extension = ""); + + /// Create a new output file, optionally deriving the output path name. + /// + /// If \arg OutputPath is empty, then createOutputFile will derive an output + /// path location as \arg BaseInput, with any suffix removed, and \arg + /// Extension appended. + /// + /// \param OutputPath - If given, the path to the output file. + /// \param Error [out] - On failure, the error message. + /// \param BaseInput - If \arg OutputPath is empty, the input path name to use + /// for deriving the output path. + /// \param Extension - The extension to use for derived output names. + /// \param Binary - The mode to open the file in. + /// \param ResultPathName [out] - If given, the result path name will be + /// stored here on success. + static llvm::raw_fd_ostream * + createOutputFile(llvm::StringRef OutputPath, std::string &Error, + bool Binary = true, llvm::StringRef BaseInput = "", + llvm::StringRef Extension = "", + std::string *ResultPathName = 0); + + /// } + /// @name Initialization Utility Methods + /// { + + /// InitializeSourceManager - Initialize the source manager to set InputFile + /// as the main file. + /// + /// \return True on success. + bool InitializeSourceManager(llvm::StringRef InputFile); + + /// InitializeSourceManager - Initialize the source manager to set InputFile + /// as the main file. + /// + /// \return True on success. + static bool InitializeSourceManager(llvm::StringRef InputFile, + Diagnostic &Diags, + FileManager &FileMgr, + SourceManager &SourceMgr, + const FrontendOptions &Opts); + + /// } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h new file mode 100644 index 000000000000..9d068c523c69 --- /dev/null +++ b/include/clang/Frontend/CompilerInvocation.h @@ -0,0 +1,150 @@ +//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_ +#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_ + +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/TargetOptions.h" +#include "clang/CodeGen/CodeGenOptions.h" +#include "clang/Frontend/AnalysisConsumer.h" +#include "clang/Frontend/DependencyOutputOptions.h" +#include "clang/Frontend/DiagnosticOptions.h" +#include "clang/Frontend/FrontendOptions.h" +#include "clang/Frontend/HeaderSearchOptions.h" +#include "clang/Frontend/PreprocessorOptions.h" +#include "clang/Frontend/PreprocessorOutputOptions.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringMap.h" +#include <string> +#include <vector> + +namespace llvm { + template<typename T> class SmallVectorImpl; +} + +namespace clang { + +/// CompilerInvocation - Helper class for holding the data necessary to invoke +/// the compiler. +/// +/// This class is designed to represent an abstract "invocation" of the +/// compiler, including data such as the include paths, the code generation +/// options, the warning flags, and so on. +class CompilerInvocation { + /// Options controlling the static analyzer. + AnalyzerOptions AnalyzerOpts; + + /// Options controlling IRgen and the backend. + CodeGenOptions CodeGenOpts; + + /// Options controlling dependency output. + DependencyOutputOptions DependencyOutputOpts; + + /// Options controlling the diagnostic engine. + DiagnosticOptions DiagnosticOpts; + + /// Options controlling the frontend itself. + FrontendOptions FrontendOpts; + + /// Options controlling the #include directive. + HeaderSearchOptions HeaderSearchOpts; + + /// Options controlling the language variant. + LangOptions LangOpts; + + /// Options controlling the preprocessor (aside from #include handling). + PreprocessorOptions PreprocessorOpts; + + /// Options controlling preprocessed output. + PreprocessorOutputOptions PreprocessorOutputOpts; + + /// Options controlling the target. + TargetOptions TargetOpts; + +public: + CompilerInvocation() {} + + /// @name Utility Methods + /// @{ + + /// CreateFromArgs - Create a compiler invocation from a list of input + /// options. + /// + /// FIXME: Documenting error behavior. + /// + /// \param Res [out] - The resulting invocation. + /// \param Args - The input argument strings. + static void CreateFromArgs(CompilerInvocation &Res, + const llvm::SmallVectorImpl<llvm::StringRef> &Args); + + /// toArgs - Convert the CompilerInvocation to a list of strings suitable for + /// passing to CreateFromArgs. + void toArgs(std::vector<std::string> &Res); + + /// @} + /// @name Option Subgroups + /// @{ + + AnalyzerOptions &getAnalyzerOpts() { return AnalyzerOpts; } + const AnalyzerOptions &getAnalyzerOpts() const { + return AnalyzerOpts; + } + + CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; } + const CodeGenOptions &getCodeGenOpts() const { + return CodeGenOpts; + } + + DependencyOutputOptions &getDependencyOutputOpts() { + return DependencyOutputOpts; + } + const DependencyOutputOptions &getDependencyOutputOpts() const { + return DependencyOutputOpts; + } + + DiagnosticOptions &getDiagnosticOpts() { return DiagnosticOpts; } + const DiagnosticOptions &getDiagnosticOpts() const { return DiagnosticOpts; } + + HeaderSearchOptions &getHeaderSearchOpts() { return HeaderSearchOpts; } + const HeaderSearchOptions &getHeaderSearchOpts() const { + return HeaderSearchOpts; + } + + FrontendOptions &getFrontendOpts() { return FrontendOpts; } + const FrontendOptions &getFrontendOpts() const { + return FrontendOpts; + } + + LangOptions &getLangOpts() { return LangOpts; } + const LangOptions &getLangOpts() const { return LangOpts; } + + PreprocessorOptions &getPreprocessorOpts() { return PreprocessorOpts; } + const PreprocessorOptions &getPreprocessorOpts() const { + return PreprocessorOpts; + } + + PreprocessorOutputOptions &getPreprocessorOutputOpts() { + return PreprocessorOutputOpts; + } + const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { + return PreprocessorOutputOpts; + } + + TargetOptions &getTargetOpts() { return TargetOpts; } + const TargetOptions &getTargetOpts() const { + return TargetOpts; + } + + /// @} +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h new file mode 100644 index 000000000000..ab8e49df9a88 --- /dev/null +++ b/include/clang/Frontend/DependencyOutputOptions.h @@ -0,0 +1,43 @@ +//===--- DependencyOutputOptions.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H +#define LLVM_CLANG_FRONTEND_DEPENDENCYOUTPUTOPTIONS_H + +#include <string> +#include <vector> + +namespace clang { + +/// DependencyOutputOptions - Options for controlling the compiler dependency +/// file generation. +class DependencyOutputOptions { +public: + unsigned IncludeSystemHeaders : 1; ///< Include system header dependencies. + unsigned UsePhonyTargets : 1; ///< Include phony targets for each + /// dependency, which can avoid some 'make' + /// problems. + + /// The file to write depencency output to. + std::string OutputFile; + + /// A list of names to use as the targets in the dependency file; this list + /// must contain at least one entry. + std::vector<std::string> Targets; + +public: + DependencyOutputOptions() { + IncludeSystemHeaders = 0; + UsePhonyTargets = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index 58673e4dad6b..6346dc0bfdec 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -19,6 +19,10 @@ namespace clang { /// engine. class DiagnosticOptions { public: + unsigned IgnoreWarnings : 1; /// -w + unsigned NoRewriteMacros : 1; /// -Wno-rewrite-macros + unsigned Pedantic : 1; /// -pedantic + unsigned PedanticErrors : 1; /// -pedantic-errors unsigned ShowColumn : 1; /// Show column number on diagnostics. unsigned ShowLocation : 1; /// Show source location information. unsigned ShowCarets : 1; /// Show carets in diagnostics. @@ -27,20 +31,36 @@ public: unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable /// diagnostics. unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. + unsigned VerifyDiagnostics; /// Check that diagnostics match the expected + /// diagnostics, indicated by markers in the + /// input source file. /// Column limit for formatting message diagnostics, or 0 if unused. unsigned MessageLength; + /// If non-empty, a file to log extended build information to, for development + /// testing and analysis. + std::string DumpBuildInformation; + + /// The list of -W... options used to alter the diagnostic mappings, with the + /// prefixes removed. + std::vector<std::string> Warnings; + public: DiagnosticOptions() { - ShowColumn = 1; - ShowLocation = 1; + IgnoreWarnings = 0; + MessageLength = 0; + NoRewriteMacros = 0; + Pedantic = 0; + PedanticErrors = 0; ShowCarets = 1; + ShowColors = 0; + ShowColumn = 1; ShowFixits = 1; - ShowSourceRanges = 0; + ShowLocation = 1; ShowOptionNames = 0; - ShowColors = 0; - MessageLength = 0; + ShowSourceRanges = 0; + VerifyDiagnostics = 0; } }; diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h new file mode 100644 index 000000000000..469ea535f6aa --- /dev/null +++ b/include/clang/Frontend/FrontendAction.h @@ -0,0 +1,215 @@ +//===-- FrontendAction.h - Generic Frontend Action Interface ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H +#define LLVM_CLANG_FRONTEND_FRONTENDACTION_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/OwningPtr.h" +#include <string> + +namespace llvm { +class Timer; +} + +namespace clang { +class ASTUnit; +class ASTConsumer; +class CompilerInstance; + +/// FrontendAction - Abstract base class for actions which can be performed by +/// the frontend. +class FrontendAction { + std::string CurrentFile; + llvm::OwningPtr<ASTUnit> CurrentASTUnit; + CompilerInstance *Instance; + llvm::Timer *CurrentTimer; + +protected: + /// @name Implementation Action Interface + /// @{ + + /// CreateASTConsumer - Create the AST consumer object for this action, if + /// supported. + /// + /// This routine is called as part of \see BeginSourceAction(), which will + /// fail if the AST consumer cannot be created. This will not be called if the + /// action has indicated that it only uses the preprocessor. + /// + /// \param CI - The current compiler instance, provided as a convenience, \see + /// getCompilerInstance(). + /// + /// \param InFile - The current input file, provided as a convenience, \see + /// getCurrentFile(). + /// + /// \return The new AST consumer, or 0 on failure. + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) = 0; + + /// BeginSourceFileAction - Callback at the start of processing a single + /// input. + /// + /// \return True on success; on failure \see ExecutionAction() and + /// EndSourceFileAction() will not be called. + virtual bool BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename) { + return true; + } + + /// ExecuteAction - Callback to run the program action, using the initialized + /// compiler instance. + /// + /// This routine is guaranteed to only be called between \see + /// BeginSourceFileAction() and \see EndSourceFileAction(). + virtual void ExecuteAction() = 0; + + /// EndSourceFileAction - Callback at the end of processing a single input; + /// this is guaranteed to only be called following a successful call to + /// BeginSourceFileAction (and BeingSourceFile). + virtual void EndSourceFileAction() {} + + /// @} + +public: + FrontendAction(); + virtual ~FrontendAction(); + + /// @name Compiler Instance Access + /// @{ + + CompilerInstance &getCompilerInstance() const { + assert(Instance && "Compiler instance not registered!"); + return *Instance; + } + + void setCompilerInstance(CompilerInstance *Value) { Instance = Value; } + + /// @} + /// @name Current File Information + /// @{ + + bool isCurrentFileAST() const { + assert(!CurrentFile.empty() && "No current file!"); + return CurrentASTUnit != 0; + } + + const std::string &getCurrentFile() const { + assert(!CurrentFile.empty() && "No current file!"); + return CurrentFile; + } + + ASTUnit &getCurrentASTUnit() const { + assert(!CurrentASTUnit && "No current AST unit!"); + return *CurrentASTUnit; + } + + void setCurrentFile(llvm::StringRef Value, ASTUnit *AST = 0); + + /// @} + /// @name Timing Utilities + /// @{ + + llvm::Timer *getCurrentTimer() const { + return CurrentTimer; + } + + void setCurrentTimer(llvm::Timer *Value) { + CurrentTimer = Value; + } + + /// @} + /// @name Supported Modes + /// @{ + + /// usesPreprocessorOnly - Does this action only use the preprocessor? If so + /// no AST context will be created and this action will be invalid with PCH + /// inputs. + virtual bool usesPreprocessorOnly() const = 0; + + /// usesCompleteTranslationUnit - For AST based actions, should the + /// translation unit be completed? + virtual bool usesCompleteTranslationUnit() { return true; } + + /// hasPCHSupport - Does this action support use with PCH? + virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); } + + /// hasASTSupport - Does this action support use with AST files? + virtual bool hasASTSupport() const { return !usesPreprocessorOnly(); } + + /// hasCodeCompletionSupport - Does this action support use with code + /// completion? + virtual bool hasCodeCompletionSupport() const { return false; } + + /// @} + /// @name Public Action Interface + /// @{ + + /// BeginSourceFile - Prepare the action for processing the input file \arg + /// Filename; this is run after the options and frontend have been + /// initialized, but prior to executing any per-file processing. + /// + /// \param CI - The compiler instance this action is being run from. The + /// action may store and use this object up until the matching EndSourceFile + /// action. + /// + /// \param Filename - The input filename, which will be made available to + /// clients via \see getCurrentFile(). + /// + /// \param IsAST - Indicates whether this is an AST input. AST inputs require + /// special handling, since the AST file itself contains several objects which + /// would normally be owned by the CompilerInstance. When processing AST input + /// files, these objects should generally not be initialized in the + /// CompilerInstance -- they will automatically be shared with the AST file in + /// between \see BeginSourceFile() and \see EndSourceFile(). + /// + /// \return True on success; the compilation of this file should be aborted + /// and neither Execute nor EndSourceFile should be called. + bool BeginSourceFile(CompilerInstance &CI, llvm::StringRef Filename, + bool IsAST = false); + + /// Execute - Set the source managers main input file, and run the action. + void Execute(); + + /// EndSourceFile - Perform any per-file post processing, deallocate per-file + /// objects, and run statistics and output file cleanup code. + void EndSourceFile(); + + /// @} +}; + +/// ASTFrontendAction - Abstract base class to use for AST consumer based +/// frontend actios. +class ASTFrontendAction : public FrontendAction { + /// ExecuteAction - Implement the ExecuteAction interface by running Sema on + /// the already initialized AST consumer. + /// + /// This will also take care of instantiating a code completion consumer if + /// the user requested it and the action supports it. + virtual void ExecuteAction(); + +public: + virtual bool usesPreprocessorOnly() const { return false; } +}; + +/// PreprocessorFrontendAction - Abstract base class to use for preprocessor +/// based frontend actions. +class PreprocessorFrontendAction : public FrontendAction { +protected: + /// CreateASTConsumer - Provide a default implementation which returns aborts, + /// this method should never be called by FrontendAction clients. + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + +public: + virtual bool usesPreprocessorOnly() const { return true; } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h new file mode 100644 index 000000000000..e755fe1b1b5f --- /dev/null +++ b/include/clang/Frontend/FrontendActions.h @@ -0,0 +1,216 @@ +//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H +#define LLVM_CLANG_FRONTEND_FRONTENDACTIONS_H + +#include "clang/Frontend/FrontendAction.h" + +namespace clang { +class FixItRewriter; + +//===----------------------------------------------------------------------===// +// AST Consumer Actions +//===----------------------------------------------------------------------===// + +class AnalysisAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class ASTPrintAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class ASTPrintXMLAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class ASTDumpAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class ASTViewAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class DeclContextPrintAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class DumpRecordAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class FixItAction : public ASTFrontendAction { +private: + llvm::OwningPtr<FixItRewriter> Rewriter; + +protected: + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual bool BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename); + + virtual void EndSourceFileAction(); + + virtual bool hasASTSupport() const { return false; } + +public: + FixItAction(); + ~FixItAction(); +}; + +class GeneratePCHAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual bool usesCompleteTranslationUnit() { return false; } + + virtual bool hasASTSupport() const { return false; } +}; + +class HTMLPrintAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class InheritanceViewAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class RewriteObjCAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class RewriteBlocksAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class SyntaxOnlyAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + +public: + virtual bool hasCodeCompletionSupport() const { return true; } +}; + +//===----------------------------------------------------------------------===// +// Code Gen AST Actions +//===----------------------------------------------------------------------===// + +class CodeGenAction : public ASTFrontendAction { +private: + unsigned Act; + +protected: + CodeGenAction(unsigned _Act); + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class EmitAssemblyAction : public CodeGenAction { +public: + EmitAssemblyAction(); +}; + +class EmitBCAction : public CodeGenAction { +public: + EmitBCAction(); +}; + +class EmitLLVMAction : public CodeGenAction { +public: + EmitLLVMAction(); +}; + +class EmitLLVMOnlyAction : public CodeGenAction { +public: + EmitLLVMOnlyAction(); +}; + +//===----------------------------------------------------------------------===// +// Preprocessor Actions +//===----------------------------------------------------------------------===// + +class DumpRawTokensAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class DumpTokensAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class GeneratePTHAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class ParseOnlyAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class PreprocessOnlyAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class PrintParseAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class PrintPreprocessedAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); + + virtual bool hasPCHSupport() const { return true; } +}; + +class RewriteMacrosAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class RewriteTestAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h new file mode 100644 index 000000000000..197a2a05e5e0 --- /dev/null +++ b/include/clang/Frontend/FrontendOptions.h @@ -0,0 +1,131 @@ +//===--- FrontendOptions.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H +#define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H + +#include "clang/Frontend/CommandLineSourceLoc.h" +#include "llvm/ADT/StringRef.h" +#include <string> +#include <vector> + +namespace clang { + +namespace frontend { + enum ActionKind { + ASTDump, ///< Parse ASTs and dump them. + ASTPrint, ///< Parse ASTs and print them. + ASTPrintXML, ///< Parse ASTs and print them in XML. + ASTView, ///< Parse ASTs and view them in Graphviz. + DumpRawTokens, ///< Dump out raw tokens. + DumpRecordLayouts, ///< Dump record layout information. + DumpTokens, ///< Dump out preprocessed tokens. + EmitAssembly, ///< Emit a .s file. + EmitBC, ///< Emit a .bc file. + EmitHTML, ///< Translate input source into HTML. + EmitLLVM, ///< Emit a .ll file. + EmitLLVMOnly, ///< Generate LLVM IR, but do not + FixIt, ///< Parse and apply any fixits to the source. + GeneratePCH, ///< Generate pre-compiled header. + GeneratePTH, ///< Generate pre-tokenized header. + InheritanceView, ///< View C++ inheritance for a specified class. + ParseNoop, ///< Parse with noop callbacks. + ParsePrintCallbacks, ///< Parse and print each callback. + ParseSyntaxOnly, ///< Parse and perform semantic analysis. + PluginAction, ///< Run a plugin action, \see ActionName. + PrintDeclContext, ///< Print DeclContext and their Decls. + PrintPreprocessedInput, ///< -E mode. + RewriteBlocks, ///< ObjC->C Rewriter for Blocks. + RewriteMacros, ///< Expand macros but not #includes. + RewriteObjC, ///< ObjC->C Rewriter. + RewriteTest, ///< Rewriter playground + RunAnalysis, ///< Run one or more source code analyses. + RunPreprocessorOnly ///< Just lex, no output. + }; +} + +/// FrontendOptions - Options for controlling the behavior of the frontend. +class FrontendOptions { +public: + enum InputKind { + IK_None, + IK_Asm, + IK_C, + IK_CXX, + IK_ObjC, + IK_ObjCXX, + IK_PreprocessedC, + IK_PreprocessedCXX, + IK_PreprocessedObjC, + IK_PreprocessedObjCXX, + IK_OpenCL, + IK_AST + }; + + unsigned DebugCodeCompletionPrinter : 1; ///< Use the debug printer for code + /// completion results. + unsigned DisableFree : 1; ///< Disable memory freeing on exit. + unsigned EmptyInputOnly : 1; ///< Force input files to be treated + /// as if they were empty, for timing + /// the frontend startup. + unsigned RelocatablePCH : 1; ///< When generating PCH files, + /// instruct the PCH writer to create + /// relocatable PCH files. + unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion + /// results. + unsigned ShowStats : 1; ///< Show frontend performance + /// metrics and statistics. + unsigned ShowTimers : 1; ///< Show timers for individual + /// actions. + + /// The input files and their types. + std::vector<std::pair<InputKind, std::string> > Inputs; + + /// The output file, if any. + std::string OutputFile; + + /// If given, the name for a C++ class to view the inheritance of. + std::string ViewClassInheritance; + + /// A list of locations to apply fix-its at. + std::vector<ParsedSourceLocation> FixItLocations; + + /// If given, enable code completion at the provided location. + ParsedSourceLocation CodeCompletionAt; + + /// The frontend action to perform. + frontend::ActionKind ProgramAction; + + /// The name of the action to run when using a plugin action. + std::string ActionName; + +public: + FrontendOptions() { + DebugCodeCompletionPrinter = 0; + DisableFree = 0; + EmptyInputOnly = 0; + ProgramAction = frontend::ParseSyntaxOnly; + ActionName = ""; + RelocatablePCH = 0; + ShowMacrosInCodeCompletion = 0; + ShowStats = 0; + ShowTimers = 0; + } + + /// getInputKindForExtension - Return the appropriate input kind for a file + /// extension. For example, "c" would return IK_C. + /// + /// \return The input kind for the extension, or IK_None if the extension is + /// not recognized. + static InputKind getInputKindForExtension(llvm::StringRef Extension); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h new file mode 100644 index 000000000000..8341492cfd23 --- /dev/null +++ b/include/clang/Frontend/FrontendPluginRegistry.h @@ -0,0 +1,23 @@ +//===-- FrontendAction.h - Pluggable Frontend Action Interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H +#define LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H + +#include "clang/Frontend/FrontendAction.h" +#include "llvm/Support/Registry.h" + +namespace clang { + +/// The frontend plugin registry. +typedef llvm::Registry<FrontendAction> FrontendPluginRegistry; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h new file mode 100644 index 000000000000..2edc7e1f4ab4 --- /dev/null +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -0,0 +1,87 @@ +//===--- HeaderSearchOptions.h ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H +#define LLVM_CLANG_FRONTEND_HEADERSEARCHOPTIONS_H + +#include "llvm/ADT/StringRef.h" +#include <vector> + +namespace clang { + +namespace frontend { + /// IncludeDirGroup - Identifiers the group a include entry belongs to, which + /// represents its relative positive in the search list. + enum IncludeDirGroup { + Quoted = 0, ///< `#include ""` paths. Thing `gcc -iquote`. + Angled, ///< Paths for both `#include ""` and `#include <>`. (`-I`) + System, ///< Like Angled, but marks system directories. + After ///< Like System, but searched after the system directories. + }; +} + +/// HeaderSearchOptions - Helper class for storing options related to the +/// initialization of the HeaderSearch object. +class HeaderSearchOptions { +public: + struct Entry { + std::string Path; + frontend::IncludeDirGroup Group; + unsigned IsUserSupplied : 1; + unsigned IsFramework : 1; + + Entry(llvm::StringRef _Path, frontend::IncludeDirGroup _Group, + bool _IsUserSupplied, bool _IsFramework) + : Path(_Path), Group(_Group), IsUserSupplied(_IsUserSupplied), + IsFramework(_IsFramework) {} + }; + + /// If non-empty, the directory to use as a "virtual system root" for include + /// paths. + std::string Sysroot; + + /// User specified include entries. + std::vector<Entry> UserEntries; + + /// A (system-path) delimited list of include paths to be added from the + /// environment following the user specified includes (but prior to builtin + /// and standard includes). This is parsed in the same manner as the CPATH + /// environment variable for gcc. + std::string EnvIncPath; + + /// Per-language environmental include paths, see \see EnvIncPath. + std::string CEnvIncPath; + std::string ObjCEnvIncPath; + std::string CXXEnvIncPath; + std::string ObjCXXEnvIncPath; + + /// If non-empty, the path to the compiler builtin include directory, which + /// will be searched following the user and environment includes. + std::string BuiltinIncludePath; + + /// Include the system standard include search directories. + unsigned UseStandardIncludes : 1; + + /// Whether header search information should be output as for -v. + unsigned Verbose : 1; + +public: + HeaderSearchOptions(llvm::StringRef _Sysroot = "") + : Sysroot(_Sysroot), UseStandardIncludes(true) {} + + /// AddPath - Add the \arg Path path to the specified \arg Group list. + void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group, + bool IsUserSupplied, bool IsFramework) { + UserEntries.push_back(Entry(Path, Group, IsUserSupplied, IsFramework)); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index cc8b3a03e3e8..85861fab4a22 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -29,6 +29,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/System/DataTypes.h" #include <deque> @@ -78,7 +79,7 @@ public: /// \brief Receives the target triple. /// /// \returns true to indicate the target triple is invalid or false otherwise. - virtual bool ReadTargetTriple(const std::string &Triple) { + virtual bool ReadTargetTriple(llvm::StringRef Triple) { return false; } @@ -87,18 +88,18 @@ public: /// \param PCHPredef The start of the predefines buffer in the PCH /// file. /// - /// \param PCHPredefLen The length of the predefines buffer in the PCH - /// file. - /// /// \param PCHBufferID The FileID for the PCH predefines buffer. /// + /// \param OriginalFileName The original file name for the PCH, which will + /// appear as an entry in the predefines buffer. + /// /// \param SuggestedPredefines If necessary, additional definitions are added /// here. /// /// \returns true to indicate the predefines are invalid or false otherwise. - virtual bool ReadPredefinesBuffer(const char *PCHPredef, - unsigned PCHPredefLen, + virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID, + llvm::StringRef OriginalFileName, std::string &SuggestedPredefines) { return false; } @@ -123,10 +124,10 @@ public: : PP(PP), Reader(Reader), NumHeaderInfos(0) {} virtual bool ReadLanguageOptions(const LangOptions &LangOpts); - virtual bool ReadTargetTriple(const std::string &Triple); - virtual bool ReadPredefinesBuffer(const char *PCHPredef, - unsigned PCHPredefLen, + virtual bool ReadTargetTriple(llvm::StringRef Triple); + virtual bool ReadPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID, + llvm::StringRef OriginalFileName, std::string &SuggestedPredefines); virtual void ReadHeaderFileInfo(const HeaderFileInfo &HFI); virtual void ReadCounter(unsigned Value); @@ -312,10 +313,13 @@ private: /// the PCH file. llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls; - /// \brief The original file name that was used to build the PCH - /// file. + /// \brief The original file name that was used to build the PCH file, which + /// may have been modified for relocatable-pch support. std::string OriginalFileName; + /// \brief The actual original file name that was used to build the PCH file. + std::string ActualOriginalFileName; + /// \brief Whether this precompiled header is a relocatable PCH file. bool RelocatablePCH; @@ -444,9 +448,7 @@ private: void MaybeAddSystemRootToFilename(std::string &Filename); PCHReadResult ReadPCHBlock(); - bool CheckPredefinesBuffer(const char *PCHPredef, - unsigned PCHPredefLen, - FileID PCHBufferID); + bool CheckPredefinesBuffer(llvm::StringRef PCHPredef, FileID PCHBufferID); bool ParseLineTable(llvm::SmallVectorImpl<uint64_t> &Record); PCHReadResult ReadSourceManagerBlock(); PCHReadResult ReadSLocEntryRecord(unsigned ID); @@ -625,13 +627,15 @@ public: /// \brief Retrieve the IdentifierInfo for the named identifier. /// - /// This routine builds a new IdentifierInfo for the given - /// identifier. If any declarations with this name are visible from - /// translation unit scope, their declarations will be deserialized - /// and introduced into the declaration chain of the - /// identifier. FIXME: if this identifier names a macro, deserialize - /// the macro. + /// This routine builds a new IdentifierInfo for the given identifier. If any + /// declarations with this name are visible from translation unit scope, their + /// declarations will be deserialized and introduced into the declaration + /// chain of the identifier. FIXME: if this identifier names a macro, + /// deserialize the macro. virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd); + IdentifierInfo* get(llvm::StringRef Name) { + return get(Name.begin(), Name.end()); + } /// \brief Load the contents of the global method pool for a given /// selector. diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 22427eb67103..b520f4be1d31 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -52,7 +52,8 @@ struct UnsafeQualTypeDenseMapInfo { return QualType::getFromOpaquePtr((void*) 2); } static inline unsigned getHashValue(QualType T) { - assert(!T.getFastQualifiers() && "hash invalid for types with fast quals"); + assert(!T.getLocalFastQualifiers() && + "hash invalid for types with fast quals"); uintptr_t v = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); return (unsigned(v) >> 4) ^ (unsigned(v) >> 9); } diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h new file mode 100644 index 000000000000..f0c1d3c2c38d --- /dev/null +++ b/include/clang/Frontend/PreprocessorOptions.h @@ -0,0 +1,57 @@ +//===--- PreprocessorOptionms.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_ +#define LLVM_CLANG_FRONTEND_PREPROCESSOROPTIONS_H_ + +#include "llvm/ADT/StringRef.h" +#include <cassert> +#include <string> +#include <vector> + +namespace clang { + +class Preprocessor; +class LangOptions; + +/// PreprocessorOptions - This class is used for passing the various options +/// used in preprocessor initialization to InitializePreprocessor(). +class PreprocessorOptions { +public: + std::vector<std::pair<std::string, bool/*isUndef*/> > Macros; + std::vector<std::string> Includes; + std::vector<std::string> MacroIncludes; + + unsigned UsePredefines : 1; /// Initialize the preprocessor with the compiler + /// and target specific predefines. + + /// The implicit PCH included at the start of the translation unit, or empty. + std::string ImplicitPCHInclude; + + /// The implicit PTH input included at the start of the translation unit, or + /// empty. + std::string ImplicitPTHInclude; + + /// If given, a PTH cache file to use for speeding up header parsing. + std::string TokenCache; + +public: + PreprocessorOptions() : UsePredefines(true) {} + + void addMacroDef(llvm::StringRef Name) { + Macros.push_back(std::make_pair(Name, false)); + } + void addMacroUndef(llvm::StringRef Name) { + Macros.push_back(std::make_pair(Name, true)); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/PreprocessorOutputOptions.h b/include/clang/Frontend/PreprocessorOutputOptions.h new file mode 100644 index 000000000000..a712a3d1bb05 --- /dev/null +++ b/include/clang/Frontend/PreprocessorOutputOptions.h @@ -0,0 +1,37 @@ +//===--- PreprocessorOutputOptions.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H +#define LLVM_CLANG_FRONTEND_PREPROCESSOROUTPUTOPTIONS_H + +namespace clang { + +/// PreprocessorOutputOptions - Options for controlling the C preprocessor +/// output (e.g., -E). +class PreprocessorOutputOptions { +public: + unsigned ShowCPP : 1; ///< Print normal preprocessed output. + unsigned ShowMacros : 1; ///< Print macro definitions. + unsigned ShowLineMarkers : 1; ///< Show #line markers. + unsigned ShowComments : 1; ///< Show comments. + unsigned ShowMacroComments : 1; ///< Show comments, even in macros. + +public: + PreprocessorOutputOptions() { + ShowCPP = 1; + ShowMacros = 0; + ShowLineMarkers = 1; + ShowComments = 0; + ShowMacroComments = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index 3c5c6267c632..d727e4800727 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -34,12 +34,15 @@ class TextDiagnosticPrinter : public DiagnosticClient { SourceLocation LastWarningLoc; FullSourceLoc LastLoc; - bool LastCaretDiagnosticWasNote; + unsigned LastCaretDiagnosticWasNote : 1; + unsigned OwnsOutputStream : 1; public: - TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags); + TextDiagnosticPrinter(llvm::raw_ostream &os, const DiagnosticOptions &diags, + bool OwnsOutputStream = false); + virtual ~TextDiagnosticPrinter(); - void BeginSourceFile(const LangOptions &LO) { + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) { LangOpts = &LO; } diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def index 6aca15a75427..35f5debe5cf0 100644 --- a/include/clang/Frontend/TypeXML.def +++ b/include/clang/Frontend/TypeXML.def @@ -65,9 +65,9 @@ NODE_XML(QualType, "CvQualifiedType") ID_ATTRIBUTE_XML TYPE_ATTRIBUTE_XML(getTypePtr()) // the qualified type, e.g. for 'T* const' it's 'T*' - ATTRIBUTE_OPT_XML(isConstQualified(), "const") // boolean - ATTRIBUTE_OPT_XML(isVolatileQualified(), "volatile") // boolean - ATTRIBUTE_OPT_XML(isRestrictQualified(), "restrict") // boolean + ATTRIBUTE_OPT_XML(isLocalConstQualified(), "const") // boolean + ATTRIBUTE_OPT_XML(isLocalVolatileQualified(), "volatile") // boolean + ATTRIBUTE_OPT_XML(isLocalRestrictQualified(), "restrict") // boolean ATTRIBUTE_OPT_XML(getObjCGCAttr(), "objc_gc") // Qualifiers::GC ATTRIBUTE_OPT_XML(getAddressSpace(), "address_space") // unsigned END_NODE_XML diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 3c670286545b..27c14c917015 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -1,4 +1,4 @@ -//===--- Utils.h - Misc utilities for the front-end------------------------===// +//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,42 +14,57 @@ #ifndef LLVM_CLANG_FRONTEND_UTILS_H #define LLVM_CLANG_FRONTEND_UTILS_H +#include "llvm/ADT/StringRef.h" #include <vector> #include <string> namespace llvm { +class Triple; class raw_ostream; class raw_fd_ostream; } namespace clang { -class Preprocessor; -class MinimalAction; -class TargetInfo; -class Diagnostic; class ASTConsumer; +class Decl; +class DependencyOutputOptions; +class Diagnostic; +class DiagnosticOptions; +class HeaderSearch; +class HeaderSearchOptions; class IdentifierTable; -class SourceManager; class LangOptions; -class Decl; +class MinimalAction; +class Preprocessor; +class PreprocessorOptions; +class PreprocessorOutputOptions; +class SourceManager; class Stmt; +class TargetInfo; + +/// Normalize \arg File for use in a user defined #include directive (in the +/// predefines buffer). +std::string NormalizeDashIncludePath(llvm::StringRef File); + +/// Apply the header search options to get given HeaderSearch object. +void ApplyHeaderSearchOptions(HeaderSearch &HS, + const HeaderSearchOptions &HSOpts, + const LangOptions &Lang, + const llvm::Triple &triple); + +/// InitializePreprocessor - Initialize the preprocessor getting it and the +/// environment ready to process a single file. +void InitializePreprocessor(Preprocessor &PP, + const PreprocessorOptions &PPOpts, + const HeaderSearchOptions &HSOpts); /// ProcessWarningOptions - Initialize the diagnostic client and process the /// warning options specified on the command line. -bool ProcessWarningOptions(Diagnostic &Diags, - std::vector<std::string> &Warnings, - bool Pedantic, bool PedanticErrors, - bool NoWarnings); - -/// DoPrintPreprocessedInput - Implement -E -dM mode. -void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream* OS); +bool ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts); /// DoPrintPreprocessedInput - Implement -E mode. void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS, - bool EnableCommentOutput, - bool EnableMacroCommentOutput, - bool DisableLineMarkers, - bool DumpDefines); + const PreprocessorOutputOptions &Opts); /// RewriteMacrosInInput - Implement -rewrite-macros mode. void RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream* OS); @@ -67,13 +82,12 @@ bool CheckDiagnostics(Preprocessor &PP); /// AttachDependencyFileGen - Create a dependency file generator, and attach /// it to the given preprocessor. This takes ownership of the output stream. -void AttachDependencyFileGen(Preprocessor *PP, llvm::raw_ostream *OS, - std::vector<std::string> &Targets, - bool IncludeSystemHeaders, bool PhonyTarget); +void AttachDependencyFileGen(Preprocessor &PP, + const DependencyOutputOptions &Opts); /// CacheTokens - Cache tokens for use with PCH. Note that this requires /// a seekable stream. -void CacheTokens(Preprocessor& PP, llvm::raw_fd_ostream* OS); +void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS); } // end namespace clang diff --git a/include/clang/Frontend/VerifyDiagnosticsClient.h b/include/clang/Frontend/VerifyDiagnosticsClient.h new file mode 100644 index 000000000000..6f7ebbe537f9 --- /dev/null +++ b/include/clang/Frontend/VerifyDiagnosticsClient.h @@ -0,0 +1,82 @@ +//===-- VerifyDiagnosticsClient.h - Verifying Diagnostic Client -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H +#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H + +#include "clang/Basic/Diagnostic.h" +#include "llvm/ADT/OwningPtr.h" + +namespace clang { + +class Diagnostic; +class SourceMgr; +class TextDiagnosticBuffer; + +/// VerifyDiagnosticsClient - Create a diagnostic client which will use markers +/// in the input source to check that all the emitted diagnostics match those +/// expected. +/// +/// USING THE DIAGNOSTIC CHECKER: +/// +/// Indicating that a line expects an error or a warning is simple. Put a +/// comment on the line that has the diagnostic, use "expected-{error,warning}" +/// to tag if it's an expected error or warning, and place the expected text +/// between {{ and }} markers. The full text doesn't have to be included, only +/// enough to ensure that the correct diagnostic was emitted. +/// +/// Here's an example: +/// +/// int A = B; // expected-error {{use of undeclared identifier 'B'}} +/// +/// You can place as many diagnostics on one line as you wish. To make the code +/// more readable, you can use slash-newline to separate out the diagnostics. +/// +/// The simple syntax above allows each specification to match exactly one +/// error. You can use the extended syntax to customize this. The extended +/// syntax is "expected-<type> <n> {{diag text}}", where <type> is one of +/// "error", "warning" or "note", and <n> is a positive integer. This allows the +/// diagnostic to appear as many times as specified. Example: +/// +/// void f(); // expected-note 2 {{previous declaration is here}} +/// +class VerifyDiagnosticsClient : public DiagnosticClient { +public: + Diagnostic &Diags; + llvm::OwningPtr<DiagnosticClient> PrimaryClient; + llvm::OwningPtr<TextDiagnosticBuffer> Buffer; + Preprocessor *CurrentPreprocessor; + unsigned NumErrors; + +private: + void CheckDiagnostics(); + +public: + /// Create a new verifying diagnostic client, which will issue errors to \arg + /// PrimaryClient when a diagnostic does not match what is expected (as + /// indicated in the source file). The verifying diagnostic client takes + /// ownership of \arg PrimaryClient. + VerifyDiagnosticsClient(Diagnostic &Diags, DiagnosticClient *PrimaryClient); + ~VerifyDiagnosticsClient(); + + virtual void BeginSourceFile(const LangOptions &LangOpts, + const Preprocessor *PP); + + virtual void EndSourceFile(); + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); + + /// HadErrors - Check if there were any mismatches in expected diagnostics. + bool HadErrors(); +}; + +} // end namspace clang + +#endif diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index ff1a17259e8a..ac5594e55d7d 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -119,8 +119,7 @@ public: /// Create - This method creates PTHManager objects. The 'file' argument /// is the name of the PTH file. This method returns NULL upon failure. - static PTHManager *Create(const std::string& file, Diagnostic* Diags = 0, - Diagnostic::Level failureLevel=Diagnostic::Warning); + static PTHManager *Create(const std::string& file, Diagnostic &Diags); void setPreprocessor(Preprocessor *pp) { PP = pp; } diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 2783716b89ff..1c0036e3edcb 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -51,7 +51,7 @@ class DirectoryLookup; class Preprocessor { Diagnostic *Diags; LangOptions Features; - TargetInfo &Target; + const TargetInfo &Target; FileManager &FileMgr; SourceManager &SourceMgr; ScratchBuffer *ScratchBuf; @@ -94,6 +94,9 @@ class Preprocessor { bool DisableMacroExpansion : 1; // True if macro expansion is disabled. bool InMacroArgs : 1; // True if parsing fn macro invocation args. + /// Whether the preprocessor owns the header search object. + bool OwnsHeaderSearch : 1; + /// Identifiers - This is mapping/lookup information for all identifiers in /// the program, including program keywords. mutable IdentifierTable Identifiers; @@ -207,9 +210,11 @@ private: // Cached tokens state. std::vector<CachedTokensTy::size_type> BacktrackPositions; public: - Preprocessor(Diagnostic &diags, const LangOptions &opts, TargetInfo &target, + Preprocessor(Diagnostic &diags, const LangOptions &opts, + const TargetInfo &target, SourceManager &SM, HeaderSearch &Headers, - IdentifierInfoLookup *IILookup = 0); + IdentifierInfoLookup *IILookup = 0, + bool OwnsHeaderSearch = false); ~Preprocessor(); @@ -217,7 +222,7 @@ public: void setDiagnostics(Diagnostic &D) { Diags = &D; } const LangOptions &getLangOptions() const { return Features; } - TargetInfo &getTargetInfo() const { return Target; } + const TargetInfo &getTargetInfo() const { return Target; } FileManager &getFileManager() const { return FileMgr; } SourceManager &getSourceManager() const { return SourceMgr; } HeaderSearch &getHeaderSearchInfo() const { return HeaderInfo; } @@ -498,6 +503,15 @@ public: /// UCNs, etc. std::string getSpelling(const Token &Tok) const; + /// getSpelling() - Return the 'spelling' of the Tok token. The spelling of a + /// token is the characters used to represent the token in the source file + /// after trigraph expansion and escaped-newline folding. In particular, this + /// wants to get the true, uncanonicalized, spelling of things like digraphs + /// UCNs, etc. + static std::string getSpelling(const Token &Tok, + const SourceManager &SourceMgr, + const LangOptions &Features); + /// getSpelling - This method is used to get the spelling of a token into a /// preallocated buffer, instead of as an std::string. The caller is required /// to allocate enough space for the token, which is guaranteed to be at least diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 8d910959b9fa..604eae1027aa 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -248,69 +248,6 @@ struct PPConditionalInfo { bool FoundElse; }; -/// TemplateIdAnnotation - Information about a template-id annotation -/// token, which contains the template declaration, template -/// arguments, whether those template arguments were types or -/// expressions, and the source locations for important tokens. All of -/// the information about template arguments is allocated directly -/// after this structure. -struct TemplateIdAnnotation { - /// TemplateNameLoc - The location of the template name within the - /// source. - SourceLocation TemplateNameLoc; - - /// FIXME: Temporarily stores the name of a specialization - IdentifierInfo *Name; - - /// FIXME: Temporarily stores the overloaded operator kind. - OverloadedOperatorKind Operator; - - /// The declaration of the template corresponding to the - /// template-name. This is an Action::DeclTy*. - void *Template; - - /// The kind of template that Template refers to. - TemplateNameKind Kind; - - /// The location of the '<' before the template argument - /// list. - SourceLocation LAngleLoc; - - /// The location of the '>' after the template argument - /// list. - SourceLocation RAngleLoc; - - /// NumArgs - The number of template arguments. - unsigned NumArgs; - - /// \brief Retrieves a pointer to the template arguments - void **getTemplateArgs() { return (void **)(this + 1); } - - /// \brief Retrieves a pointer to the array of template argument - /// locations. - SourceLocation *getTemplateArgLocations() { - return (SourceLocation *)(getTemplateArgs() + NumArgs); - } - - /// \brief Retrieves a pointer to the array of flags that states - /// whether the template arguments are types. - bool *getTemplateArgIsType() { - return (bool *)(getTemplateArgLocations() + NumArgs); - } - - static TemplateIdAnnotation* Allocate(unsigned NumArgs) { - TemplateIdAnnotation *TemplateId - = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + - sizeof(void*) * NumArgs + - sizeof(SourceLocation) * NumArgs + - sizeof(bool) * NumArgs); - TemplateId->NumArgs = NumArgs; - return TemplateId; - } - - void Destroy() { free(this); } -}; - } // end namespace clang #endif diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 657a14fff082..a9b32133234a 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1203,6 +1203,8 @@ public: /// 'typename' keyword. FIXME: This will eventually be split into a /// separate action. /// + /// \param TypenameLoc the location of the 'typename' keyword, if present + /// /// \returns a representation of the using declaration. virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, @@ -1210,7 +1212,8 @@ public: const CXXScopeSpec &SS, UnqualifiedId &Name, AttributeList *AttrList, - bool IsTypeName); + bool IsTypeName, + SourceLocation TypenameLoc); /// ActOnParamDefaultArgument - Parse default argument for function parameter virtual void ActOnParamDefaultArgument(DeclPtrTy param, @@ -1577,7 +1580,7 @@ public: /// parameter. virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, SourceLocation EqualLoc, - ExprArg Default) { + const ParsedTemplateArgument &Default) { } /// ActOnTemplateParameterList - Called when a complete template @@ -1632,7 +1635,6 @@ public: SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc) { return TypeResult(); }; @@ -1737,7 +1739,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr, MultiTemplateParamsArg TemplateParameterLists) { @@ -1817,7 +1818,6 @@ public: SourceLocation TemplateNameLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, - SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc, AttributeList *Attr) { return DeclResult(); @@ -2105,6 +2105,7 @@ public: virtual DeclPtrTy ActOnForwardClassDeclaration( SourceLocation AtClassLoc, IdentifierInfo **IdentList, + SourceLocation *IdentLocs, unsigned NumElts) { return DeclPtrTy(); } @@ -2329,6 +2330,47 @@ public: /// /// \param S the scope in which the operator keyword occurs. virtual void CodeCompleteObjCProperty(Scope *S, ObjCDeclSpec &ODS) { } + + /// \brief Code completion for an ObjC message expression that refers to + /// a class method. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the class name. + /// + /// \param S the scope in which the message expression occurs. + /// \param FName the factory name. + /// \param FNameLoc the source location of the factory name. + virtual void CodeCompleteObjCClassMessage(Scope *S, IdentifierInfo *FName, + SourceLocation FNameLoc){ } + + /// \brief Code completion for an ObjC message expression that refers to + /// an instance method. + /// + /// This code completion action is invoked when the code-completion token is + /// found after the receiver expression. + /// + /// \param S the scope in which the operator keyword occurs. + /// \param Receiver an expression for the receiver of the message. + virtual void CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver) { } + + /// \brief Code completion for a list of protocol references in Objective-C, + /// such as P1 and P2 in \c id<P1,P2>. + /// + /// This code completion action is invoked prior to each identifier + /// in the protocol list. + /// + /// \param Protocols the set of protocols that have already been parsed. + /// + /// \param NumProtocols the number of protocols that have already been + /// parsed. + virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, + unsigned NumProtocols) { } + + /// \brief Code completion for a protocol declaration or definition, after + /// the @protocol but before any identifier. + /// + /// \param S the scope in which the protocol declaration occurs. + virtual void CodeCompleteObjCProtocolDecl(Scope *S) { } //@} }; @@ -2398,6 +2440,7 @@ public: virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc, IdentifierInfo **IdentList, + SourceLocation *SLocs, unsigned NumElts); virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc, diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 9fcc845cb006..81bb3007baea 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -57,6 +57,7 @@ public: AT_analyzer_noreturn, AT_annotate, AT_blocks, + AT_cdecl, AT_cleanup, AT_const, AT_constructor, diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index d539508e973b..7e7d0b3f28e8 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -25,7 +25,8 @@ namespace clang { class IdentifierInfo; class Preprocessor; class Declarator; - + struct TemplateIdAnnotation; + /// DeclSpec - This class captures information about "declaration specifiers", /// which encompasses storage-class-specifiers, type-specifiers, /// type-qualifiers, and function-specifiers. @@ -642,13 +643,7 @@ public: /// \param TemplateId the template-id annotation that describes the parsed /// template-id. This UnqualifiedId instance will take ownership of the /// \p TemplateId and will free it on destruction. - void setTemplateId(TemplateIdAnnotation *TemplateId) { - assert(TemplateId && "NULL template-id annotation?"); - Kind = IK_TemplateId; - this->TemplateId = TemplateId; - StartLocation = TemplateId->TemplateNameLoc; - EndLocation = TemplateId->RAngleLoc; - } + void setTemplateId(TemplateIdAnnotation *TemplateId); /// \brief Return the source range that covers this unqualified-id. SourceRange getSourceRange() const { diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h index 9bd69c5fdb68..5eb9635f06a1 100644 --- a/include/clang/Parse/Ownership.h +++ b/include/clang/Parse/Ownership.h @@ -654,41 +654,33 @@ namespace clang { #endif }; + class ParsedTemplateArgument; + class ASTTemplateArgsPtr { #if !defined(DISABLE_SMART_POINTERS) ActionBase &Actions; #endif - void **Args; - bool *ArgIsType; + ParsedTemplateArgument *Args; mutable unsigned Count; #if !defined(DISABLE_SMART_POINTERS) - void destroy() { - if (!Count) - return; - - for (unsigned i = 0; i != Count; ++i) - if (Args[i] && !ArgIsType[i]) - Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]); - - Count = 0; - } + void destroy(); #endif - + public: - ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType, + ASTTemplateArgsPtr(ActionBase &actions, ParsedTemplateArgument *args, unsigned count) : #if !defined(DISABLE_SMART_POINTERS) Actions(actions), #endif - Args(args), ArgIsType(argIsType), Count(count) { } + Args(args), Count(count) { } // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : #if !defined(DISABLE_SMART_POINTERS) Actions(Other.Actions), #endif - Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) { + Args(Other.Args), Count(Other.Count) { #if !defined(DISABLE_SMART_POINTERS) Other.Count = 0; #endif @@ -700,7 +692,6 @@ namespace clang { Actions = Other.Actions; #endif Args = Other.Args; - ArgIsType = Other.ArgIsType; Count = Other.Count; #if !defined(DISABLE_SMART_POINTERS) Other.Count = 0; @@ -712,22 +703,20 @@ namespace clang { ~ASTTemplateArgsPtr() { destroy(); } #endif - void **getArgs() const { return Args; } - bool *getArgIsType() const {return ArgIsType; } + ParsedTemplateArgument *getArgs() const { return Args; } unsigned size() const { return Count; } - void reset(void **args, bool *argIsType, unsigned count) { + void reset(ParsedTemplateArgument *args, unsigned count) { #if !defined(DISABLE_SMART_POINTERS) destroy(); #endif Args = args; - ArgIsType = argIsType; Count = count; } - void *operator[](unsigned Arg) const { return Args[Arg]; } + const ParsedTemplateArgument &operator[](unsigned Arg) const; - void **release() const { + ParsedTemplateArgument *release() const { #if !defined(DISABLE_SMART_POINTERS) Count = 0; #endif diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 1ca92edc9a8b..e7dabdbd5b66 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -114,7 +114,7 @@ public: ~Parser(); const LangOptions &getLang() const { return PP.getLangOptions(); } - TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); } + const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); } Preprocessor &getPreprocessor() const { return PP; } Action &getActions() const { return Actions; } @@ -179,6 +179,8 @@ public: /// the EOF was encountered. bool ParseTopLevelDecl(DeclGroupPtrTy &Result); + DeclGroupPtrTy RetrievePendingObjCImpDecl(); + private: //===--------------------------------------------------------------------===// // Low-Level token peeking and consumption methods. @@ -331,7 +333,7 @@ private: /// either "commit the consumed tokens" or revert to the previously marked /// token position. Example: /// - /// TentativeParsingAction TPA; + /// TentativeParsingAction TPA(*this); /// ConsumeToken(); /// .... /// TPA.Revert(); @@ -783,6 +785,7 @@ private: AttributeList *prefixAttrs = 0); DeclPtrTy ObjCImpDecl; + llvm::SmallVector<DeclPtrTy, 4> PendingObjCImpDecl; DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc); DeclPtrTy ParseObjCAtEndDeclaration(SourceLocation atLoc); @@ -1226,13 +1229,18 @@ private: Parser &P; CXXScopeSpec &SS; bool EnteredScope; + bool CreatedScope; public: DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss) - : P(p), SS(ss), EnteredScope(false) {} + : P(p), SS(ss), EnteredScope(false), CreatedScope(false) {} void EnterDeclaratorScope() { assert(!EnteredScope && "Already entered the scope!"); assert(SS.isSet() && "C++ scope was not set!"); + + CreatedScope = true; + P.EnterScope(0); // Not a decl scope. + if (P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS)) SS.setScopeRep(0); @@ -1245,6 +1253,8 @@ private: assert(SS.isSet() && "C++ scope was cleared ?"); P.Actions.ActOnCXXExitDeclaratorScope(P.CurScope, SS); } + if (CreatedScope) + P.ExitScope(); } }; @@ -1347,9 +1357,7 @@ private: DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position); // C++ 14.3: Template arguments [temp.arg] - typedef llvm::SmallVector<void *, 16> TemplateArgList; - typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList; - typedef llvm::SmallVector<SourceLocation, 16> TemplateArgLocationList; + typedef llvm::SmallVector<ParsedTemplateArgument, 16> TemplateArgList; bool ParseTemplateIdAfterTemplateName(TemplateTy Template, SourceLocation TemplateNameLoc, @@ -1357,8 +1365,6 @@ private: bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, - TemplateArgIsTypeList &TemplateArgIsType, - TemplateArgLocationList &TemplateArgLocations, SourceLocation &RAngleLoc); bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, @@ -1367,10 +1373,9 @@ private: SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); - bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs, - TemplateArgIsTypeList &TemplateArgIsType, - TemplateArgLocationList &TemplateArgLocations); - void *ParseTemplateArgument(bool &ArgIsType); + bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); + ParsedTemplateArgument ParseTemplateTemplateArgument(); + ParsedTemplateArgument ParseTemplateArgument(); DeclPtrTy ParseExplicitInstantiation(SourceLocation ExternLoc, SourceLocation TemplateLoc, SourceLocation &DeclEnd); diff --git a/include/clang/Parse/Scope.h b/include/clang/Parse/Scope.h index 480b94f73f62..c6a1e53472c1 100644 --- a/include/clang/Parse/Scope.h +++ b/include/clang/Parse/Scope.h @@ -275,7 +275,8 @@ public: AnyParent = Parent; Depth = AnyParent ? AnyParent->Depth+1 : 0; Flags = ScopeFlags; - + WithinElse = false; + if (AnyParent) { FnParent = AnyParent->FnParent; BreakParent = AnyParent->BreakParent; @@ -283,13 +284,10 @@ public: ControlParent = AnyParent->ControlParent; BlockParent = AnyParent->BlockParent; TemplateParamParent = AnyParent->TemplateParamParent; - WithinElse = AnyParent->WithinElse; - } else { FnParent = BreakParent = ContinueParent = BlockParent = 0; ControlParent = 0; TemplateParamParent = 0; - WithinElse = false; } // If this scope is a function or contains breaks/continues, remember it. diff --git a/include/clang/Parse/Template.h b/include/clang/Parse/Template.h new file mode 100644 index 000000000000..1f8ccfbf05c6 --- /dev/null +++ b/include/clang/Parse/Template.h @@ -0,0 +1,183 @@ +//===--- Template.h - Template Parsing Data Types -------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides data structures that store the parsed representation of +// templates. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_PARSE_TEMPLATE_H +#define LLVM_CLANG_PARSE_TEMPLATE_H + +#include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Ownership.h" +#include <cassert> + +namespace clang { + /// \brief Represents the parsed form of a C++ template argument. + class ParsedTemplateArgument { + public: + /// \brief Describes the kind of template argument that was parsed. + enum KindType { + /// \brief A template type parameter, stored as a type. + Type, + /// \brief A non-type template parameter, stored as an expression. + NonType, + /// \brief A template template argument, stored as a template name. + Template + }; + + /// \brief Build an empty template argument. This template argument + ParsedTemplateArgument() : Kind(Type), Arg(0) { } + + /// \brief Create a template type argument or non-type template argument. + /// + /// \param Arg the template type argument or non-type template argument. + /// \param Loc the location of the type. + ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc) + : Kind(Kind), Arg(Arg), Loc(Loc) { } + + /// \brief Create a template template argument. + /// + /// \param SS the C++ scope specifier that precedes the template name, if + /// any. + /// + /// \param Template the template to which this template template + /// argument refers. + /// + /// \param TemplateLoc the location of the template name. + ParsedTemplateArgument(const CXXScopeSpec &SS, + ActionBase::TemplateTy Template, + SourceLocation TemplateLoc) + : Kind(ParsedTemplateArgument::Template), Arg(Template.get()), + Loc(TemplateLoc), SS(SS) { } + + /// \brief Determine whether the given template argument is invalid. + bool isInvalid() { return Arg == 0; } + + /// \brief Determine what kind of template argument we have. + KindType getKind() const { return Kind; } + + /// \brief Retrieve the template type argument's type. + ActionBase::TypeTy *getAsType() const { + assert(Kind == Type && "Not a template type argument"); + return Arg; + } + + /// \brief Retrieve the non-type template argument's expression. + ActionBase::ExprTy *getAsExpr() const { + assert(Kind == NonType && "Not a non-type template argument"); + return Arg; + } + + /// \brief Retrieve the template template argument's template name. + ActionBase::TemplateTy getAsTemplate() const { + assert(Kind == Template && "Not a template template argument"); + return ActionBase::TemplateTy::make(Arg); + } + + /// \brief Retrieve the location of the template argument. + SourceLocation getLocation() const { return Loc; } + + /// \brief Retrieve the nested-name-specifier that precedes the template + /// name in a template template argument. + const CXXScopeSpec &getScopeSpec() const { + assert(Kind == Template && + "Only template template arguments can have a scope specifier"); + return SS; + } + + private: + KindType Kind; + + /// \brief The actual template argument representation, which may be + /// an \c ActionBase::TypeTy* (for a type), an ActionBase::ExprTy* (for an + /// expression), or an ActionBase::TemplateTy (for a template). + void *Arg; + + /// \brief the location of the template argument. + SourceLocation Loc; + + /// \brief The nested-name-specifier that can accompany a template template + /// argument. + CXXScopeSpec SS; + }; + + /// \brief Information about a template-id annotation + /// token. + /// + /// A template-id annotation token contains the template declaration, + /// template arguments, whether those template arguments were types, + /// expressions, or template names, and the source locations for important + /// tokens. All of the information about template arguments is allocated + /// directly after this structure. + struct TemplateIdAnnotation { + /// TemplateNameLoc - The location of the template name within the + /// source. + SourceLocation TemplateNameLoc; + + /// FIXME: Temporarily stores the name of a specialization + IdentifierInfo *Name; + + /// FIXME: Temporarily stores the overloaded operator kind. + OverloadedOperatorKind Operator; + + /// The declaration of the template corresponding to the + /// template-name. This is an Action::TemplateTy. + void *Template; + + /// The kind of template that Template refers to. + TemplateNameKind Kind; + + /// The location of the '<' before the template argument + /// list. + SourceLocation LAngleLoc; + + /// The location of the '>' after the template argument + /// list. + SourceLocation RAngleLoc; + + /// NumArgs - The number of template arguments. + unsigned NumArgs; + + /// \brief Retrieves a pointer to the template arguments + ParsedTemplateArgument *getTemplateArgs() { + return reinterpret_cast<ParsedTemplateArgument *>(this + 1); + } + + static TemplateIdAnnotation* Allocate(unsigned NumArgs) { + TemplateIdAnnotation *TemplateId + = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + + sizeof(ParsedTemplateArgument) * NumArgs); + TemplateId->NumArgs = NumArgs; + return TemplateId; + } + + void Destroy() { free(this); } + }; + +#if !defined(DISABLE_SMART_POINTERS) + inline void ASTTemplateArgsPtr::destroy() { + if (!Count) + return; + + for (unsigned I = 0; I != Count; ++I) + if (Args[I].getKind() == ParsedTemplateArgument::NonType) + Actions.DeleteExpr(Args[I].getAsExpr()); + + Count = 0; + } +#endif + + inline const ParsedTemplateArgument & + ASTTemplateArgsPtr::operator[](unsigned Arg) const { + return Args[Arg]; + } +} + +#endif diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 5b3522c9eb49..43ff6869184d 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -14,6 +14,7 @@ #define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include <memory> #include <string> @@ -43,6 +44,10 @@ public: /// \brief The different kinds of "chunks" that can occur within a code /// completion string. enum ChunkKind { + /// \brief The piece of text that the user is expected to type to + /// match the code-completion string, typically a keyword or the name of a + /// declarator or macro. + CK_TypedText, /// \brief A piece of text that should be placed in the buffer, e.g., /// parentheses or a comma in a function call. CK_Text, @@ -55,7 +60,29 @@ public: CK_Placeholder, /// \brief A piece of text that describes something about the result but /// should not be inserted into the buffer. - CK_Informative + CK_Informative, + /// \brief A piece of text that describes the parameter that corresponds + /// to the code-completion location within a function call, message send, + /// macro invocation, etc. + CK_CurrentParameter, + /// \brief A left parenthesis ('('). + CK_LeftParen, + /// \brief A right parenthesis (')'). + CK_RightParen, + /// \brief A left bracket ('['). + CK_LeftBracket, + /// \brief A right bracket (']'). + CK_RightBracket, + /// \brief A left brace ('{'). + CK_LeftBrace, + /// \brief A right brace ('}'). + CK_RightBrace, + /// \brief A left angle bracket ('<'). + CK_LeftAngle, + /// \brief A right angle bracket ('>'). + CK_RightAngle, + /// \brief A comma separator (','). + CK_Comma }; /// \brief One piece of the code completion string. @@ -66,7 +93,7 @@ public: union { /// \brief The text string associated with a CK_Text, CK_Placeholder, - /// or CK_Informative chunk. + /// CK_Informative, or CK_Comma chunk. /// The string is owned by the chunk and will be deallocated /// (with delete[]) when the chunk is destroyed. const char *Text; @@ -79,21 +106,22 @@ public: Chunk() : Kind(CK_Text), Text(0) { } - private: - Chunk(ChunkKind Kind, const char *Text); - - public: + Chunk(ChunkKind Kind, llvm::StringRef Text = ""); + /// \brief Create a new text chunk. - static Chunk CreateText(const char *Text); + static Chunk CreateText(llvm::StringRef Text); /// \brief Create a new optional chunk. static Chunk CreateOptional(std::auto_ptr<CodeCompletionString> Optional); /// \brief Create a new placeholder chunk. - static Chunk CreatePlaceholder(const char *Placeholder); + static Chunk CreatePlaceholder(llvm::StringRef Placeholder); /// \brief Create a new informative chunk. - static Chunk CreateInformative(const char *Informative); + static Chunk CreateInformative(llvm::StringRef Informative); + + /// \brief Create a new current-parameter chunk. + static Chunk CreateCurrentParameter(llvm::StringRef CurrentParameter); /// \brief Destroy this chunk, deallocating any memory it owns. void Destroy(); @@ -113,10 +141,28 @@ public: typedef llvm::SmallVector<Chunk, 4>::const_iterator iterator; iterator begin() const { return Chunks.begin(); } iterator end() const { return Chunks.end(); } + bool empty() const { return Chunks.empty(); } + unsigned size() const { return Chunks.size(); } + + Chunk &operator[](unsigned I) { + assert(I < size() && "Chunk index out-of-range"); + return Chunks[I]; + } + + const Chunk &operator[](unsigned I) const { + assert(I < size() && "Chunk index out-of-range"); + return Chunks[I]; + } + + /// \brief Add a new typed-text chunk. + /// The text string will be copied. + void AddTypedTextChunk(llvm::StringRef Text) { + Chunks.push_back(Chunk(CK_TypedText, Text)); + } /// \brief Add a new text chunk. /// The text string will be copied. - void AddTextChunk(const char *Text) { + void AddTextChunk(llvm::StringRef Text) { Chunks.push_back(Chunk::CreateText(Text)); } @@ -127,24 +173,46 @@ public: /// \brief Add a new placeholder chunk. /// The placeholder text will be copied. - void AddPlaceholderChunk(const char *Placeholder) { + void AddPlaceholderChunk(llvm::StringRef Placeholder) { Chunks.push_back(Chunk::CreatePlaceholder(Placeholder)); } /// \brief Add a new informative chunk. /// The text will be copied. - void AddInformativeChunk(const char *Text) { + void AddInformativeChunk(llvm::StringRef Text) { Chunks.push_back(Chunk::CreateInformative(Text)); } + + /// \brief Add a new current-parameter chunk. + /// The text will be copied. + void AddCurrentParameterChunk(llvm::StringRef CurrentParameter) { + Chunks.push_back(Chunk::CreateCurrentParameter(CurrentParameter)); + } + + /// \brief Add a new chunk. + void AddChunk(Chunk C) { Chunks.push_back(C); } /// \brief Retrieve a string representation of the code completion string, /// which is mainly useful for debugging. - std::string getAsString() const; + std::string getAsString() const; + + /// \brief Serialize this code-completion string to the given stream. + void Serialize(llvm::raw_ostream &OS) const; + + /// \brief Deserialize a code-completion string from the given string. + static CodeCompletionString *Deserialize(llvm::StringRef &Str); }; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const CodeCompletionString &CCS); + /// \brief Abstract interface for a consumer of code-completion /// information. class CodeCompleteConsumer { +protected: + /// \brief Whether to include macros in the code-completion results. + bool IncludeMacros; + public: /// \brief Captures a result of code completion. struct Result { @@ -291,23 +359,32 @@ public: Sema &S) const; }; + CodeCompleteConsumer() : IncludeMacros(false) { } + + explicit CodeCompleteConsumer(bool IncludeMacros) + : IncludeMacros(IncludeMacros) { } + + /// \brief Whether the code-completion consumer wants to see macros. + bool includeMacros() const { return IncludeMacros; } + /// \brief Deregisters and destroys this code-completion consumer. virtual ~CodeCompleteConsumer(); /// \name Code-completion callbacks //@{ /// \brief Process the finalized code-completion results. - virtual void ProcessCodeCompleteResults(Result *Results, + virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, unsigned NumResults) { } - - /// \brief Process the set of overload candidates. + + /// \param S the semantic-analyzer object for which code-completion is being + /// done. /// /// \param CurrentArg the index of the current argument. /// /// \param Candidates an array of overload candidates. /// /// \param NumCandidates the number of overload candidates - virtual void ProcessOverloadCandidates(unsigned CurrentArg, + virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, OverloadCandidate *Candidates, unsigned NumCandidates) { } //@} @@ -316,24 +393,43 @@ public: /// \brief A simple code-completion consumer that prints the results it /// receives in a simple format. class PrintingCodeCompleteConsumer : public CodeCompleteConsumer { - /// \brief The semantic-analysis object to which this code-completion - /// consumer is attached. - Sema &SemaRef; - /// \brief The raw output stream. llvm::raw_ostream &OS; public: /// \brief Create a new printing code-completion consumer that prints its /// results to the given raw output stream. - PrintingCodeCompleteConsumer(Sema &S, llvm::raw_ostream &OS) - : SemaRef(S), OS(OS) { } + PrintingCodeCompleteConsumer(bool IncludeMacros, + llvm::raw_ostream &OS) + : CodeCompleteConsumer(IncludeMacros), OS(OS) { } + + /// \brief Prints the finalized code-completion results. + virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, + unsigned NumResults); + + virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates); +}; + +/// \brief A code-completion consumer that prints the results it receives +/// in a format that is parsable by the CIndex library. +class CIndexCodeCompleteConsumer : public CodeCompleteConsumer { + /// \brief The raw output stream. + llvm::raw_ostream &OS; + +public: + /// \brief Create a new CIndex code-completion consumer that prints its + /// results to the given raw output stream in a format readable to the CIndex + /// library. + CIndexCodeCompleteConsumer(bool IncludeMacros, llvm::raw_ostream &OS) + : CodeCompleteConsumer(IncludeMacros), OS(OS) { } /// \brief Prints the finalized code-completion results. - virtual void ProcessCodeCompleteResults(Result *Results, + virtual void ProcessCodeCompleteResults(Sema &S, Result *Results, unsigned NumResults); - virtual void ProcessOverloadCandidates(unsigned CurrentArg, + virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, OverloadCandidate *Candidates, unsigned NumCandidates); }; diff --git a/include/clang/Sema/ParseAST.h b/include/clang/Sema/ParseAST.h index 8a245d03cdaa..f6cff2a023e6 100644 --- a/include/clang/Sema/ParseAST.h +++ b/include/clang/Sema/ParseAST.h @@ -20,7 +20,7 @@ namespace clang { class ASTContext; class CodeCompleteConsumer; class Sema; - + /// \brief Parse the entire file specified, notifying the ASTConsumer as /// the file is parsed. /// @@ -30,11 +30,13 @@ namespace clang { /// \param CompleteTranslationUnit When true, the parsed file is /// considered to be a complete translation unit, and any /// end-of-translation-unit wrapup will be performed. + /// + /// \param CompletionConsumer If given, an object to consume code completion + /// results. void ParseAST(Preprocessor &pp, ASTConsumer *C, ASTContext &Ctx, bool PrintStats = false, bool CompleteTranslationUnit = true, - CodeCompleteConsumer *(*CreateCodeCompleter)(Sema &, void *Data) = 0, - void *CreateCodeCompleterData = 0); + CodeCompleteConsumer *CompletionConsumer = 0); } // end namespace clang |