diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2011-05-02 19:39:53 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2011-05-02 19:39:53 +0000 |
commit | 01af97d3b23bded2b2b21af19bbc6e4cce49e5b3 (patch) | |
tree | 64a10f4c4154739d4a8191d7e1b52ce497f4ebd6 /include/clang | |
parent | c3b054d250cdca485c71845089c316e10610ebad (diff) |
Notes
Diffstat (limited to 'include/clang')
167 files changed, 6416 insertions, 4009 deletions
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index 08ee4ef40de0..fcc91768dac3 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -89,7 +89,7 @@ public: /// \brief If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to - /// a GetASTMutationListener here. + /// an ASTMutationListener here. virtual ASTMutationListener *GetASTMutationListener() { return 0; } /// \brief If the consumer is interested in entities being deserialized from diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index c0eeb5af3892..28ec8cf88d52 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -14,10 +14,12 @@ #ifndef LLVM_CLANG_AST_ASTCONTEXT_H #define LLVM_CLANG_AST_ASTCONTEXT_H +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/VersionTuple.h" #include "clang/AST/Decl.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" @@ -27,6 +29,7 @@ #include "clang/AST/UsuallyTinyPtrVector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/Allocator.h" @@ -68,7 +71,7 @@ namespace clang { class TemplateTypeParmDecl; class TranslationUnitDecl; class TypeDecl; - class TypedefDecl; + class TypedefNameDecl; class UsingDecl; class UsingShadowDecl; class UnresolvedSetIterator; @@ -77,7 +80,7 @@ namespace clang { /// ASTContext - This class holds long-lived AST nodes (such as types and /// decls) that can be referred to throughout the semantic analysis of a file. -class ASTContext { +class ASTContext : public llvm::RefCountedBase<ASTContext> { ASTContext &this_() { return *this; } mutable std::vector<Type*> Types; @@ -96,7 +99,8 @@ class ASTContext { DependentSizedExtVectorTypes; mutable llvm::FoldingSet<VectorType> VectorTypes; mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; - mutable llvm::FoldingSet<FunctionProtoType> FunctionProtoTypes; + mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&> + FunctionProtoTypes; mutable llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes; mutable llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; @@ -310,6 +314,9 @@ class ASTContext { llvm::OwningPtr<CXXABI> ABI; CXXABI *createCXXABI(const TargetInfo &T); + /// \brief The logical -> physical address space map. + const LangAS::Map &AddrSpaceMap; + friend class ASTDeclReader; public: @@ -335,6 +342,14 @@ public: } void Deallocate(void *Ptr) const { } + /// Return the total amount of physical memory allocated for representing + /// AST nodes and type information. + size_t getASTAllocatedMemory() const { + return BumpAlloc.getTotalMemory(); + } + /// Return the total memory used for various side tables. + size_t getSideTableAllocatedMemory() const; + PartialDiagnostic::StorageAllocator &getDiagAllocator() { return DiagAllocator; } @@ -381,6 +396,16 @@ public: FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); + + /// ZeroBitfieldFollowsNonBitfield - return 'true" if 'FD' is a zero-length + /// bitfield which follows the non-bitfield 'LastFD'. + bool ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const; + + /// ZeroBitfieldFollowsBitfield - return 'true" if 'FD' is a zero-length + /// bitfield which follows the bitfield 'LastFD'. + bool ZeroBitfieldFollowsBitfield(const FieldDecl *FD, + const FieldDecl *LastFD) const; // Access to the set of methods overridden by the given C++ method. typedef CXXMethodVector::iterator overridden_cxx_method_iterator; @@ -413,10 +438,13 @@ public: CanQualType FloatTy, DoubleTy, LongDoubleTy; CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; CanQualType VoidPtrTy, NullPtrTy; - CanQualType OverloadTy; - CanQualType DependentTy; + CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; + // Types for deductions in C++0x [stmt.ranged]'s desugaring. Built on demand. + mutable QualType AutoDeductTy; // Deduction against 'auto'. + mutable QualType AutoRRefDeductTy; // Deduction against 'auto &&'. + ASTContext(const LangOptions& LOpts, SourceManager &SM, const TargetInfo &t, IdentifierTable &idents, SelectorTable &sels, Builtin::Context &builtins, @@ -654,9 +682,9 @@ public: } /// getTypedefType - Return the unique reference to the type for the - /// specified typename decl. - QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType()) - const; + /// specified typedef-name decl. + QualType getTypedefType(const TypedefNameDecl *Decl, + QualType Canon = QualType()) const; QualType getRecordType(const RecordDecl *Decl) const; @@ -676,7 +704,7 @@ public: QualType getTemplateTypeParmType(unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name = 0) const; + TemplateTypeParmDecl *ParmDecl = 0) const; QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, @@ -739,6 +767,12 @@ public: /// getAutoType - C++0x deduced auto type. QualType getAutoType(QualType DeducedType) const; + /// getAutoDeductType - C++0x deduction pattern for 'auto' type. + QualType getAutoDeductType() const; + + /// getAutoRRefDeductType - C++0x deduction pattern for 'auto &&' type. + QualType getAutoRRefDeductType() const; + /// getTagDeclType - Return the unique reference to the type for the /// specified TagDecl (struct/union/class/enum) decl. QualType getTagDeclType(const TagDecl *Decl) const; @@ -1294,6 +1328,21 @@ public: QualType getFloatingTypeOfSizeWithinDomain(QualType typeSize, QualType typeDomain) const; + unsigned getTargetAddressSpace(QualType T) const { + return getTargetAddressSpace(T.getQualifiers()); + } + + unsigned getTargetAddressSpace(Qualifiers Q) const { + return getTargetAddressSpace(Q.getAddressSpace()); + } + + unsigned getTargetAddressSpace(unsigned AS) const { + if (AS < LangAS::Offset || AS >= LangAS::Offset + LangAS::Count) + return AS; + else + return AddrSpaceMap[AS - LangAS::Offset]; + } + private: // Helper for integer ordering unsigned getIntegerRank(const Type *T) const; @@ -1332,7 +1381,8 @@ public: const ObjCObjectType *RHS); bool canAssignObjCInterfacesInBlockPointer( const ObjCObjectPointerType *LHSOPT, - const ObjCObjectPointerType *RHSOPT); + const ObjCObjectPointerType *RHSOPT, + bool BlockReturnType); bool areComparableObjCPointerTypes(QualType LHS, QualType RHS); QualType areCommonBaseCompatible(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT); @@ -1340,7 +1390,7 @@ public: // Functions for calculating composite types QualType mergeTypes(QualType, QualType, bool OfBlockPointer=false, - bool Unqualified = false); + bool Unqualified = false, bool BlockReturnType = false); QualType mergeFunctionTypes(QualType, QualType, bool OfBlockPointer=false, bool Unqualified = false); QualType mergeFunctionArgumentTypes(QualType, QualType, @@ -1528,13 +1578,13 @@ private: }; /// @brief Utility function for constructing a nullary selector. -static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) { +static inline Selector GetNullarySelector(llvm::StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(0, &II); } /// @brief Utility function for constructing an unary selector. -static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) { +static inline Selector GetUnarySelector(llvm::StringRef name, ASTContext& Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(1, &II); } diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index 1ab53b3e9148..1cb803a3396a 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define ASTSTART #include "clang/Basic/DiagnosticASTKinds.inc" #undef DIAG diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 01e618024913..470cca8ee76e 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -20,6 +20,8 @@ namespace clang { class CXXRecordDecl; class ClassTemplateDecl; class ClassTemplateSpecializationDecl; + class FunctionDecl; + class FunctionTemplateDecl; /// \brief An abstract interface that should be implemented by listeners /// that want to be notified when an AST entity gets modified after its @@ -41,6 +43,17 @@ public: /// template declaration. virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {} + + /// \brief A template specialization (or partial one) was added to the + /// template declaration. + virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D) {} + + /// \brief An implicit member got a definition. + virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} + + /// \brief A static data member was implicitly instantiated. + virtual void StaticDataMemberInstantiated(const VarDecl *D) {} }; } // end namespace clang diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 67968fde2d6b..719023926bae 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -17,9 +17,11 @@ #include "llvm/Support/Casting.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" #include "clang/Basic/AttrKinds.h" #include "clang/AST/Type.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/VersionTuple.h" #include <cassert> #include <cstring> #include <algorithm> @@ -120,6 +122,19 @@ public: static bool classof(const InheritableAttr *) { return true; } }; +class InheritableParamAttr : public InheritableAttr { +protected: + InheritableParamAttr(attr::Kind AK, SourceLocation L) + : InheritableAttr(AK, L) {} + +public: + // Implement isa/cast/dyncast/etc. + static bool classof(const Attr *A) { + return A->getKind() <= attr::LAST_INHERITABLE_PARAM; + } + static bool classof(const InheritableParamAttr *) { return true; } +}; + #include "clang/AST/Attrs.inc" /// AttrVec - A vector of Attr, which is how they are stored on the AST. diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 2d30cb3b8b62..d712e7d0c751 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -87,7 +87,7 @@ public: /// BasePaths - Represents the set of paths from a derived class to /// one of its (direct or indirect) bases. For example, given the -/// following class hierachy: +/// following class hierarchy: /// /// @code /// class A { }; diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 4d7fcfd1d121..b3550f877323 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -655,7 +655,8 @@ struct CanProxyAdaptor<TemplateTypeParmType> LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getDepth) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getIndex) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isParameterPack) - LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getName) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(TemplateTypeParmDecl *, getDecl) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(IdentifierInfo *, getIdentifier) }; template<> diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index cf909e88220f..d7cbd08e6c2e 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -34,7 +34,7 @@ namespace clang { /// architectures where the two are the same size. /// /// For portability, never assume that a target character is 8 bits wide. Use - /// CharUnit values whereever you calculate sizes, offsets, or alignments + /// CharUnit values wherever you calculate sizes, offsets, or alignments /// in character units. class CharUnits { public: @@ -70,10 +70,24 @@ namespace clang { Quantity += Other.Quantity; return *this; } + CharUnits& operator++ () { + ++Quantity; + return *this; + } + CharUnits operator++ (int) { + return CharUnits(Quantity++); + } CharUnits& operator-= (const CharUnits &Other) { Quantity -= Other.Quantity; return *this; } + CharUnits& operator-- () { + --Quantity; + return *this; + } + CharUnits operator-- (int) { + return CharUnits(Quantity--); + } // Comparison operators. bool operator== (const CharUnits &Other) const { diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 31cee24df993..ef4920520391 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -20,6 +20,7 @@ #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" #include "clang/Basic/Linkage.h" +#include "llvm/ADT/Optional.h" namespace clang { class CXXTemporary; @@ -119,14 +120,6 @@ public: return getIdentifier() ? getIdentifier()->getName() : ""; } - llvm::StringRef getMessageUnavailableAttr(bool unavailable) const { - if (!unavailable) - return ""; - if (const UnavailableAttr *UA = getAttr<UnavailableAttr>()) - return UA->getMessage(); - return ""; - } - /// getNameAsString - Get a human-readable name for the declaration, even if /// it is one of the special kinds of names (C++ constructor, Objective-C /// selector, etc). Creating this name requires expensive string @@ -281,6 +274,10 @@ public: /// \brief Determines the linkage and visibility of this entity. LinkageInfo getLinkageAndVisibility() const; + /// \brief If visibility was explicitly specified for this + /// declaration, return that visibility. + llvm::Optional<Visibility> getExplicitVisibility() const; + /// \brief Clear the linkage cache in response to a change /// to the declaration. void ClearLinkageCache(); @@ -310,16 +307,32 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, /// location is where the __label__ is. class LabelDecl : public NamedDecl { LabelStmt *TheStmt; - LabelDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *II, LabelStmt *S) - : NamedDecl(Label, DC, L, II), TheStmt(S) {} - + /// LocStart - For normal labels, this is the same as the main declaration + /// label, i.e., the location of the identifier; for GNU local labels, + /// this is the location of the __label__ keyword. + SourceLocation LocStart; + + LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, + LabelStmt *S, SourceLocation StartL) + : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {} + public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *II); + SourceLocation IdentL, IdentifierInfo *II); + static LabelDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation IdentL, IdentifierInfo *II, + SourceLocation GnuLabelL); LabelStmt *getStmt() const { return TheStmt; } void setStmt(LabelStmt *T) { TheStmt = T; } - + + bool isGnuLocal() const { return LocStart != getLocation(); } + void setLocStart(SourceLocation L) { LocStart = L; } + + SourceRange getSourceRange() const { + return SourceRange(LocStart, getLocation()); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LabelDecl *D) { return true; } @@ -330,7 +343,11 @@ public: class NamespaceDecl : public NamedDecl, public DeclContext { bool IsInline : 1; - SourceLocation LBracLoc, RBracLoc; + /// LocStart - The starting location of the source range, pointing + /// to either the namespace or the inline keyword. + SourceLocation LocStart; + /// RBraceLoc - The ending location of the source range. + SourceLocation RBraceLoc; // For extended namespace definitions: // @@ -357,13 +374,16 @@ class NamespaceDecl : public NamedDecl, public DeclContext { /// namespace declaration (which the boolean indicates). llvm::PointerIntPair<NamespaceDecl *, 1, bool> OrigOrAnonNamespace; - NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) - : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), - IsInline(false), NextNamespace(), OrigOrAnonNamespace(0, true) { } + NamespaceDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id) + : NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace), + IsInline(false), LocStart(StartLoc), RBraceLoc(), + NextNamespace(), OrigOrAnonNamespace(0, true) { } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id); + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id); /// \brief Returns true if this is an anonymous namespace declaration. /// @@ -427,7 +447,7 @@ public: void setAnonymousNamespace(NamespaceDecl *D) { assert(!D || D->isAnonymousNamespace()); - assert(!D || D->getParent() == this); + assert(!D || D->getParent()->getRedeclContext() == this); getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D); } @@ -437,14 +457,14 @@ public: } virtual SourceRange getSourceRange() const { - return SourceRange(getLocation(), RBracLoc); + return SourceRange(LocStart, RBraceLoc); } - SourceLocation getLBracLoc() const { return LBracLoc; } - SourceLocation getRBracLoc() const { return RBracLoc; } - void setLBracLoc(SourceLocation L) { LBracLoc = L; } - void setRBracLoc(SourceLocation R) { RBracLoc = R; } - + SourceLocation getLocStart() const { return LocStart; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setLocStart(SourceLocation L) { LocStart = L; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceDecl *D) { return true; } @@ -484,16 +504,24 @@ public: /// name qualifier, to be used for the case of out-of-line declarations. struct QualifierInfo { NestedNameSpecifierLoc QualifierLoc; - /// NumTemplParamLists - The number of template parameter lists - /// that were matched against the template-ids occurring into the NNS. + + /// NumTemplParamLists - The number of "outer" template parameter lists. + /// The count includes all of the template parameter lists that were matched + /// against the template-ids occurring into the NNS and possibly (in the + /// case of an explicit specialization) a final "template <>". unsigned NumTemplParamLists; + /// TemplParamLists - A new-allocated array of size NumTemplParamLists, - /// containing pointers to the matched template parameter lists. + /// containing pointers to the "outer" template parameter lists. + /// It includes all of the template parameter lists that were matched + /// against the template-ids occurring into the NNS and possibly (in the + /// case of an explicit specialization) a final "template <>". TemplateParameterList** TemplParamLists; /// Default constructor. QualifierInfo() : QualifierLoc(), NumTemplParamLists(0), TemplParamLists(0) {} - /// setTemplateParameterListsInfo - Sets info about matched template + + /// setTemplateParameterListsInfo - Sets info about "outer" template /// parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, @@ -516,14 +544,20 @@ class DeclaratorDecl : public ValueDecl { llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo; + /// InnerLocStart - The start of the source range for this declaration, + /// ignoring outer template declarations. + SourceLocation InnerLocStart; + bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); } ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); } const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); } protected: DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, TypeSourceInfo *TInfo) - : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} + DeclarationName N, QualType T, TypeSourceInfo *TInfo, + SourceLocation StartL) + : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) { + } public: TypeSourceInfo *getTypeSourceInfo() const { @@ -540,14 +574,14 @@ public: /// getInnerLocStart - Return SourceLocation representing start of source /// range ignoring outer template declarations. - virtual SourceLocation getInnerLocStart() const { return getLocation(); } + SourceLocation getInnerLocStart() const { return InnerLocStart; } + void setInnerLocStart(SourceLocation L) { InnerLocStart = L; } /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; - SourceRange getSourceRange() const { - return SourceRange(getOuterLocStart(), getLocation()); - } + + virtual SourceRange getSourceRange() const; /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. @@ -574,9 +608,7 @@ public: return getExtInfo()->TemplParamLists[index]; } void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists) { - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); - } + TemplateParameterList **TPLists); SourceLocation getTypeSpecStartLoc() const; @@ -650,32 +682,77 @@ protected: mutable InitType Init; private: - // FIXME: This can be packed into the bitfields in Decl. - unsigned SClass : 3; - unsigned SClassAsWritten : 3; - bool ThreadSpecified : 1; - bool HasCXXDirectInit : 1; - - /// \brief Whether this variable is the exception variable in a C++ catch - /// or an Objective-C @catch statement. - bool ExceptionVar : 1; + class VarDeclBitfields { + friend class VarDecl; + friend class ASTDeclReader; + + unsigned SClass : 3; + unsigned SClassAsWritten : 3; + unsigned ThreadSpecified : 1; + unsigned HasCXXDirectInit : 1; + + /// \brief Whether this variable is the exception variable in a C++ catch + /// or an Objective-C @catch statement. + unsigned ExceptionVar : 1; - /// \brief Whether this local variable could be allocated in the return - /// slot of its function, enabling the named return value optimization (NRVO). - bool NRVOVariable : 1; + /// \brief Whether this local variable could be allocated in the return + /// slot of its function, enabling the named return value optimization (NRVO). + unsigned NRVOVariable : 1; + + /// \brief Whether this variable is the for-range-declaration in a C++0x + /// for-range statement. + unsigned CXXForRangeDecl : 1; + }; + enum { NumVarDeclBits = 13 }; // two reserved bits for now - friend class StmtIteratorBase; friend class ASTDeclReader; + friend class StmtIteratorBase; protected: - VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + class ParmVarDeclBitfields { + friend class ParmVarDecl; + friend class ASTDeclReader; + + unsigned : NumVarDeclBits; + + /// Whether this parameter inherits a default argument from a + /// prior declaration. + unsigned HasInheritedDefaultArg : 1; + + /// Whether this parameter undergoes K&R argument promotion. + unsigned IsKNRPromoted : 1; + + /// Whether this parameter is an ObjC method parameter or not. + unsigned IsObjCMethodParam : 1; + + /// If IsObjCMethodParam, a Decl::ObjCDeclQualifier. + /// Otherwise, the number of function parameter scopes enclosing + /// the function parameter scope in which this parameter was + /// declared. + unsigned ScopeDepthOrObjCQuals : 8; + + /// The number of parameters preceding this parameter in the + /// function parameter scope in which it was declared. + unsigned ParameterIndex : 8; + }; + + union { + unsigned AllBits; + VarDeclBitfields VarDeclBits; + ParmVarDeclBitfields ParmVarDeclBits; + }; + + VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC, StorageClass SCAsWritten) - : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), - ThreadSpecified(false), HasCXXDirectInit(false), - ExceptionVar(false), NRVOVariable(false) { - SClass = SC; - SClassAsWritten = SCAsWritten; + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { + assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); + assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); + AllBits = 0; + VarDeclBits.SClass = SC; + VarDeclBits.SClassAsWritten = SCAsWritten; + // Everything else is implicitly initialized to false. } typedef Redeclarable<VarDecl> redeclarable_base; @@ -691,26 +768,27 @@ public: } static VarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, StorageClass S, - StorageClass SCAsWritten); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + StorageClass S, StorageClass SCAsWritten); - virtual SourceLocation getInnerLocStart() const; virtual SourceRange getSourceRange() const; - StorageClass getStorageClass() const { return (StorageClass)SClass; } + StorageClass getStorageClass() const { + return (StorageClass) VarDeclBits.SClass; + } StorageClass getStorageClassAsWritten() const { - return (StorageClass) SClassAsWritten; + return (StorageClass) VarDeclBits.SClassAsWritten; } void setStorageClass(StorageClass SC); void setStorageClassAsWritten(StorageClass SC) { assert(isLegalForVariable(SC)); - SClassAsWritten = SC; + VarDeclBits.SClassAsWritten = SC; } - void setThreadSpecified(bool T) { ThreadSpecified = T; } + void setThreadSpecified(bool T) { VarDeclBits.ThreadSpecified = T; } bool isThreadSpecified() const { - return ThreadSpecified; + return VarDeclBits.ThreadSpecified; } /// hasLocalStorage - Returns true if a variable with function scope @@ -988,7 +1066,7 @@ public: Eval->IsICE = IsICE; } - void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; } + void setCXXDirectInitializer(bool T) { VarDeclBits.HasCXXDirectInit = T; } /// hasCXXDirectInitializer - If true, the initializer was a direct /// initializer, e.g: "int x(1);". The Init expression will be the expression @@ -997,15 +1075,15 @@ public: /// by checking hasCXXDirectInitializer. /// bool hasCXXDirectInitializer() const { - return HasCXXDirectInit; + return VarDeclBits.HasCXXDirectInit; } /// \brief Determine whether this variable is the exception variable in a /// C++ catch statememt or an Objective-C @catch statement. bool isExceptionVariable() const { - return ExceptionVar; + return VarDeclBits.ExceptionVar; } - void setExceptionVariable(bool EV) { ExceptionVar = EV; } + void setExceptionVariable(bool EV) { VarDeclBits.ExceptionVar = EV; } /// \brief Determine whether this local variable can be used with the named /// return value optimization (NRVO). @@ -1017,8 +1095,13 @@ public: /// return slot when returning from the function. Within the function body, /// each return that returns the NRVO object will have this variable as its /// NRVO candidate. - bool isNRVOVariable() const { return NRVOVariable; } - void setNRVOVariable(bool NRVO) { NRVOVariable = NRVO; } + bool isNRVOVariable() const { return VarDeclBits.NRVOVariable; } + void setNRVOVariable(bool NRVO) { VarDeclBits.NRVOVariable = NRVO; } + + /// \brief Determine whether this variable is the for-range-declaration in + /// a C++0x for-range statement. + bool isCXXForRangeDecl() const { return VarDeclBits.CXXForRangeDecl; } + void setCXXForRangeDecl(bool FRD) { VarDeclBits.CXXForRangeDecl = FRD; } /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member @@ -1048,12 +1131,12 @@ public: class ImplicitParamDecl : public VarDecl { public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T); - ImplicitParamDecl(DeclContext *DC, SourceLocation loc, - IdentifierInfo *name, QualType type) - : VarDecl(ImplicitParam, DC, loc, name, type, + ImplicitParamDecl(DeclContext *DC, SourceLocation IdLoc, + IdentifierInfo *Id, QualType Type) + : VarDecl(ImplicitParam, DC, IdLoc, IdLoc, Id, Type, /*tinfo*/ 0, SC_None, SC_None) { setImplicit(); } @@ -1064,35 +1147,85 @@ public: static bool classofKind(Kind K) { return K == ImplicitParam; } }; -/// ParmVarDecl - Represent a parameter to a function. +/// ParmVarDecl - Represents a parameter to a function. class ParmVarDecl : public VarDecl { - // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum - /// FIXME: Also can be paced into the bitfields in Decl. - /// in, inout, etc. - unsigned objcDeclQualifier : 6; - bool HasInheritedDefaultArg : 1; +public: + enum { MaxFunctionScopeDepth = 255 }; + enum { MaxFunctionScopeIndex = 255 }; protected: - ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, Expr *DefArg) - : VarDecl(DK, DC, L, Id, T, TInfo, S, SCAsWritten), - objcDeclQualifier(OBJC_TQ_None), HasInheritedDefaultArg(false) { + : VarDecl(DK, DC, StartLoc, IdLoc, Id, T, TInfo, S, SCAsWritten) { + assert(ParmVarDeclBits.HasInheritedDefaultArg == false); + assert(ParmVarDeclBits.IsKNRPromoted == false); + assert(ParmVarDeclBits.IsObjCMethodParam == false); setDefaultArg(DefArg); } public: static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L,IdentifierInfo *Id, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, Expr *DefArg); + void setObjCMethodScopeInfo(unsigned parameterIndex) { + ParmVarDeclBits.IsObjCMethodParam = true; + + ParmVarDeclBits.ParameterIndex = parameterIndex; + assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); + } + + void setScopeInfo(unsigned scopeDepth, unsigned parameterIndex) { + assert(!ParmVarDeclBits.IsObjCMethodParam); + + ParmVarDeclBits.ScopeDepthOrObjCQuals = scopeDepth; + assert(ParmVarDeclBits.ScopeDepthOrObjCQuals == scopeDepth && "truncation!"); + + ParmVarDeclBits.ParameterIndex = parameterIndex; + assert(ParmVarDeclBits.ParameterIndex == parameterIndex && "truncation!"); + } + + bool isObjCMethodParameter() const { + return ParmVarDeclBits.IsObjCMethodParam; + } + + unsigned getFunctionScopeDepth() const { + if (ParmVarDeclBits.IsObjCMethodParam) return 0; + return ParmVarDeclBits.ScopeDepthOrObjCQuals; + } + + /// Returns the index of this parameter in its prototype or method scope. + unsigned getFunctionScopeIndex() const { + return ParmVarDeclBits.ParameterIndex; + } + ObjCDeclQualifier getObjCDeclQualifier() const { - return ObjCDeclQualifier(objcDeclQualifier); + if (!ParmVarDeclBits.IsObjCMethodParam) return OBJC_TQ_None; + return ObjCDeclQualifier(ParmVarDeclBits.ScopeDepthOrObjCQuals); } void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { - objcDeclQualifier = QTVal; + assert(ParmVarDeclBits.IsObjCMethodParam); + ParmVarDeclBits.ScopeDepthOrObjCQuals = QTVal; + } + + /// True if the value passed to this parameter must undergo + /// K&R-style default argument promotion: + /// + /// C99 6.5.2.2. + /// If the expression that denotes the called function has a type + /// that does not include a prototype, the integer promotions are + /// performed on each argument, and arguments that have type float + /// are promoted to double. + bool isKNRPromoted() const { + return ParmVarDeclBits.IsKNRPromoted; + } + void setKNRPromoted(bool promoted) { + ParmVarDeclBits.IsKNRPromoted = promoted; } Expr *getDefaultArg(); @@ -1158,11 +1291,11 @@ public: } bool hasInheritedDefaultArg() const { - return HasInheritedDefaultArg; + return ParmVarDeclBits.HasInheritedDefaultArg; } void setHasInheritedDefaultArg(bool I = true) { - HasInheritedDefaultArg = I; + ParmVarDeclBits.HasInheritedDefaultArg = I; } QualType getOriginalType() const { @@ -1233,6 +1366,7 @@ private: bool IsDeleted : 1; bool IsTrivial : 1; // sunk from CXXMethodDecl bool HasImplicitReturnZero : 1; + bool IsLateTemplateParsed : 1; /// \brief End part of this FunctionDecl's source range. /// @@ -1302,17 +1436,20 @@ private: void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams); protected: - FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo, + FunctionDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass S, StorageClass SCAsWritten, bool isInlineSpecified) - : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo), + : DeclaratorDecl(DK, DC, NameInfo.getLoc(), NameInfo.getName(), T, TInfo, + StartLoc), DeclContext(DK), ParamInfo(0), Body(), - SClass(S), SClassAsWritten(SCAsWritten), + SClass(S), SClassAsWritten(SCAsWritten), IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), - HasImplicitReturnZero(false), EndRangeLoc(NameInfo.getEndLoc()), + HasImplicitReturnZero(false), IsLateTemplateParsed(false), + EndRangeLoc(NameInfo.getEndLoc()), TemplateOrSpecialization(), DNLoc(NameInfo.getInfo()) {} @@ -1328,22 +1465,25 @@ public: return redeclarable_base::redecls_end(); } - static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, + static FunctionDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation NLoc, DeclarationName N, QualType T, TypeSourceInfo *TInfo, - StorageClass S = SC_None, + StorageClass SC = SC_None, StorageClass SCAsWritten = SC_None, bool isInlineSpecified = false, bool hasWrittenPrototype = true) { - DeclarationNameInfo NameInfo(N, L); - return FunctionDecl::Create(C, DC, NameInfo, T, TInfo, S, SCAsWritten, + DeclarationNameInfo NameInfo(N, NLoc); + return FunctionDecl::Create(C, DC, StartLoc, NameInfo, T, TInfo, + SC, SCAsWritten, isInlineSpecified, hasWrittenPrototype); } static FunctionDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - StorageClass S = SC_None, + StorageClass SC = SC_None, StorageClass SCAsWritten = SC_None, bool isInlineSpecified = false, bool hasWrittenPrototype = true); @@ -1356,12 +1496,9 @@ public: const PrintingPolicy &Policy, bool Qualified) const; - virtual SourceRange getSourceRange() const { - return SourceRange(getOuterLocStart(), EndRangeLoc); - } - void setLocEnd(SourceLocation E) { - EndRangeLoc = E; - } + void setRangeEnd(SourceLocation E) { EndRangeLoc = E; } + + virtual SourceRange getSourceRange() const; /// \brief Returns true if the function has a body (definition). The /// function body might be in any of the (re-)declarations of this @@ -1395,7 +1532,9 @@ public: /// previous definition); for that information, use getBody. /// FIXME: Should return true if function is deleted or defaulted. However, /// CodeGenModule.cpp uses it, and I don't know if this would break it. - bool isThisDeclarationADefinition() const { return Body; } + bool isThisDeclarationADefinition() const { + return Body || IsLateTemplateParsed; + } void setBody(Stmt *B); void setLazyBody(uint64_t Offset) { Body = Offset; } @@ -1412,6 +1551,14 @@ public: bool isPure() const { return IsPure; } void setPure(bool P = true); + /// Whether this is a constexpr function or constexpr constructor. + // FIXME: C++0x: Implement tracking of the constexpr specifier. + bool isConstExpr() const { return false; } + + /// Whether this templated function will be late parsed. + bool isLateTemplateParsed() const { return IsLateTemplateParsed; } + void setLateTemplateParsed(bool ILT = true) { IsLateTemplateParsed = ILT; } + /// Whether this function is "trivial" in some specialized C++ senses. /// Can only be true for default constructors, copy constructors, /// copy assignment operators, and destructors. Not meaningful until @@ -1757,16 +1904,17 @@ class FieldDecl : public DeclaratorDecl { Expr *BitWidth; protected: - FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - Expr *BW, bool Mutable) - : DeclaratorDecl(DK, DC, L, Id, T, TInfo), + FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable) + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Mutable(Mutable), CachedFieldIndex(0), BitWidth(BW) { } public: static FieldDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, QualType T, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable); /// getFieldIndex - Returns the index of this field within its record, @@ -1803,7 +1951,9 @@ public: RecordDecl *getParent() { return cast<RecordDecl>(getDeclContext()); } - + + SourceRange getSourceRange() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FieldDecl *D) { return true; } @@ -1895,6 +2045,8 @@ class TypeDecl : public NamedDecl { /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. mutable const Type *TypeForDecl; + /// LocStart - The start of the source range for this declaration. + SourceLocation LocStart; friend class ASTContext; friend class DeclContext; friend class TagDecl; @@ -1902,15 +2054,24 @@ class TypeDecl : public NamedDecl { friend class TagType; protected: - TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id) - : NamedDecl(DK, DC, L, Id), TypeForDecl(0) {} + TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + SourceLocation StartL = SourceLocation()) + : NamedDecl(DK, DC, L, Id), TypeForDecl(0), LocStart(StartL) {} public: // Low-level accessor const Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(const Type *TD) { TypeForDecl = TD; } + SourceLocation getLocStart() const { return LocStart; } + void setLocStart(SourceLocation L) { LocStart = L; } + virtual SourceRange getSourceRange() const { + if (LocStart.isValid()) + return SourceRange(LocStart, getLocation()); + else + return SourceRange(getLocation()); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypeDecl *D) { return true; } @@ -1918,17 +2079,21 @@ public: }; -class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> { +/// Base class for declarations which introduce a typedef-name. +class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { /// UnderlyingType - This is the type the typedef is set to. TypeSourceInfo *TInfo; - TypedefDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} - protected: - typedef Redeclarable<TypedefDecl> redeclarable_base; - virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + TypedefNameDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + TypeSourceInfo *TInfo) + : TypeDecl(DK, DC, IdLoc, Id, StartLoc), TInfo(TInfo) {} + + typedef Redeclarable<TypedefNameDecl> redeclarable_base; + virtual TypedefNameDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; @@ -1939,19 +2104,15 @@ public: return redeclarable_base::redecls_end(); } - static TypedefDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - TypeSourceInfo *TInfo); - TypeSourceInfo *getTypeSourceInfo() const { return TInfo; } - /// Retrieves the canonical declaration of this typedef. - TypedefDecl *getCanonicalDecl() { + /// Retrieves the canonical declaration of this typedef-name. + TypedefNameDecl *getCanonicalDecl() { return getFirstDeclaration(); } - const TypedefDecl *getCanonicalDecl() const { + const TypedefNameDecl *getCanonicalDecl() const { return getFirstDeclaration(); } @@ -1964,11 +2125,51 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypedefNameDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= firstTypedefName && K <= lastTypedefName; + } +}; + +/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' +/// type specifier. +class TypedefDecl : public TypedefNameDecl { + TypedefDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(Typedef, DC, StartLoc, IdLoc, Id, TInfo) {} + +public: + static TypedefDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo); + + SourceRange getSourceRange() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypedefDecl *D) { return true; } static bool classofKind(Kind K) { return K == Typedef; } }; -class TypedefDecl; +/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x +/// alias-declaration. +class TypeAliasDecl : public TypedefNameDecl { + TypeAliasDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(TypeAlias, DC, StartLoc, IdLoc, Id, TInfo) {} + +public: + static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo); + + SourceRange getSourceRange() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypeAliasDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TypeAlias; } +}; /// TagDecl - Represents the declaration of a struct/union/class/enum. class TagDecl @@ -2013,32 +2214,31 @@ protected: bool IsFixed : 1; private: - SourceLocation TagKeywordLoc; SourceLocation RBraceLoc; // A struct representing syntactic qualifier info, // to be used for the (uncommon) case of out-of-line declarations. typedef QualifierInfo ExtInfo; - /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name + /// TypedefNameDeclOrQualifier - If the (out-of-line) tag declaration name /// is qualified, it points to the qualifier info (nns and range); /// otherwise, if the tag declaration is anonymous and it is part of - /// a typedef, it points to the TypedefDecl (used for mangling); - /// otherwise, it is a null (TypedefDecl) pointer. - llvm::PointerUnion<TypedefDecl*, ExtInfo*> TypedefDeclOrQualifier; + /// a typedef or alias, it points to the TypedefNameDecl (used for mangling); + /// otherwise, it is a null (TypedefNameDecl) pointer. + llvm::PointerUnion<TypedefNameDecl*, ExtInfo*> TypedefNameDeclOrQualifier; - bool hasExtInfo() const { return TypedefDeclOrQualifier.is<ExtInfo*>(); } - ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get<ExtInfo*>(); } + bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo*>(); } + ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo*>(); } const ExtInfo *getExtInfo() const { - return TypedefDeclOrQualifier.get<ExtInfo*>(); + return TypedefNameDeclOrQualifier.get<ExtInfo*>(); } protected: TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - TagDecl *PrevDecl, SourceLocation TKL = SourceLocation()) - : TypeDecl(DK, DC, L, Id), DeclContext(DK), TagKeywordLoc(TKL), - TypedefDeclOrQualifier((TypedefDecl*) 0) { + TagDecl *PrevDecl, SourceLocation StartL) + : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), + TypedefNameDeclOrQualifier((TypedefNameDecl*) 0) { assert((DK != Enum || TK == TTK_Enum) && "EnumDecl not matched with TTK_Enum"); TagDeclKind = TK; @@ -2068,12 +2268,9 @@ public: SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } - SourceLocation getTagKeywordLoc() const { return TagKeywordLoc; } - void setTagKeywordLoc(SourceLocation TKL) { TagKeywordLoc = TKL; } - /// getInnerLocStart - Return SourceLocation representing start of source /// range ignoring outer template declarations. - virtual SourceLocation getInnerLocStart() const { return TagKeywordLoc; } + SourceLocation getInnerLocStart() const { return getLocStart(); } /// getOuterLocStart - Return SourceLocation representing start of source /// range taking into account any outer template declarations. @@ -2146,11 +2343,11 @@ public: bool isUnion() const { return getTagKind() == TTK_Union; } bool isEnum() const { return getTagKind() == TTK_Enum; } - TypedefDecl *getTypedefForAnonDecl() const { - return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>(); + TypedefNameDecl *getTypedefNameForAnonDecl() const { + return hasExtInfo() ? 0 : TypedefNameDeclOrQualifier.get<TypedefNameDecl*>(); } - void setTypedefForAnonDecl(TypedefDecl *TDD); + void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. @@ -2177,9 +2374,7 @@ public: return getExtInfo()->TemplParamLists[i]; } void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, - TemplateParameterList **TPLists) { - getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); - } + TemplateParameterList **TPLists); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2235,18 +2430,19 @@ class EnumDecl : public TagDecl { NumBitsMask = (1 << NumBitsWidth) - 1 }; - EnumDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL, + EnumDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) - : TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { - assert(Scoped || !ScopedUsingClassTag); - IntegerType = (const Type*)0; - NumNegativeBits = 0; - NumPositiveBits = 0; - IsScoped = Scoped; - IsScopedUsingClassTag = ScopedUsingClassTag; - IsFixed = Fixed; - } + : TagDecl(Enum, TTK_Enum, DC, IdLoc, Id, PrevDecl, StartLoc), + InstantiatedFrom(0) { + assert(Scoped || !ScopedUsingClassTag); + IntegerType = (const Type*)0; + NumNegativeBits = 0; + NumPositiveBits = 0; + IsScoped = Scoped; + IsScopedUsingClassTag = ScopedUsingClassTag; + IsFixed = Fixed; + } public: EnumDecl *getCanonicalDecl() { return cast<EnumDecl>(TagDecl::getCanonicalDecl()); @@ -2263,8 +2459,8 @@ public: } static EnumDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL, EnumDecl *PrevDecl, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed); static EnumDecl *Create(ASTContext &C, EmptyShell Empty); @@ -2326,7 +2522,7 @@ public: return IntegerType.dyn_cast<TypeSourceInfo*>(); } - /// \brief Returns the width in bits requred to store all the + /// \brief Returns the width in bits required to store all the /// non-negative enumerators of this enum. unsigned getNumPositiveBits() const { return NumPositiveBits; @@ -2336,7 +2532,7 @@ public: assert(NumPositiveBits == Num && "can't store this bitcount"); } - /// \brief Returns the width in bits requred to store all the + /// \brief Returns the width in bits required to store all the /// negative enumerators of this enum. These widths include /// the rightmost leading 1; that is: /// @@ -2419,14 +2615,13 @@ class RecordDecl : public TagDecl { protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - RecordDecl *PrevDecl, SourceLocation TKL); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl *PrevDecl); public: static RecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL = SourceLocation(), - RecordDecl* PrevDecl = 0); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, RecordDecl* PrevDecl = 0); static RecordDecl *Create(const ASTContext &C, EmptyShell Empty); const RecordDecl *getPreviousDeclaration() const { @@ -2519,11 +2714,21 @@ private: class FileScopeAsmDecl : public Decl { StringLiteral *AsmString; - FileScopeAsmDecl(DeclContext *DC, SourceLocation L, StringLiteral *asmstring) - : Decl(FileScopeAsm, DC, L), AsmString(asmstring) {} + SourceLocation RParenLoc; + FileScopeAsmDecl(DeclContext *DC, StringLiteral *asmstring, + SourceLocation StartL, SourceLocation EndL) + : Decl(FileScopeAsm, DC, StartL), AsmString(asmstring), RParenLoc(EndL) {} public: static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, StringLiteral *Str); + StringLiteral *Str, SourceLocation AsmLoc, + SourceLocation RParenLoc); + + SourceLocation getAsmLoc() const { return getLocation(); } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + SourceRange getSourceRange() const { + return SourceRange(getAsmLoc(), getRParenLoc()); + } const StringLiteral *getAsmString() const { return AsmString; } StringLiteral *getAsmString() { return AsmString; } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index b35d134d0534..ce48187f3ade 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -62,6 +62,15 @@ public: namespace clang { + /// \brief Captures the result of checking the availability of a + /// declaration. + enum AvailabilityResult { + AR_Available = 0, + AR_NotYetIntroduced, + AR_Deprecated, + AR_Unavailable + }; + /// Decl - This represents one declaration (or definition), e.g. a variable, /// typedef, function, struct, etc. /// @@ -147,9 +156,20 @@ public: IDNS_NonMemberOperator = 0x0400 }; - /// ObjCDeclQualifier - Qualifier used on types in method declarations - /// for remote messaging. They are meant for the arguments though and - /// applied to the Decls (ObjCMethodDecl and ParmVarDecl). + /// ObjCDeclQualifier - 'Qualifiers' written next to the return and + /// parameter types in method declarations. Other than remembering + /// them and mangling them into the method's signature string, these + /// are ignored by the compiler; they are consumed by certain + /// remote-messaging frameworks. + /// + /// in, inout, and out are mutually exclusive and apply only to + /// method parameters. bycopy and byref are mutually exclusive and + /// apply only to method parameters (?). oneway applies only to + /// results. All of these expect their corresponding parameter to + /// have a particular type. None of this is currently enforced by + /// clang. + /// + /// This should be kept in sync with ObjCDeclSpec::ObjCDeclQualifier. enum ObjCDeclQualifier { OBJC_TQ_None = 0x0, OBJC_TQ_In = 0x1, @@ -218,6 +238,12 @@ private: /// required. unsigned Used : 1; + /// \brief Whether this declaration was "referenced". + /// The difference with 'Used' is whether the reference appears in a + /// evaluated context or not, e.g. functions used in uninstantiated templates + /// are regarded as "referenced" but not "used". + unsigned Referenced : 1; + protected: /// Access - Used by C++ decls for the access specifier. // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum @@ -252,7 +278,7 @@ protected: Decl(Kind DK, DeclContext *DC, SourceLocation L) : NextDeclInContext(0), DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), + HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), HasCachedLinkage(0) @@ -262,7 +288,7 @@ protected: Decl(Kind DK, EmptyShell Empty) : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), - HasAttrs(false), Implicit(false), Used(false), + HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), HasCachedLinkage(0) @@ -399,6 +425,57 @@ public: void setUsed(bool U = true) { Used = U; } + /// \brief Whether this declaration was referenced. + bool isReferenced() const; + + void setReferenced(bool R = true) { Referenced = R; } + + /// \brief Determine the availability of the given declaration. + /// + /// This routine will determine the most restrictive availability of + /// the given declaration (e.g., preferring 'unavailable' to + /// 'deprecated'). + /// + /// \param Message If non-NULL and the result is not \c + /// AR_Available, will be set to a (possibly empty) message + /// describing why the declaration has not been introduced, is + /// deprecated, or is unavailable. + AvailabilityResult getAvailability(std::string *Message = 0) const; + + /// \brief Determine whether this declaration is marked 'deprecated'. + /// + /// \param Message If non-NULL and the declaration is deprecated, + /// this will be set to the message describing why the declaration + /// was deprecated (which may be empty). + bool isDeprecated(std::string *Message = 0) const { + return getAvailability(Message) == AR_Deprecated; + } + + /// \brief Determine whether this declaration is marked 'unavailable'. + /// + /// \param Message If non-NULL and the declaration is unavailable, + /// this will be set to the message describing why the declaration + /// was made unavailable (which may be empty). + bool isUnavailable(std::string *Message = 0) const { + return getAvailability(Message) == AR_Unavailable; + } + + /// \brief Determine whether this is a weak-imported symbol. + /// + /// Weak-imported symbols are typically marked with the + /// 'weak_import' attribute, but may also be marked with an + /// 'availability' attribute where we're targing a platform prior to + /// the introduction of this feature. + bool isWeakImported() const; + + /// \brief Determines whether this symbol can be weak-imported, + /// e.g., whether it would be well-formed to add the weak_import + /// attribute. + /// + /// \param IsDefinition Set to \c true to indicate that this + /// declaration cannot be weak-imported because it has a definition. + bool canBeWeakImported(bool &IsDefinition) const; + /// \brief Retrieve the level of precompiled header from which this /// declaration was generated. /// diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 1656a7e9737c..8c819e38781d 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -306,6 +306,37 @@ class CXXRecordDecl : public RecordDecl { /// one pure virtual function, (that can come from a base class). bool Abstract : 1; + /// IsStandardLayout - True when this class has standard layout. + /// + /// C++0x [class]p7. A standard-layout class is a class that: + /// * has no non-static data members of type non-standard-layout class (or + /// array of such types) or reference, + /// * has no virtual functions (10.3) and no virtual base classes (10.1), + /// * has the same access control (Clause 11) for all non-static data members + /// * has no non-standard-layout base classes, + /// * either has no non-static data members in the most derived class and at + /// most one base class with non-static data members, or has no base + /// classes with non-static data members, and + /// * has no base classes of the same type as the first non-static data + /// member. + bool IsStandardLayout : 1; + + /// HasNoNonEmptyBases - True when there are no non-empty base classes. + /// + /// This is a helper bit of state used to implement IsStandardLayout more + /// efficiently. + bool HasNoNonEmptyBases : 1; + + /// HasPrivateFields - True when there are private non-static data members. + bool HasPrivateFields : 1; + + /// HasProtectedFields - True when there are protected non-static data + /// members. + bool HasProtectedFields : 1; + + /// HasPublicFields - True when there are private non-static data members. + bool HasPublicFields : 1; + /// HasTrivialConstructor - True when this class has a trivial constructor. /// /// C++ [class.ctor]p5. A constructor is trivial if it is an @@ -316,31 +347,71 @@ class CXXRecordDecl : public RecordDecl { /// (or array thereof), each such class has a trivial constructor. bool HasTrivialConstructor : 1; + /// HasConstExprNonCopyMoveConstructor - True when this class has at least + /// one constexpr constructor which is neither the copy nor move + /// constructor. + bool HasConstExprNonCopyMoveConstructor : 1; + /// HasTrivialCopyConstructor - True when this class has a trivial copy /// constructor. /// - /// C++ [class.copy]p6. A copy constructor for class X is trivial - /// if it is implicitly declared and if - /// * class X has no virtual functions and no virtual base classes, and - /// * each direct base class of X has a trivial copy constructor, and - /// * for all the nonstatic data members of X that are of class type (or - /// array thereof), each such class type has a trivial copy constructor; - /// otherwise the copy constructor is non-trivial. + /// C++0x [class.copy]p13: + /// A copy/move constructor for class X is trivial if it is neither + /// user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the constructor selected to copy/move each direct base class + /// subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the constructor selected to copy/move that member + /// is trivial; + /// otherwise the copy/move constructor is non-trivial. bool HasTrivialCopyConstructor : 1; + /// HasTrivialMoveConstructor - True when this class has a trivial move + /// constructor. + /// + /// C++0x [class.copy]p13: + /// A copy/move constructor for class X is trivial if it is neither + /// user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the constructor selected to copy/move each direct base class + /// subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the constructor selected to copy/move that member + /// is trivial; + /// otherwise the copy/move constructor is non-trivial. + bool HasTrivialMoveConstructor : 1; + /// HasTrivialCopyAssignment - True when this class has a trivial copy /// assignment operator. /// - /// C++ [class.copy]p11. A copy assignment operator for class X is - /// trivial if it is implicitly declared and if - /// * class X has no virtual functions and no virtual base classes, and - /// * each direct base class of X has a trivial copy assignment operator, and - /// * for all the nonstatic data members of X that are of class type (or - /// array thereof), each such class type has a trivial copy assignment - /// operator; - /// otherwise the copy assignment operator is non-trivial. + /// C++0x [class.copy]p27: + /// A copy/move assignment operator for class X is trivial if it is + /// neither user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the assignment operator selected to copy/move each direct base + /// class subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the assignment operator selected to copy/move + /// that member is trivial; + /// otherwise the copy/move assignment operator is non-trivial. bool HasTrivialCopyAssignment : 1; + /// HasTrivialMoveAssignment - True when this class has a trivial move + /// assignment operator. + /// + /// C++0x [class.copy]p27: + /// A copy/move assignment operator for class X is trivial if it is + /// neither user-provided nor deleted and if + /// -- class X has no virtual functions and no virtual base classes, and + /// -- the assignment operator selected to copy/move each direct base + /// class subobject is trivial, and + /// -- for each non-static data member of X that is of class type (or an + /// array thereof), the assignment operator selected to copy/move + /// that member is trivial; + /// otherwise the copy/move assignment operator is non-trivial. + bool HasTrivialMoveAssignment : 1; + /// HasTrivialDestructor - True when this class has a trivial destructor. /// /// C++ [class.dtor]p3. A destructor is trivial if it is an @@ -351,6 +422,10 @@ class CXXRecordDecl : public RecordDecl { /// type (or array thereof), each such class has a trivial destructor. bool HasTrivialDestructor : 1; + /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least + /// one non-static data member or base class of non literal type. + bool HasNonLiteralTypeFieldsOrBases : 1; + /// ComputedVisibleConversions - True when visible conversion functions are /// already computed and are available. bool ComputedVisibleConversions : 1; @@ -449,9 +524,8 @@ class CXXRecordDecl : public RecordDecl { protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - CXXRecordDecl *PrevDecl, - SourceLocation TKL = SourceLocation()); + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, CXXRecordDecl *PrevDecl); public: /// base_class_iterator - Iterator that traverses the base classes @@ -494,9 +568,8 @@ public: bool hasDefinition() const { return DefinitionData != 0; } static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - SourceLocation TKL = SourceLocation(), - CXXRecordDecl* PrevDecl=0, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); static CXXRecordDecl *Create(const ASTContext &C, EmptyShell Empty); @@ -723,26 +796,58 @@ public: /// which means that the class contains or inherits a pure virtual function. bool isAbstract() const { return data().Abstract; } + /// isStandardLayout - Whether this class has standard layout + /// (C++ [class]p7) + bool isStandardLayout() const { return data().IsStandardLayout; } + // hasTrivialConstructor - Whether this class has a trivial constructor // (C++ [class.ctor]p5) bool hasTrivialConstructor() const { return data().HasTrivialConstructor; } + // hasConstExprNonCopyMoveConstructor - Whether this class has at least one + // constexpr constructor other than the copy or move constructors + bool hasConstExprNonCopyMoveConstructor() const { + return data().HasConstExprNonCopyMoveConstructor; + } + // hasTrivialCopyConstructor - Whether this class has a trivial copy - // constructor (C++ [class.copy]p6) + // constructor (C++ [class.copy]p6, C++0x [class.copy]p13) bool hasTrivialCopyConstructor() const { return data().HasTrivialCopyConstructor; } + // hasTrivialMoveConstructor - Whether this class has a trivial move + // constructor (C++0x [class.copy]p13) + bool hasTrivialMoveConstructor() const { + return data().HasTrivialMoveConstructor; + } + // hasTrivialCopyAssignment - Whether this class has a trivial copy - // assignment operator (C++ [class.copy]p11) + // assignment operator (C++ [class.copy]p11, C++0x [class.copy]p27) bool hasTrivialCopyAssignment() const { return data().HasTrivialCopyAssignment; } + // hasTrivialMoveAssignment - Whether this class has a trivial move + // assignment operator (C++0x [class.copy]p27) + bool hasTrivialMoveAssignment() const { + return data().HasTrivialMoveAssignment; + } + // hasTrivialDestructor - Whether this class has a trivial destructor // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } + // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal type + // non-static data member or base class. + bool hasNonLiteralTypeFieldsOrBases() const { + return data().HasNonLiteralTypeFieldsOrBases; + } + + // isTriviallyCopyable - Whether this class is considered trivially copyable + // (C++0x [class]p5). + bool isTriviallyCopyable() const; + /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// @@ -1034,20 +1139,27 @@ public: /// struct/union/class. class CXXMethodDecl : public FunctionDecl { protected: - CXXMethodDecl(Kind DK, CXXRecordDecl *RD, + CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic, StorageClass SCAsWritten, bool isInline) - : FunctionDecl(DK, RD, NameInfo, T, TInfo, (isStatic ? SC_Static : SC_None), - SCAsWritten, isInline) {} + bool isStatic, StorageClass SCAsWritten, bool isInline, + SourceLocation EndLocation) + : FunctionDecl(DK, RD, StartLoc, NameInfo, T, TInfo, + (isStatic ? SC_Static : SC_None), + SCAsWritten, isInline) { + if (EndLocation.isValid()) + setRangeEnd(EndLocation); + } public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isStatic = false, - StorageClass SCAsWritten = SC_None, - bool isInline = false); + bool isStatic, + StorageClass SCAsWritten, + bool isInline, + SourceLocation EndLocation); bool isStatic() const { return getStorageClass() == SC_Static; } bool isInstance() const { return !isStatic(); } @@ -1148,13 +1260,16 @@ public: /// @endcode class CXXCtorInitializer { /// \brief Either the base class name (stored as a TypeSourceInfo*), an normal - /// field (FieldDecl) or an anonymous field (IndirectFieldDecl*) being - /// initialized. - llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> + /// field (FieldDecl), anonymous field (IndirectFieldDecl*), or target + /// constructor (CXXConstructorDecl*) being initialized. + llvm::PointerUnion4<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *, + CXXConstructorDecl *> Initializee; /// \brief The source location for the field name or, for a base initializer - /// pack expansion, the location of the ellipsis. + /// pack expansion, the location of the ellipsis. In the case of a delegating + /// constructor, it will still include the type's source location as the + /// Initializee points to the CXXConstructorDecl (to allow loop detection). SourceLocation MemberOrEllipsisLocation; /// \brief The argument used to initialize the base or member, which may @@ -1199,11 +1314,17 @@ public: SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); + /// CXXCtorInitializer - Creates a new anonymous field initializer. explicit CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); + /// CXXCtorInitializer - Creates a new delegating Initializer. + explicit + CXXCtorInitializer(ASTContext &Context, SourceLocation D, SourceLocation L, + CXXConstructorDecl *Target, Expr *Init, SourceLocation R); + /// \brief Creates a new member initializer that optionally contains /// array indices used to describe an elementwise initialization. static CXXCtorInitializer *Create(ASTContext &Context, FieldDecl *Member, @@ -1227,6 +1348,12 @@ public: return Initializee.is<IndirectFieldDecl*>(); } + /// isDelegatingInitializer - Returns true when this initializer is creating + /// a delegating constructor. + bool isDelegatingInitializer() const { + return Initializee.is<CXXConstructorDecl *>(); + } + /// \brief Determine whether this initializer is a pack expansion. bool isPackExpansion() const { return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); @@ -1284,6 +1411,13 @@ public: return 0; } + CXXConstructorDecl *getTargetConstructor() const { + if (isDelegatingInitializer()) + return Initializee.get<CXXConstructorDecl*>(); + else + return 0; + } + SourceLocation getMemberLocation() const { return MemberOrEllipsisLocation; } @@ -1373,12 +1507,13 @@ class CXXConstructorDecl : public CXXMethodDecl { CXXCtorInitializer **CtorInitializers; unsigned NumCtorInitializers; - CXXConstructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, SourceLocation()), IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), CtorInitializers(0), NumCtorInitializers(0) { setImplicit(isImplicitlyDeclared); @@ -1387,6 +1522,7 @@ class CXXConstructorDecl : public CXXMethodDecl { public: static CXXConstructorDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicit, @@ -1472,6 +1608,23 @@ public: void setCtorInitializers(CXXCtorInitializer ** initializers) { CtorInitializers = initializers; } + + /// isDelegatingConstructor - Whether this constructor is a + /// delegating constructor + bool isDelegatingConstructor() const { + return (getNumCtorInitializers() == 1) && + CtorInitializers[0]->isDelegatingInitializer(); + } + + /// getTargetConstructor - When this constructor delegates to + /// another, retrieve the target + CXXConstructorDecl *getTargetConstructor() const { + if (isDelegatingConstructor()) + return CtorInitializers[0]->getTargetConstructor(); + else + return 0; + } + /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to /// default-initialize a class of this type. @@ -1508,8 +1661,11 @@ public: /// \brief Determine whether this constructor is a move constructor /// (C++0x [class.copy]p3), which can be used to move values of the class. - bool isMoveConstructor() const; - + bool isMoveConstructor() const { + unsigned TypeQuals = 0; + return isMoveConstructor(TypeQuals); + } + /// \brief Determine whether this is a copy or move constructor. /// /// \param TypeQuals Will be set to the type qualifiers on the reference @@ -1567,11 +1723,12 @@ class CXXDestructorDecl : public CXXMethodDecl { FunctionDecl *OperatorDelete; - CXXDestructorDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, SourceLocation()), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -1579,6 +1736,7 @@ class CXXDestructorDecl : public CXXMethodDecl { public: static CXXDestructorDecl *Create(ASTContext& C, EmptyShell Empty); static CXXDestructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo* TInfo, bool isInline, @@ -1629,19 +1787,23 @@ class CXXConversionDecl : public CXXMethodDecl { /// explicitly wrote a cast. This is a C++0x feature. bool IsExplicitSpecified : 1; - CXXConversionDecl(CXXRecordDecl *RD, const DeclarationNameInfo &NameInfo, + CXXConversionDecl(CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicitSpecified) - : CXXMethodDecl(CXXConversion, RD, NameInfo, T, TInfo, false, - SC_None, isInline), + bool isInline, bool isExplicitSpecified, + SourceLocation EndLocation) + : CXXMethodDecl(CXXConversion, RD, StartLoc, NameInfo, T, TInfo, false, + SC_None, isInline, EndLocation), IsExplicitSpecified(isExplicitSpecified) { } public: static CXXConversionDecl *Create(ASTContext &C, EmptyShell Empty); static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, + SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, - bool isInline, bool isExplicit); + bool isInline, bool isExplicit, + SourceLocation EndLocation); /// IsExplicitSpecified - Whether this conversion function declaration is /// marked "explicit", meaning that it can only be applied when the user @@ -1688,33 +1850,48 @@ public: private: /// Language - The language for this linkage specification. LanguageIDs Language; + /// ExternLoc - The source location for the extern keyword. + SourceLocation ExternLoc; + /// RBraceLoc - The source location for the right brace (if valid). + SourceLocation RBraceLoc; - /// HadBraces - Whether this linkage specification had curly braces or not. - bool HadBraces : 1; - - LinkageSpecDecl(DeclContext *DC, SourceLocation L, LanguageIDs lang, - bool Braces) - : Decl(LinkageSpec, DC, L), - DeclContext(LinkageSpec), Language(lang), HadBraces(Braces) { } + LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, + SourceLocation LangLoc, LanguageIDs lang, + SourceLocation RBLoc) + : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec), + Language(lang), ExternLoc(ExternLoc), RBraceLoc(RBLoc) { } public: static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, LanguageIDs Lang, - bool Braces); + SourceLocation ExternLoc, + SourceLocation LangLoc, LanguageIDs Lang, + SourceLocation RBraceLoc = SourceLocation()); /// \brief Return the language specified by this linkage specification. LanguageIDs getLanguage() const { return Language; } - /// \brief Set the language specified by this linkage specification. void setLanguage(LanguageIDs L) { Language = L; } /// \brief Determines whether this linkage specification had braces in /// its syntactic form. - bool hasBraces() const { return HadBraces; } + bool hasBraces() const { return RBraceLoc.isValid(); } - /// \brief Set whether this linkage specification has braces in its - /// syntactic form. - void setHasBraces(bool B) { HadBraces = B; } + SourceLocation getExternLoc() const { return ExternLoc; } + SourceLocation getRBraceLoc() const { return RBraceLoc; } + void setExternLoc(SourceLocation L) { ExternLoc = L; } + void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + + SourceLocation getLocEnd() const { + if (hasBraces()) + return getRBraceLoc(); + // No braces: get the end location of the (only) declaration in context + // (if present). + return decls_empty() ? getLocation() : decls_begin()->getLocEnd(); + } + + SourceRange getSourceRange() const { + return SourceRange(ExternLoc, getLocEnd()); + } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const LinkageSpecDecl *D) { return true; } @@ -2023,12 +2200,6 @@ public: return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } @@ -2154,12 +2325,6 @@ public: return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } @@ -2205,15 +2370,15 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, IdentifierInfo *TargetName) - : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), - UsingLocation(UsingLoc), TypenameLocation(TypenameLoc), - QualifierLoc(QualifierLoc) { } + : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName, + UsingLoc), + TypenameLocation(TypenameLoc), QualifierLoc(QualifierLoc) { } friend class ASTDeclReader; public: /// \brief Returns the source location of the 'using' keyword. - SourceLocation getUsingLoc() const { return UsingLocation; } + SourceLocation getUsingLoc() const { return getLocStart(); } /// \brief Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } @@ -2227,22 +2392,11 @@ public: return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the source range of the nested-name-specifier - /// that qualifies the name. - SourceRange getQualifierRange() const { - return QualifierLoc.getSourceRange(); - } - - // FIXME: DeclarationNameInfo static UnresolvedUsingTypenameDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation UsingLoc, SourceLocation TypenameLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TargetNameLoc, DeclarationName TargetName); - SourceRange getSourceRange() const { - return SourceRange(UsingLocation, getLocation()); - } - static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingTypenameDecl *D) { return true; } static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } @@ -2252,15 +2406,19 @@ public: class StaticAssertDecl : public Decl { Expr *AssertExpr; StringLiteral *Message; + SourceLocation RParenLoc; - StaticAssertDecl(DeclContext *DC, SourceLocation L, - Expr *assertexpr, StringLiteral *message) - : Decl(StaticAssert, DC, L), AssertExpr(assertexpr), Message(message) { } + StaticAssertDecl(DeclContext *DC, SourceLocation StaticAssertLoc, + Expr *assertexpr, StringLiteral *message, + SourceLocation RParenLoc) + : Decl(StaticAssert, DC, StaticAssertLoc), AssertExpr(assertexpr), + Message(message), RParenLoc(RParenLoc) { } public: static StaticAssertDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, Expr *AssertExpr, - StringLiteral *Message); + SourceLocation StaticAssertLoc, + Expr *AssertExpr, StringLiteral *Message, + SourceLocation RParenLoc); Expr *getAssertExpr() { return AssertExpr; } const Expr *getAssertExpr() const { return AssertExpr; } @@ -2268,6 +2426,13 @@ public: StringLiteral *getMessage() { return Message; } const StringLiteral *getMessage() const { return Message; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation L) { RParenLoc = L; } + + SourceRange getSourceRange() const { + return SourceRange(getLocation(), getRParenLoc()); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(StaticAssertDecl *D) { return true; } static bool classofKind(Kind K) { return K == StaticAssert; } diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 20d6da19b8ca..b84e5bba86b7 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -98,6 +98,17 @@ public: return FriendLoc; } + /// Retrieves the source range for the friend declaration. + SourceRange getSourceRange() const { + /* FIXME: consider the case of templates wrt start of range. */ + if (NamedDecl *ND = getFriendDecl()) + return SourceRange(getFriendLoc(), ND->getLocEnd()); + else if (TypeSourceInfo *TInfo = getFriendType()) + return SourceRange(getFriendLoc(), TInfo->getTypeLoc().getEndLoc()); + else + return SourceRange(getFriendLoc(), getLocation()); + } + /// Determines if this friend kind is unsupported. bool isUnsupportedFriend() const { return UnsupportedFriend; diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index b3ca474fcc19..0a4d864cd867 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -112,17 +112,20 @@ class ObjCMethodDecl : public NamedDecl, public DeclContext { public: enum ImplementationControl { None, Required, Optional }; private: - /// Bitfields must be first fields in this class so they pack with those - /// declared in class Decl. + // The conventional meaning of this method; an ObjCMethodFamily. + // This is not serialized; instead, it is computed on demand and + // cached. + mutable unsigned Family : ObjCMethodFamilyBitWidth; + /// instance (true) or class (false) method. - bool IsInstance : 1; - bool IsVariadic : 1; + unsigned IsInstance : 1; + unsigned IsVariadic : 1; // Synthesized declaration method for a property setter/getter - bool IsSynthesized : 1; + unsigned IsSynthesized : 1; // Method has a definition. - bool IsDefined : 1; + unsigned IsDefined : 1; // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum /// @required/@optional @@ -170,7 +173,7 @@ private: ImplementationControl impControl = None, unsigned numSelectorArgs = 0) : NamedDecl(ObjCMethod, contextDecl, beginLoc, SelInfo), - DeclContext(ObjCMethod), + DeclContext(ObjCMethod), Family(InvalidObjCMethodFamily), IsInstance(isInstance), IsVariadic(isVariadic), IsSynthesized(isSynthesized), IsDefined(isDefined), @@ -279,6 +282,9 @@ public: ImplicitParamDecl * getCmdDecl() const { return CmdDecl; } void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; } + /// Determines the family of this method. + ObjCMethodFamily getMethodFamily() const; + bool isInstanceMethod() const { return IsInstance; } void setInstanceMethod(bool isInst) { IsInstance = isInst; } bool isVariadic() const { return IsVariadic; } @@ -453,7 +459,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl { /// /// Categories are stored as a linked list in the AST, since the categories /// and class extensions come long after the initial interface declaration, - /// and we avoid dynamically-resized arrays in the AST whereever possible. + /// and we avoid dynamically-resized arrays in the AST wherever possible. ObjCCategoryDecl *CategoryList; /// IvarList - List of all ivars defined by this class; including class @@ -701,15 +707,18 @@ public: }; private: - ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation L, IdentifierInfo *Id, + ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, bool synthesized) - : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), - NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} + : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, + /*Mutable=*/false), + NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, - SourceLocation L, IdentifierInfo *Id, QualType T, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW = NULL, bool synthesized=false); @@ -753,17 +762,18 @@ private: /// @defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { private: - ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, Expr *BW) - : FieldDecl(ObjCAtDefsField, DC, L, Id, T, + : FieldDecl(ObjCAtDefsField, DC, StartLoc, IdLoc, Id, T, /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? BW, /*Mutable=*/false) {} public: static ObjCAtDefsFieldDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - IdentifierInfo *Id, QualType T, - Expr *BW); + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + QualType T, Expr *BW); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -773,7 +783,7 @@ public: /// ObjCProtocolDecl - Represents a protocol declaration. ObjC protocols /// declare a pure abstract type (i.e no instance variables are permitted). -/// Protocols orginally drew inspiration from C++ pure virtual functions (a C++ +/// Protocols originally drew inspiration from C++ pure virtual functions (a C++ /// feature with nice semantics and lousy syntax:-). Here is an example: /// /// @protocol NSDraggingInfo <refproto1, refproto2> diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index f41859c85790..ddbe344cdffd 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -771,9 +771,20 @@ protected: /// \brief Data that is common to all of the declarations of a given /// function template. struct Common : CommonBase { + Common() : InjectedArgs(0) { } + /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + + /// \brief The set of "injected" template arguments used within this + /// function template. + /// + /// This pointer refers to the template arguments (there are as + /// many template arguments as template parameaters) for the function + /// template, and is allocated lazily, since most function templates do not + /// require the use of this information. + TemplateArgument *InjectedArgs; }; FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -793,6 +804,13 @@ protected: llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { return getCommonPtr()->Specializations; } + + /// \brief Add a specialization of this function template. + /// + /// \param InsertPos Insert position in the FoldingSet, must have been + /// retrieved by an earlier call to findSpecialization(). + void addSpecialization(FunctionTemplateSpecializationInfo* Info, + void *InsertPos); public: /// Get the underlying function declaration of the template. @@ -844,13 +862,25 @@ public: return makeSpecIterator(getSpecializations(), true); } - /// Create a template function node. + /// \brief Retrieve the "injected" template arguments that correspond to the + /// template parameters of this function template. + /// + /// Although the C++ standard has no notion of the "injected" template + /// arguments for a function template, the notion is convenient when + /// we need to perform substitutions inside the definition of a function + /// template. + std::pair<const TemplateArgument *, unsigned> getInjectedTemplateArgs(); + + /// \brief Create a function template node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl); + /// \brief Create an empty function template node. + static FunctionTemplateDecl *Create(ASTContext &C, EmptyShell); + // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FunctionTemplateDecl *D) { return true; } @@ -915,25 +945,23 @@ class TemplateTypeParmDecl : public TypeDecl { /// default argument. bool InheritedDefault : 1; - /// \brief Whether this is a parameter pack. - bool ParameterPack : 1; - /// \brief The default template argument, if any. TypeSourceInfo *DefaultArgument; - TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - bool Typename, QualType Type, bool ParameterPack) - : TypeDecl(TemplateTypeParm, DC, L, Id), Typename(Typename), - InheritedDefault(false), ParameterPack(ParameterPack), DefaultArgument() { - TypeForDecl = Type.getTypePtrOrNull(); - } + TemplateTypeParmDecl(DeclContext *DC, SourceLocation KeyLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + bool Typename) + : TypeDecl(TemplateTypeParm, DC, IdLoc, Id, KeyLoc), Typename(Typename), + InheritedDefault(false), DefaultArgument() { } /// Sema creates these on the stack during auto type deduction. friend class Sema; public: static TemplateTypeParmDecl *Create(const ASTContext &C, DeclContext *DC, - SourceLocation L, unsigned D, unsigned P, + SourceLocation KeyLoc, + SourceLocation NameLoc, + unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack); static TemplateTypeParmDecl *Create(const ASTContext &C, EmptyShell Empty); @@ -978,9 +1006,6 @@ public: /// the 'typename' or 'class' keyword. void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; } - /// \brief Set whether this is a parameter pack. - void setParameterPack(bool isParamPack) { ParameterPack = isParamPack; } - /// \brief Retrieve the depth of the template parameter. unsigned getDepth() const; @@ -988,7 +1013,9 @@ public: unsigned getIndex() const; /// \brief Returns whether this is a parameter pack. - bool isParameterPack() const { return ParameterPack; } + bool isParameterPack() const; + + SourceRange getSourceRange() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1021,17 +1048,19 @@ class NonTypeTemplateParmDecl /// \brief The number of types in an expanded parameter pack. unsigned NumExpandedTypes; - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, bool ParameterPack, TypeSourceInfo *TInfo) - : DeclaratorDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo), + : DeclaratorDecl(NonTypeTemplateParm, DC, IdLoc, Id, T, TInfo, StartLoc), TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false), ParameterPack(ParameterPack), ExpandedParameterPack(false), NumExpandedTypes(0) { } - NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, + NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, const QualType *ExpandedTypes, unsigned NumExpandedTypes, @@ -1041,13 +1070,14 @@ class NonTypeTemplateParmDecl public: static NonTypeTemplateParmDecl * - Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, bool ParameterPack, - TypeSourceInfo *TInfo); + Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, + QualType T, bool ParameterPack, TypeSourceInfo *TInfo); static NonTypeTemplateParmDecl * - Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, + QualType T, TypeSourceInfo *TInfo, const QualType *ExpandedTypes, unsigned NumExpandedTypes, TypeSourceInfo **ExpandedTInfos); @@ -1057,7 +1087,6 @@ public: using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; - SourceLocation getInnerLocStart() const; SourceRange getSourceRange() const; /// \brief Determine whether this template parameter has a default @@ -1316,7 +1345,8 @@ class ClassTemplateSpecializationDecl protected: ClassTemplateSpecializationDecl(ASTContext &Context, Kind DK, TagKind TK, - DeclContext *DC, SourceLocation L, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, @@ -1326,7 +1356,8 @@ protected: public: static ClassTemplateSpecializationDecl * - Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, @@ -1488,7 +1519,7 @@ public: return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } - SourceLocation getInnerLocStart() const { return getTemplateKeywordLoc(); } + SourceRange getSourceRange() const; void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext()); @@ -1544,7 +1575,9 @@ class ClassTemplatePartialSpecializationDecl InstantiatedFromMember; ClassTemplatePartialSpecializationDecl(ASTContext &Context, TagKind TK, - DeclContext *DC, SourceLocation L, + DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, @@ -1552,14 +1585,7 @@ class ClassTemplatePartialSpecializationDecl TemplateArgumentLoc *ArgInfos, unsigned NumArgInfos, ClassTemplatePartialSpecializationDecl *PrevDecl, - unsigned SequenceNumber) - : ClassTemplateSpecializationDecl(Context, - ClassTemplatePartialSpecialization, - TK, DC, L, SpecializedTemplate, - Args, NumArgs, PrevDecl), - TemplateParams(Params), ArgsAsWritten(ArgInfos), - NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), - InstantiatedFromMember(0, false) { } + unsigned SequenceNumber); ClassTemplatePartialSpecializationDecl() : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization), @@ -1569,7 +1595,8 @@ class ClassTemplatePartialSpecializationDecl public: static ClassTemplatePartialSpecializationDecl * - Create(ASTContext &Context, TagKind TK,DeclContext *DC, SourceLocation L, + Create(ASTContext &Context, TagKind TK,DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, @@ -1742,6 +1769,10 @@ protected: TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } + ClassTemplateDecl(EmptyShell Empty) + : RedeclarableTemplateDecl(ClassTemplate, 0, SourceLocation(), + DeclarationName(), 0, 0) { } + CommonBase *newCommon(ASTContext &C); Common *getCommonPtr() { @@ -1768,6 +1799,9 @@ public: NamedDecl *Decl, ClassTemplateDecl *PrevDecl); + /// Create an empty class template node. + static ClassTemplateDecl *Create(ASTContext &C, EmptyShell); + /// \brief Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. ClassTemplateSpecializationDecl * diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index 035f57c12ea7..bab1606dcee4 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -37,7 +37,8 @@ public: // other sub-expressions). void VisitDeclRefExpr(DeclRefExpr *E) { } void VisitOffsetOfExpr(OffsetOfExpr *E) { } - void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) { } + void VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *E) { } + void VisitExpressionTraitExpr(ExpressionTraitExpr *E) { } void VisitBlockExpr(BlockExpr *E) { } void VisitCXXUuidofExpr(CXXUuidofExpr *E) { } void VisitCXXNoexceptExpr(CXXNoexceptExpr *E) { } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 95bfad5a16c2..5f2d144eb544 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -21,12 +21,12 @@ #include "clang/AST/OperationKinds.h" #include "clang/AST/ASTVector.h" #include "clang/AST/UsuallyTinyPtrVector.h" +#include "clang/Basic/TypeTraits.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include <cctype> -#include <vector> namespace clang { class ASTContext; @@ -172,6 +172,7 @@ public: LV_IncompleteVoidType, LV_DuplicateVectorComponents, LV_InvalidExpression, + LV_InvalidMessageExpression, LV_MemberFunction, LV_SubObjCPropertySetting, LV_ClassTemporary @@ -203,6 +204,7 @@ public: MLV_NoSetterProperty, MLV_MemberFunction, MLV_SubObjCPropertySetting, + MLV_InvalidMessageExpression, MLV_ClassTemporary }; isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, @@ -218,10 +220,12 @@ public: CL_XValue, CL_Function, // Functions cannot be lvalues in C. CL_Void, // Void cannot be an lvalue in C. + CL_AddressableVoid, // Void expression whose address can be taken in C. CL_DuplicateVectorComponents, // A vector shuffle with dupes. CL_MemberFunction, // An expression referring to a member function CL_SubObjCPropertySetting, CL_ClassTemporary, // A prvalue of class type + CL_ObjCMessageRValue, // ObjC message is an rvalue CL_PRValue // A prvalue for any other reason, of any other type }; /// \brief The results of modification testing. @@ -482,6 +486,11 @@ public: /// \brief Returns true if this expression is a bound member function. bool isBoundMemberFunction(ASTContext &Ctx) const; + /// \brief Given an expression of bound-member type, find the type + /// of the member. Returns null if this is an *overloaded* bound + /// member expression. + static QualType findBoundMemberType(const Expr *expr); + /// \brief Result type of CanThrow(). enum CanThrowResult { CT_Cannot, @@ -536,6 +545,9 @@ public: /// temporary object of the given class type. bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; + /// \brief Whether this expression is an implicit reference to 'this' in C++. + bool isImplicitCXXThis() const; + const Expr *IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); } @@ -618,16 +630,6 @@ public: static bool classof(const OpaqueValueExpr *) { return true; } }; -/// \brief Represents the qualifier that may precede a C++ name, e.g., the -/// "std::" in "std::sort". -struct NameQualifier { - /// \brief The nested name specifier. - NestedNameSpecifier *NNS; - - /// \brief The source range covered by the nested name specifier. - SourceRange Range; -}; - /// \brief Represents an explicit template argument list in C++, e.g., /// the "<int>" in "sort<int>". struct ExplicitTemplateArgumentList { @@ -659,95 +661,118 @@ struct ExplicitTemplateArgumentList { static std::size_t sizeFor(unsigned NumTemplateArgs); static std::size_t sizeFor(const TemplateArgumentListInfo &List); }; - -/// DeclRefExpr - [C99 6.5.1p2] - A reference to a declared variable, function, -/// enum, etc. + +/// \brief A reference to a declared variable, function, enum, etc. +/// [C99 6.5.1p2] +/// +/// This encodes all the information about how a declaration is referenced +/// within an expression. +/// +/// There are several optional constructs attached to DeclRefExprs only when +/// they apply in order to conserve memory. These are laid out past the end of +/// the object, and flags in the DeclRefExprBitfield track whether they exist: +/// +/// DeclRefExprBits.HasQualifier: +/// Specifies when this declaration reference expression has a C++ +/// nested-name-specifier. +/// DeclRefExprBits.HasFoundDecl: +/// Specifies when this declaration reference expression has a record of +/// a NamedDecl (different from the referenced ValueDecl) which was found +/// during name lookup and/or overload resolution. +/// DeclRefExprBits.HasExplicitTemplateArgs: +/// Specifies when this declaration reference expression has an explicit +/// C++ template argument list. class DeclRefExpr : public Expr { - enum { - // Flag on DecoratedD that specifies when this declaration reference - // expression has a C++ nested-name-specifier. - HasQualifierFlag = 0x01, - // Flag on DecoratedD that specifies when this declaration reference - // expression has an explicit C++ template argument list. - HasExplicitTemplateArgumentListFlag = 0x02 - }; - - // DecoratedD - The declaration that we are referencing, plus two bits to - // indicate whether (1) the declaration's name was explicitly qualified and - // (2) the declaration's name was followed by an explicit template - // argument list. - llvm::PointerIntPair<ValueDecl *, 2> DecoratedD; + /// \brief The declaration that we are referencing. + ValueDecl *D; - // Loc - The location of the declaration name itself. + /// \brief The location of the declaration name itself. SourceLocation Loc; - /// DNLoc - Provides source/type location info for the - /// declaration name embedded in DecoratedD. + /// \brief Provides source/type location info for the declaration name + /// embedded in D. DeclarationNameLoc DNLoc; - /// \brief Retrieve the qualifier that preceded the declaration name, if any. - NameQualifier *getNameQualifier() { - if ((DecoratedD.getInt() & HasQualifierFlag) == 0) - return 0; - - return reinterpret_cast<NameQualifier *> (this + 1); + /// \brief Helper to retrieve the optional NestedNameSpecifierLoc. + NestedNameSpecifierLoc &getInternalQualifierLoc() { + assert(hasQualifier()); + return *reinterpret_cast<NestedNameSpecifierLoc *>(this + 1); } - - /// \brief Retrieve the qualifier that preceded the member name, if any. - const NameQualifier *getNameQualifier() const { - return const_cast<DeclRefExpr *>(this)->getNameQualifier(); + + /// \brief Helper to retrieve the optional NestedNameSpecifierLoc. + const NestedNameSpecifierLoc &getInternalQualifierLoc() const { + return const_cast<DeclRefExpr *>(this)->getInternalQualifierLoc(); } - DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - ValueDecl *D, SourceLocation NameLoc, - const TemplateArgumentListInfo *TemplateArgs, - QualType T, ExprValueKind VK); + /// \brief Test whether there is a distinct FoundDecl attached to the end of + /// this DRE. + bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } - DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + /// \brief Helper to retrieve the optional NamedDecl through which this + /// reference occured. + NamedDecl *&getInternalFoundDecl() { + assert(hasFoundDecl()); + if (hasQualifier()) + return *reinterpret_cast<NamedDecl **>(&getInternalQualifierLoc() + 1); + return *reinterpret_cast<NamedDecl **>(this + 1); + } + + /// \brief Helper to retrieve the optional NamedDecl through which this + /// reference occured. + NamedDecl *getInternalFoundDecl() const { + return const_cast<DeclRefExpr *>(this)->getInternalFoundDecl(); + } + + DeclRefExpr(NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, const DeclarationNameInfo &NameInfo, + NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK); /// \brief Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } - + /// \brief Computes the type- and value-dependence flags for this /// declaration reference expression. void computeDependence(); public: - DeclRefExpr(ValueDecl *d, QualType t, ExprValueKind VK, SourceLocation l) : - Expr(DeclRefExprClass, t, VK, OK_Ordinary, false, false, false), - DecoratedD(d, 0), Loc(l) { + DeclRefExpr(ValueDecl *D, QualType T, ExprValueKind VK, SourceLocation L) + : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false), + D(D), Loc(L) { + DeclRefExprBits.HasQualifier = 0; + DeclRefExprBits.HasExplicitTemplateArgs = 0; + DeclRefExprBits.HasFoundDecl = 0; computeDependence(); } static DeclRefExpr *Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, SourceLocation NameLoc, QualType T, ExprValueKind VK, + NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0); static DeclRefExpr *Create(ASTContext &Context, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *D, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, + NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0); /// \brief Construct an empty declaration reference expression. static DeclRefExpr *CreateEmpty(ASTContext &Context, - bool HasQualifier, + bool HasQualifier, + bool HasFoundDecl, bool HasExplicitTemplateArgs, unsigned NumTemplateArgs); - - ValueDecl *getDecl() { return DecoratedD.getPointer(); } - const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } - void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); } + + ValueDecl *getDecl() { return D; } + const ValueDecl *getDecl() const { return D; } + void setDecl(ValueDecl *NewD) { D = NewD; } DeclarationNameInfo getNameInfo() const { return DeclarationNameInfo(getDecl()->getDeclName(), Loc, DNLoc); @@ -759,43 +784,62 @@ public: /// \brief Determine whether this declaration reference was preceded by a /// C++ nested-name-specifier, e.g., \c N::foo. - bool hasQualifier() const { return DecoratedD.getInt() & HasQualifierFlag; } - - /// \brief If the name was qualified, retrieves the source range of - /// the nested-name-specifier that precedes the name. Otherwise, - /// returns an empty source range. - SourceRange getQualifierRange() const { - if (!hasQualifier()) - return SourceRange(); - - return getNameQualifier()->Range; - } - - /// \brief If the name was qualified, retrieves the nested-name-specifier + bool hasQualifier() const { return DeclRefExprBits.HasQualifier; } + + /// \brief If the name was qualified, retrieves the nested-name-specifier /// that precedes the name. Otherwise, returns NULL. NestedNameSpecifier *getQualifier() const { if (!hasQualifier()) return 0; - - return getNameQualifier()->NNS; + + return getInternalQualifierLoc().getNestedNameSpecifier(); } - + + /// \brief If the name was qualified, retrieves the nested-name-specifier + /// that precedes the name, with source-location information. + NestedNameSpecifierLoc getQualifierLoc() const { + if (!hasQualifier()) + return NestedNameSpecifierLoc(); + + return getInternalQualifierLoc(); + } + + /// \brief Get the NamedDecl through which this reference occured. + /// + /// This Decl may be different from the ValueDecl actually referred to in the + /// presence of using declarations, etc. It always returns non-NULL, and may + /// simple return the ValueDecl when appropriate. + NamedDecl *getFoundDecl() { + return hasFoundDecl() ? getInternalFoundDecl() : D; + } + + /// \brief Get the NamedDecl through which this reference occurred. + /// See non-const variant. + const NamedDecl *getFoundDecl() const { + return hasFoundDecl() ? getInternalFoundDecl() : D; + } + + /// \brief Determines whether this declaration reference was followed by an + /// explict template argument list. bool hasExplicitTemplateArgs() const { - return (DecoratedD.getInt() & HasExplicitTemplateArgumentListFlag); + return DeclRefExprBits.HasExplicitTemplateArgs; } - + /// \brief Retrieve the explicit template argument list that followed the /// member template name. ExplicitTemplateArgumentList &getExplicitTemplateArgs() { assert(hasExplicitTemplateArgs()); + if (hasFoundDecl()) + return *reinterpret_cast<ExplicitTemplateArgumentList *>( + &getInternalFoundDecl() + 1); - if ((DecoratedD.getInt() & HasQualifierFlag) == 0) - return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); - - return *reinterpret_cast<ExplicitTemplateArgumentList *>( - getNameQualifier() + 1); + if (hasQualifier()) + return *reinterpret_cast<ExplicitTemplateArgumentList *>( + &getInternalQualifierLoc() + 1); + + return *reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); } - + /// \brief Retrieve the explicit template argument list that followed the /// member template name. const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { @@ -809,50 +853,50 @@ public: if (!hasExplicitTemplateArgs()) return 0; return &getExplicitTemplateArgs(); } - + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) getExplicitTemplateArgs().copyInto(List); } - + /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { if (!hasExplicitTemplateArgs()) return SourceLocation(); - + return getExplicitTemplateArgs().LAngleLoc; } - + /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; - + return getExplicitTemplateArgs().getTemplateArgs(); } - + /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { if (!hasExplicitTemplateArgs()) return 0; - + return getExplicitTemplateArgs().NumTemplateArgs; } - + /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { if (!hasExplicitTemplateArgs()) return SourceLocation(); - + return getExplicitTemplateArgs().RAngleLoc; } - + static bool classof(const Stmt *T) { return T->getStmtClass() == DeclRefExprClass; } @@ -860,7 +904,7 @@ public: // Iterators child_range children() { return child_range(); } - + friend class ASTStmtReader; friend class ASTStmtWriter; }; @@ -1133,9 +1177,12 @@ public: /// In this case, getByteLength() will return 6, but the string literal will /// have type "char[2]". class StringLiteral : public Expr { + friend class ASTStmtReader; + const char *StrData; unsigned ByteLength; bool IsWide; + bool IsPascal; unsigned NumConcatenated; SourceLocation TokLocs[1]; @@ -1146,14 +1193,15 @@ public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. static StringLiteral *Create(ASTContext &C, const char *StrData, - unsigned ByteLength, bool Wide, QualType Ty, + unsigned ByteLength, bool Wide, bool Pascal, + QualType Ty, const SourceLocation *Loc, unsigned NumStrs); /// Simple constructor for string literals made from one token. static StringLiteral *Create(ASTContext &C, const char *StrData, - unsigned ByteLength, - bool Wide, QualType Ty, SourceLocation Loc) { - return Create(C, StrData, ByteLength, Wide, Ty, &Loc, 1); + unsigned ByteLength, bool Wide, + bool Pascal, QualType Ty, SourceLocation Loc) { + return Create(C, StrData, ByteLength, Wide, Pascal, Ty, &Loc, 1); } /// \brief Construct an empty string literal. @@ -1169,8 +1217,8 @@ public: void setString(ASTContext &C, llvm::StringRef Str); bool isWide() const { return IsWide; } - void setWide(bool W) { IsWide = W; } - + bool isPascal() const { return IsPascal; } + bool containsNonAsciiOrNull() const { llvm::StringRef Str = getString(); for (unsigned i = 0, e = Str.size(); i != e; ++i) @@ -1458,7 +1506,7 @@ public: /// the square brackets. For a field or identifier node, the source range /// contains the location of the period (if there is one) and the /// identifier. - SourceRange getRange() const { return Range; } + SourceRange getSourceRange() const { return Range; } }; private: @@ -1556,10 +1604,11 @@ public: } }; -/// SizeOfAlignOfExpr - [C99 6.5.3.4] - This is for sizeof/alignof, both of -/// types and expressions. -class SizeOfAlignOfExpr : public Expr { - bool isSizeof : 1; // true if sizeof, false if alignof. +/// UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) +/// expression operand. Used for sizeof/alignof (C99 6.5.3.4) and +/// vec_step (OpenCL 1.1 6.11.12). +class UnaryExprOrTypeTraitExpr : public Expr { + unsigned Kind : 2; bool isType : 1; // true if operand is a type, false if an expression union { TypeSourceInfo *Ty; @@ -1568,36 +1617,38 @@ class SizeOfAlignOfExpr : public Expr { SourceLocation OpLoc, RParenLoc; public: - SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo, - QualType resultType, SourceLocation op, - SourceLocation rp) : - Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary, + UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, TypeSourceInfo *TInfo, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. TInfo->getType()->isDependentType(), TInfo->getType()->containsUnexpandedParameterPack()), - isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) { + Kind(ExprKind), isType(true), OpLoc(op), RParenLoc(rp) { Argument.Ty = TInfo; } - SizeOfAlignOfExpr(bool issizeof, Expr *E, - QualType resultType, SourceLocation op, - SourceLocation rp) : - Expr(SizeOfAlignOfExprClass, resultType, VK_RValue, OK_Ordinary, + UnaryExprOrTypeTraitExpr(UnaryExprOrTypeTrait ExprKind, Expr *E, + QualType resultType, SourceLocation op, + SourceLocation rp) : + Expr(UnaryExprOrTypeTraitExprClass, resultType, VK_RValue, OK_Ordinary, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. E->isTypeDependent(), E->containsUnexpandedParameterPack()), - isSizeof(issizeof), isType(false), OpLoc(op), RParenLoc(rp) { + Kind(ExprKind), isType(false), OpLoc(op), RParenLoc(rp) { Argument.Ex = E; } /// \brief Construct an empty sizeof/alignof expression. - explicit SizeOfAlignOfExpr(EmptyShell Empty) - : Expr(SizeOfAlignOfExprClass, Empty) { } + explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty) + : Expr(UnaryExprOrTypeTraitExprClass, Empty) { } - bool isSizeOf() const { return isSizeof; } - void setSizeof(bool S) { isSizeof = S; } + UnaryExprOrTypeTrait getKind() const { + return static_cast<UnaryExprOrTypeTrait>(Kind); + } + void setKind(UnaryExprOrTypeTrait K) { Kind = K; } bool isArgumentType() const { return isType; } QualType getArgumentType() const { @@ -1612,7 +1663,7 @@ public: return static_cast<Expr*>(Argument.Ex); } const Expr *getArgumentExpr() const { - return const_cast<SizeOfAlignOfExpr*>(this)->getArgumentExpr(); + return const_cast<UnaryExprOrTypeTraitExpr*>(this)->getArgumentExpr(); } void setArgument(Expr *E) { Argument.Ex = E; isType = false; } @@ -1638,9 +1689,9 @@ public: } static bool classof(const Stmt *T) { - return T->getStmtClass() == SizeOfAlignOfExprClass; + return T->getStmtClass() == UnaryExprOrTypeTraitExprClass; } - static bool classof(const SizeOfAlignOfExpr *) { return true; } + static bool classof(const UnaryExprOrTypeTraitExpr *) { return true; } // Iterators child_range children(); @@ -1862,7 +1913,13 @@ public: /// class MemberExpr : public Expr { /// Extra data stored in some member expressions. - struct MemberNameQualifier : public NameQualifier { + struct MemberNameQualifier { + /// \brief The nested-name-specifier that qualifies the name, including + /// source-location information. + NestedNameSpecifierLoc QualifierLoc; + + /// \brief The DeclAccessPair through which the MemberDecl was found due to + /// name qualifiers. DeclAccessPair FoundDecl; }; @@ -1936,7 +1993,7 @@ public: HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, - NestedNameSpecifier *qual, SourceRange qualrange, + NestedNameSpecifierLoc QualifierLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *targs, @@ -1965,16 +2022,6 @@ public: /// x->Base::foo. bool hasQualifier() const { return getQualifier() != 0; } - /// \brief If the member name was qualified, retrieves the source range of - /// the nested-name-specifier that precedes the member name. Otherwise, - /// returns an empty source range. - SourceRange getQualifierRange() const { - if (!HasQualifierOrFoundDecl) - return SourceRange(); - - return getMemberQualifier()->Range; - } - /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. @@ -1982,7 +2029,17 @@ public: if (!HasQualifierOrFoundDecl) return 0; - return getMemberQualifier()->NNS; + return getMemberQualifier()->QualifierLoc.getNestedNameSpecifier(); + } + + /// \brief If the member name was qualified, retrieves the + /// nested-name-specifier that precedes the member name, with source-location + /// information. + NestedNameSpecifierLoc getQualifierLoc() const { + if (!hasQualifier()) + return NestedNameSpecifierLoc(); + + return getMemberQualifier()->QualifierLoc; } /// \brief Determines whether this member expression actually had a C++ @@ -2075,20 +2132,15 @@ public: SourceLocation getMemberLoc() const { return MemberLoc; } void setMemberLoc(SourceLocation L) { MemberLoc = L; } - SourceRange getSourceRange() const { - // If we have an implicit base (like a C++ implicit this), - // make sure not to return its location - SourceLocation EndLoc = (HasExplicitTemplateArgumentList) - ? getRAngleLoc() : getMemberNameInfo().getEndLoc(); - - SourceLocation BaseLoc = getBase()->getLocStart(); - if (BaseLoc.isInvalid()) - return SourceRange(MemberLoc, EndLoc); - return SourceRange(BaseLoc, EndLoc); - } - + SourceRange getSourceRange() const; + SourceLocation getExprLoc() const { return MemberLoc; } + /// \brief Determine whether the base of this explicit is implicit. + bool isImplicitAccess() const { + return getBase() && getBase()->isImplicitCXXThis(); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == MemberExprClass; } @@ -2234,6 +2286,12 @@ private: } CXXBaseSpecifier **path_buffer(); + void setBasePathSize(unsigned basePathSize) { + CastExprBits.BasePathSize = basePathSize; + assert(CastExprBits.BasePathSize == basePathSize && + "basePathSize doesn't fit in bits of CastExprBits.BasePathSize!"); + } + protected: CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, Expr *op, unsigned BasePathSize) : @@ -2249,14 +2307,14 @@ protected: Op(op) { assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; - CastExprBits.BasePathSize = BasePathSize; + setBasePathSize(BasePathSize); CheckCastConsistency(); } /// \brief Construct an empty cast. CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) : Expr(SC, Empty) { - CastExprBits.BasePathSize = BasePathSize; + setBasePathSize(BasePathSize); } public: @@ -3173,9 +3231,14 @@ class InitListExpr : public Expr { /// written in the source code. InitListExpr *SyntacticForm; - /// If this initializer list initializes a union, specifies which - /// field within the union will be initialized. - FieldDecl *UnionFieldInit; + /// \brief Either: + /// If this initializer list initializes an array with more elements than + /// there are initializers in the list, specifies an expression to be used + /// for value initialization of the rest of the elements. + /// Or + /// If this initializer list initializes a union, specifies which + /// field within the union will be initialized. + llvm::PointerUnion<Expr *, FieldDecl *> ArrayFillerOrUnionFieldInit; /// Whether this initializer list originally had a GNU array-range /// designator in it. This is a temporary marker used by CodeGen. @@ -3227,17 +3290,29 @@ public: /// /// When @p Init is out of range for this initializer list, the /// initializer list will be extended with NULL expressions to - /// accomodate the new entry. + /// accommodate the new entry. Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr); + /// \brief If this initializer list initializes an array with more elements + /// than there are initializers in the list, specifies an expression to be + /// used for value initialization of the rest of the elements. + Expr *getArrayFiller() { + return ArrayFillerOrUnionFieldInit.dyn_cast<Expr *>(); + } + void setArrayFiller(Expr *filler); + /// \brief If this initializes a union, specifies which field in the /// union to initialize. /// /// Typically, this field is the first named field within the /// union. However, a designated initializer can specify the /// initialization of a different field within the union. - FieldDecl *getInitializedFieldInUnion() { return UnionFieldInit; } - void setInitializedFieldInUnion(FieldDecl *FD) { UnionFieldInit = FD; } + FieldDecl *getInitializedFieldInUnion() { + return ArrayFillerOrUnionFieldInit.dyn_cast<FieldDecl *>(); + } + void setInitializedFieldInUnion(FieldDecl *FD) { + ArrayFillerOrUnionFieldInit = FD; + } // Explicit InitListExpr's originate from source code (and have valid source // locations). Implicit InitListExpr's are created by the semantic analyzer. @@ -3288,6 +3363,9 @@ public: const_reverse_iterator rbegin() const { return InitExprs.rbegin(); } reverse_iterator rend() { return InitExprs.rend(); } const_reverse_iterator rend() const { return InitExprs.rend(); } + + friend class ASTStmtReader; + friend class ASTStmtWriter; }; /// @brief Represents a C99 designated initializer expression. @@ -3492,6 +3570,12 @@ public: else return getLBracketLoc(); } + SourceLocation getEndLocation() const { + return Kind == FieldDesignator ? getFieldLoc() : getRBracketLoc(); + } + SourceRange getSourceRange() const { + return SourceRange(getStartLocation(), getEndLocation()); + } }; static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, @@ -3574,6 +3658,8 @@ public: void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First, const Designator *Last); + SourceRange getDesignatorsSourceRange() const; + SourceRange getSourceRange() const; static bool classof(const Stmt *T) { @@ -3667,6 +3753,118 @@ public: }; +/// \brief Represents a C1X generic selection. +/// +/// A generic selection (C1X 6.5.1.1) contains an unevaluated controlling +/// expression, followed by one or more generic associations. Each generic +/// association specifies a type name and an expression, or "default" and an +/// expression (in which case it is known as a default generic association). +/// The type and value of the generic selection are identical to those of its +/// result expression, which is defined as the expression in the generic +/// association with a type name that is compatible with the type of the +/// controlling expression, or the expression in the default generic association +/// if no types are compatible. For example: +/// +/// @code +/// _Generic(X, double: 1, float: 2, default: 3) +/// @endcode +/// +/// The above expression evaluates to 1 if 1.0 is substituted for X, 2 if 1.0f +/// or 3 if "hello". +/// +/// As an extension, generic selections are allowed in C++, where the following +/// additional semantics apply: +/// +/// Any generic selection whose controlling expression is type-dependent or +/// which names a dependent type in its association list is result-dependent, +/// which means that the choice of result expression is dependent. +/// Result-dependent generic associations are both type- and value-dependent. +class GenericSelectionExpr : public Expr { + enum { CONTROLLING, END_EXPR }; + TypeSourceInfo **AssocTypes; + Stmt **SubExprs; + unsigned NumAssocs, ResultIndex; + SourceLocation GenericLoc, DefaultLoc, RParenLoc; + +public: + GenericSelectionExpr(ASTContext &Context, + SourceLocation GenericLoc, Expr *ControllingExpr, + TypeSourceInfo **AssocTypes, Expr **AssocExprs, + unsigned NumAssocs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack, + unsigned ResultIndex); + + /// This constructor is used in the result-dependent case. + GenericSelectionExpr(ASTContext &Context, + SourceLocation GenericLoc, Expr *ControllingExpr, + TypeSourceInfo **AssocTypes, Expr **AssocExprs, + unsigned NumAssocs, SourceLocation DefaultLoc, + SourceLocation RParenLoc, + bool ContainsUnexpandedParameterPack); + + explicit GenericSelectionExpr(EmptyShell Empty) + : Expr(GenericSelectionExprClass, Empty) { } + + unsigned getNumAssocs() const { return NumAssocs; } + + SourceLocation getGenericLoc() const { return GenericLoc; } + SourceLocation getDefaultLoc() const { return DefaultLoc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + + const Expr *getAssocExpr(unsigned i) const { + return cast<Expr>(SubExprs[END_EXPR+i]); + } + Expr *getAssocExpr(unsigned i) { return cast<Expr>(SubExprs[END_EXPR+i]); } + + const TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) const { + return AssocTypes[i]; + } + TypeSourceInfo *getAssocTypeSourceInfo(unsigned i) { return AssocTypes[i]; } + + QualType getAssocType(unsigned i) const { + if (const TypeSourceInfo *TS = getAssocTypeSourceInfo(i)) + return TS->getType(); + else + return QualType(); + } + + const Expr *getControllingExpr() const { + return cast<Expr>(SubExprs[CONTROLLING]); + } + Expr *getControllingExpr() { return cast<Expr>(SubExprs[CONTROLLING]); } + + /// Whether this generic selection is result-dependent. + bool isResultDependent() const { return ResultIndex == -1U; } + + /// The zero-based index of the result expression's generic association in + /// the generic selection's association list. Defined only if the + /// generic selection is not result-dependent. + unsigned getResultIndex() const { + assert(!isResultDependent() && "Generic selection is result-dependent"); + return ResultIndex; + } + + /// The generic selection's result expression. Defined only if the + /// generic selection is not result-dependent. + const Expr *getResultExpr() const { return getAssocExpr(getResultIndex()); } + Expr *getResultExpr() { return getAssocExpr(getResultIndex()); } + + SourceRange getSourceRange() const { + return SourceRange(GenericLoc, RParenLoc); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == GenericSelectionExprClass; + } + static bool classof(const GenericSelectionExpr *) { return true; } + + child_range children() { + return child_range(SubExprs, SubExprs+END_EXPR+NumAssocs); + } + + friend class ASTStmtReader; +}; + //===----------------------------------------------------------------------===// // Clang Extensions //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 225db3c11fd0..a97057973745 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_EXPRCXX_H #include "clang/Basic/TypeTraits.h" +#include "clang/Basic/ExpressionTraits.h" #include "clang/AST/Expr.h" #include "clang/AST/UnresolvedSet.h" #include "clang/AST/TemplateBase.h" @@ -99,7 +100,10 @@ public: /// getImplicitObjectArgument - Retrieves the implicit object /// argument for the member call. For example, in "x.f(5)", this /// operation would return "x". - Expr *getImplicitObjectArgument(); + Expr *getImplicitObjectArgument() const; + + /// Retrieves the declaration of the called method. + CXXMethodDecl *getMethodDecl() const; /// getRecordDecl - Retrieves the CXXRecordDecl for the underlying type of /// the implicit object argument. Note that this is may not be the same @@ -250,6 +254,8 @@ public: static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, unsigned pathSize); + bool isAlwaysNull() const; + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDynamicCastExprClass; } @@ -774,7 +780,8 @@ public: enum ConstructionKind { CK_Complete, CK_NonVirtualBase, - CK_VirtualBase + CK_VirtualBase, + CK_Delegating }; private: @@ -1080,6 +1087,17 @@ public: TypeSourceInfo *getAllocatedTypeSourceInfo() const { return AllocatedTypeInfo; } + + /// \brief True if the allocation result needs to be null-checked. + /// C++0x [expr.new]p13: + /// If the allocation function returns null, initialization shall + /// not be done, the deallocation function shall not be called, + /// and the value of the new-expression shall be null. + /// An allocation function is not allowed to return null unless it + /// has a non-throwing exception-specification. The '03 rule is + /// identical except that the definition of a non-throwing + /// exception specification is just "is it throw()?". + bool shouldNullCheckAllocation(ASTContext &Ctx) const; FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } @@ -1577,6 +1595,122 @@ public: friend class ASTStmtReader; }; +/// ArrayTypeTraitExpr - An Embarcadero array type trait, as used in the +/// implementation of __array_rank and __array_extent. +/// Example: +/// __array_rank(int[10][20]) == 2 +/// __array_extent(int, 1) == 20 +class ArrayTypeTraitExpr : public Expr { + /// ATT - The trait. An ArrayTypeTrait enum in MSVC compat unsigned. + unsigned ATT : 2; + + /// The value of the type trait. Unspecified if dependent. + uint64_t Value; + + /// The array dimension being queried, or -1 if not used + Expr *Dimension; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + /// The type being queried. + TypeSourceInfo *QueriedType; + +public: + ArrayTypeTraitExpr(SourceLocation loc, ArrayTypeTrait att, + TypeSourceInfo *queried, uint64_t value, + Expr *dimension, SourceLocation rparen, QualType ty) + : Expr(ArrayTypeTraitExprClass, ty, VK_RValue, OK_Ordinary, + false, queried->getType()->isDependentType(), + queried->getType()->containsUnexpandedParameterPack()), + ATT(att), Value(value), Dimension(dimension), + Loc(loc), RParen(rparen), QueriedType(queried) { } + + + explicit ArrayTypeTraitExpr(EmptyShell Empty) + : Expr(ArrayTypeTraitExprClass, Empty), ATT(0), Value(false), + QueriedType() { } + + virtual ~ArrayTypeTraitExpr() { } + + virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen); } + + ArrayTypeTrait getTrait() const { return static_cast<ArrayTypeTrait>(ATT); } + + QualType getQueriedType() const { return QueriedType->getType(); } + + TypeSourceInfo *getQueriedTypeSourceInfo() const { return QueriedType; } + + uint64_t getValue() const { assert(!isTypeDependent()); return Value; } + + Expr *getDimensionExpression() const { return Dimension; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ArrayTypeTraitExprClass; + } + static bool classof(const ArrayTypeTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; +}; + +/// ExpressionTraitExpr - An expression trait intrinsic +/// Example: +/// __is_lvalue_expr(std::cout) == true +/// __is_lvalue_expr(1) == false +class ExpressionTraitExpr : public Expr { + /// ET - The trait. A ExpressionTrait enum in MSVC compat unsigned. + unsigned ET : 31; + /// The value of the type trait. Unspecified if dependent. + bool Value : 1; + + /// Loc - The location of the type trait keyword. + SourceLocation Loc; + + /// RParen - The location of the closing paren. + SourceLocation RParen; + + Expr* QueriedExpression; +public: + ExpressionTraitExpr(SourceLocation loc, ExpressionTrait et, + Expr *queried, bool value, + SourceLocation rparen, QualType resultType) + : Expr(ExpressionTraitExprClass, resultType, VK_RValue, OK_Ordinary, + false, // Not type-dependent + // Value-dependent if the argument is type-dependent. + queried->isTypeDependent(), + queried->containsUnexpandedParameterPack()), + ET(et), Value(value), Loc(loc), RParen(rparen), QueriedExpression(queried) { } + + explicit ExpressionTraitExpr(EmptyShell Empty) + : Expr(ExpressionTraitExprClass, Empty), ET(0), Value(false), + QueriedExpression() { } + + SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} + + ExpressionTrait getTrait() const { return static_cast<ExpressionTrait>(ET); } + + Expr *getQueriedExpression() const { return QueriedExpression; } + + bool getValue() const { return Value; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ExpressionTraitExprClass; + } + static bool classof(const ExpressionTraitExpr *) { return true; } + + // Iterators + child_range children() { return child_range(); } + + friend class ASTStmtReader; +}; + + /// \brief A reference to an overloaded function set, either an /// \t UnresolvedLookupExpr or an \t UnresolvedMemberExpr. class OverloadExpr : public Expr { @@ -1590,18 +1724,15 @@ class OverloadExpr : public Expr { /// The common name of these declarations. DeclarationNameInfo NameInfo; - /// The scope specifier, if any. - NestedNameSpecifier *Qualifier; - - /// The source range of the scope specifier. - SourceRange QualifierRange; + /// \brief The nested-name-specifier that qualifies the name, if any. + NestedNameSpecifierLoc QualifierLoc; protected: /// True if the name was a template-id. bool HasExplicitTemplateArgs; OverloadExpr(StmtClass K, ASTContext &C, - NestedNameSpecifier *Qualifier, SourceRange QRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, @@ -1610,7 +1741,7 @@ protected: OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty), Results(0), NumResults(0), - Qualifier(0), HasExplicitTemplateArgs(false) { } + QualifierLoc(), HasExplicitTemplateArgs(false) { } void initializeResults(ASTContext &C, UnresolvedSetIterator Begin, @@ -1665,23 +1796,21 @@ public: /// Gets the full name info. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - void setNameInfo(const DeclarationNameInfo &N) { NameInfo = N; } /// Gets the name looked up. DeclarationName getName() const { return NameInfo.getName(); } - void setName(DeclarationName N) { NameInfo.setName(N); } /// Gets the location of the name. SourceLocation getNameLoc() const { return NameInfo.getLoc(); } - void setNameLoc(SourceLocation Loc) { NameInfo.setLoc(Loc); } /// Fetches the nested-name qualifier, if one was given. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } - /// Fetches the range of the nested-name qualifier. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + /// Fetches the nested-name qualifier with source-location information, if + /// one was given. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } /// \brief Determines whether this expression had an explicit /// template argument list, e.g. f<int>. @@ -1727,6 +1856,10 @@ class UnresolvedLookupExpr : public OverloadExpr { /// call. bool RequiresADL; + /// True if namespace ::std should be considered an associated namespace + /// for the purposes of argument-dependent lookup. See C++0x [stmt.ranged]p1. + bool StdIsAssociatedNamespace; + /// True if these lookup results are overloaded. This is pretty /// trivially rederivable if we urgently need to kill this field. bool Overloaded; @@ -1740,39 +1873,46 @@ class UnresolvedLookupExpr : public OverloadExpr { UnresolvedLookupExpr(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, SourceRange QRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End) - : OverloadExpr(UnresolvedLookupExprClass, C, Qualifier, QRange, NameInfo, + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool StdIsAssociatedNamespace) + : OverloadExpr(UnresolvedLookupExprClass, C, QualifierLoc, NameInfo, TemplateArgs, Begin, End), - RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) + RequiresADL(RequiresADL), + StdIsAssociatedNamespace(StdIsAssociatedNamespace), + Overloaded(Overloaded), NamingClass(NamingClass) {} UnresolvedLookupExpr(EmptyShell Empty) : OverloadExpr(UnresolvedLookupExprClass, Empty), - RequiresADL(false), Overloaded(false), NamingClass(0) + RequiresADL(false), StdIsAssociatedNamespace(false), Overloaded(false), + NamingClass(0) {} + friend class ASTStmtReader; + public: static UnresolvedLookupExpr *Create(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool ADL, bool Overloaded, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { - return new(C) UnresolvedLookupExpr(C, NamingClass, Qualifier, - QualifierRange, NameInfo, ADL, - Overloaded, 0, Begin, End); + UnresolvedSetIterator End, + bool StdIsAssociatedNamespace = false) { + assert((ADL || !StdIsAssociatedNamespace) && + "std considered associated namespace when not performing ADL"); + return new(C) UnresolvedLookupExpr(C, NamingClass, QualifierLoc, NameInfo, + ADL, Overloaded, 0, Begin, End, + StdIsAssociatedNamespace); } static UnresolvedLookupExpr *Create(ASTContext &C, CXXRecordDecl *NamingClass, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool ADL, const TemplateArgumentListInfo &Args, @@ -1786,17 +1926,18 @@ public: /// True if this declaration should be extended by /// argument-dependent lookup. bool requiresADL() const { return RequiresADL; } - void setRequiresADL(bool V) { RequiresADL = V; } + + /// True if namespace ::std should be artificially added to the set of + /// associated namespaecs for argument-dependent lookup purposes. + bool isStdAssociatedNamespace() const { return StdIsAssociatedNamespace; } /// True if this lookup is overloaded. bool isOverloaded() const { return Overloaded; } - void setOverloaded(bool V) { Overloaded = V; } /// Gets the 'naming class' (in the sense of C++0x /// [class.access.base]p5) of the lookup. This is the scope /// that was looked in to find these results. CXXRecordDecl *getNamingClass() const { return NamingClass; } - void setNamingClass(CXXRecordDecl *D) { NamingClass = D; } // Note that, inconsistently with the explicit-template-argument AST // nodes, users are *forbidden* from calling these methods on objects @@ -1845,8 +1986,10 @@ public: SourceRange getSourceRange() const { SourceRange Range(getNameInfo().getSourceRange()); - if (getQualifier()) Range.setBegin(getQualifierRange().getBegin()); - if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); + if (getQualifierLoc()) + Range.setBegin(getQualifierLoc().getBeginLoc()); + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); return Range; } @@ -2186,16 +2329,13 @@ class CXXDependentScopeMemberExpr : public Expr { SourceLocation OperatorLoc; /// \brief The nested-name-specifier that precedes the member name, if any. - NestedNameSpecifier *Qualifier; - - /// \brief The source range covering the nested name specifier. - SourceRange QualifierRange; + NestedNameSpecifierLoc QualifierLoc; /// \brief In a qualified member access expression such as t->Base::f, this /// member stores the resolves of name lookup in the context of the member /// access expression, to be used at instantiation time. /// - /// FIXME: This member, along with the Qualifier and QualifierRange, could + /// FIXME: This member, along with the QualifierLoc, could /// be stuck into a structure that is optionally allocated at the end of /// the CXXDependentScopeMemberExpr, to save space in the common case. NamedDecl *FirstQualifierFoundInScope; @@ -2208,8 +2348,7 @@ class CXXDependentScopeMemberExpr : public Expr { CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2219,8 +2358,7 @@ public: Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo); @@ -2228,8 +2366,7 @@ public: Create(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); @@ -2241,7 +2378,7 @@ public: /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. - bool isImplicitAccess() const { return Base == 0; } + bool isImplicitAccess() const; /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -2249,30 +2386,27 @@ public: assert(!isImplicitAccess()); return cast<Expr>(Base); } - void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } - void setBaseType(QualType T) { BaseType = T; } /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieve the nested-name-specifier that qualifies the member /// name. - NestedNameSpecifier *getQualifier() const { return Qualifier; } - void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } - - /// \brief Retrieve the source range covering the nested-name-specifier - /// that qualifies the member name. - SourceRange getQualifierRange() const { return QualifierRange; } - void setQualifierRange(SourceRange R) { QualifierRange = R; } + NestedNameSpecifier *getQualifier() const { + return QualifierLoc.getNestedNameSpecifier(); + } + /// \brief Retrieve the nested-name-specifier that qualifies the member + /// name, with source location information. + NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } + + /// \brief Retrieve the first part of the nested-name-specifier that was /// found in the scope of the member access expression when the member access /// was initially parsed. @@ -2287,26 +2421,20 @@ public: NamedDecl *getFirstQualifierFoundInScope() const { return FirstQualifierFoundInScope; } - void setFirstQualifierFoundInScope(NamedDecl *D) { - FirstQualifierFoundInScope = D; - } /// \brief Retrieve the name of the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return MemberNameInfo; } - void setMemberNameInfo(const DeclarationNameInfo &N) { MemberNameInfo = N; } /// \brief Retrieve the name of the member that this expression /// refers to. DeclarationName getMember() const { return MemberNameInfo.getName(); } - void setMember(DeclarationName N) { MemberNameInfo.setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } - void setMemberLoc(SourceLocation L) { MemberNameInfo.setLoc(L); } /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. @@ -2376,7 +2504,7 @@ public: if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); else if (getQualifier()) - Range.setBegin(getQualifierRange().getBegin()); + Range.setBegin(getQualifierLoc().getBeginLoc()); else Range.setBegin(MemberNameInfo.getBeginLoc()); @@ -2438,8 +2566,7 @@ class UnresolvedMemberExpr : public OverloadExpr { UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2448,13 +2575,14 @@ class UnresolvedMemberExpr : public OverloadExpr { : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), HasUnresolvedUsing(false), Base(0) { } + friend class ASTStmtReader; + public: static UnresolvedMemberExpr * Create(ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, - NestedNameSpecifier *Qualifier, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2466,7 +2594,7 @@ public: /// \brief True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. - bool isImplicitAccess() const { return Base == 0; } + bool isImplicitAccess() const; /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. @@ -2478,24 +2606,19 @@ public: assert(!isImplicitAccess()); return cast<Expr>(Base); } - void setBase(Expr *E) { Base = E; } QualType getBaseType() const { return BaseType; } - void setBaseType(QualType T) { BaseType = T; } /// \brief Determine whether the lookup results contain an unresolved using /// declaration. bool hasUnresolvedUsing() const { return HasUnresolvedUsing; } - void setHasUnresolvedUsing(bool V) { HasUnresolvedUsing = V; } /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - void setArrow(bool A) { IsArrow = A; } /// \brief Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieves the naming class of this lookup. CXXRecordDecl *getNamingClass() const; @@ -2503,17 +2626,14 @@ public: /// \brief Retrieve the full name info for the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } - void setMemberNameInfo(const DeclarationNameInfo &N) { setNameInfo(N); } /// \brief Retrieve the name of the member that this expression /// refers to. DeclarationName getMemberName() const { return getName(); } - void setMemberName(DeclarationName N) { setName(N); } // \brief Retrieve the location of the name of the member that this // expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } - void setMemberLoc(SourceLocation L) { setNameLoc(L); } /// \brief Retrieve the explicit template argument list that followed the /// member template name. @@ -2570,8 +2690,8 @@ public: SourceRange Range = getMemberNameInfo().getSourceRange(); if (!isImplicitAccess()) Range.setBegin(Base->getSourceRange().getBegin()); - else if (getQualifier()) - Range.setBegin(getQualifierRange().getBegin()); + else if (getQualifierLoc()) + Range.setBegin(getQualifierLoc().getBeginLoc()); if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 285efb757bbb..8163923d62d1 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -337,6 +337,39 @@ public: QualType getSuperReceiverType() const { return QualType(Receiver.get<const Type*>(), 0); } + QualType getGetterResultType() const { + QualType ResultType; + if (isExplicitProperty()) { + const ObjCPropertyDecl *PDecl = getExplicitProperty(); + if (const ObjCMethodDecl *Getter = PDecl->getGetterMethodDecl()) + ResultType = Getter->getResultType(); + else + ResultType = getType(); + } else { + const ObjCMethodDecl *Getter = getImplicitPropertyGetter(); + ResultType = Getter->getResultType(); // with reference! + } + return ResultType; + } + + QualType getSetterArgType() const { + QualType ArgType; + if (isImplicitProperty()) { + const ObjCMethodDecl *Setter = getImplicitPropertySetter(); + ObjCMethodDecl::param_iterator P = Setter->param_begin(); + ArgType = (*P)->getType(); + } else { + if (ObjCPropertyDecl *PDecl = getExplicitProperty()) + if (const ObjCMethodDecl *Setter = PDecl->getSetterMethodDecl()) { + ObjCMethodDecl::param_iterator P = Setter->param_begin(); + ArgType = (*P)->getType(); + } + if (ArgType.isNull()) + ArgType = getType(); + } + return ArgType; + } + ObjCInterfaceDecl *getClassReceiver() const { return Receiver.get<ObjCInterfaceDecl*>(); } @@ -741,6 +774,11 @@ public: SelectorOrMethod = reinterpret_cast<uintptr_t>(MD); } + ObjCMethodFamily getMethodFamily() const { + if (HasMethod) return getMethodDecl()->getMethodFamily(); + return getSelector().getMethodFamily(); + } + /// \brief Return the number of actual arguments in this message, /// not counting the receiver. unsigned getNumArgs() const { return NumArgs; } @@ -808,7 +846,7 @@ public: }; /// ObjCIsaExpr - Represent X->isa and X.isa when X is an ObjC 'id' type. -/// (similiar in spirit to MemberExpr). +/// (similar in spirit to MemberExpr). class ObjCIsaExpr : public Expr { /// Base - the expression for the base object pointer. Stmt *Base; diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 7b23766b0714..6db233641220 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This file defines the ExternalASTSource interface, which enables -// construction of AST nodes from some external source.x +// construction of AST nodes from some external source. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H @@ -16,7 +16,6 @@ #include "clang/AST/DeclBase.h" #include <cassert> -#include <vector> namespace llvm { template <class T> class SmallVectorImpl; @@ -26,9 +25,6 @@ namespace clang { class ASTConsumer; class CXXBaseSpecifier; -class Decl; -class DeclContext; -class DeclContextLookupResult; class DeclarationName; class ExternalSemaSource; // layering violation required for downcasting class NamedDecl; @@ -74,17 +70,23 @@ public: /// /// This method only needs to be implemented if the AST source ever /// passes back decl sets as VisibleDeclaration objects. - virtual Decl *GetExternalDecl(uint32_t ID) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Decl *GetExternalDecl(uint32_t ID); /// \brief Resolve a selector ID into a selector. /// /// This operation only needs to be implemented if the AST source /// returns non-zero for GetNumKnownSelectors(). - virtual Selector GetExternalSelector(uint32_t ID) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Selector GetExternalSelector(uint32_t ID); /// \brief Returns the number of selectors known to the external AST /// source. - virtual uint32_t GetNumExternalSelectors() = 0; + /// + /// The default implementation of this method is a no-op. + virtual uint32_t GetNumExternalSelectors(); /// \brief Resolve the offset of a statement in the decl stream into /// a statement. @@ -92,21 +94,26 @@ public: /// This operation is meant to be used via a LazyOffsetPtr. It only /// needs to be implemented if the AST source uses methods like /// FunctionDecl::setLazyBody when building decls. - virtual Stmt *GetExternalDeclStmt(uint64_t Offset) = 0; + /// + /// The default implementation of this method is a no-op. + virtual Stmt *GetExternalDeclStmt(uint64_t Offset); /// \brief Resolve the offset of a set of C++ base specifiers in the decl /// stream into an array of specifiers. - virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) = 0; - + /// + /// The default implementation of this method is a no-op. + virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); + /// \brief Finds all declarations with the given name in the /// given context. /// /// Generally the final step of this method is either to call /// SetExternalVisibleDeclsForName or to recursively call lookup on /// the DeclContext after calling SetExternalVisibleDecls. + /// + /// The default implementation of this method is a no-op. virtual DeclContextLookupResult - FindExternalVisibleDeclsByName(const DeclContext *DC, - DeclarationName Name) = 0; + FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); /// \brief Deserialize all the visible declarations from external storage. /// @@ -114,7 +121,9 @@ public: /// may not have a complete name lookup table. This function deserializes /// the rest of visible declarations from the external storage and completes /// the name lookup table of the DeclContext. - virtual void MaterializeVisibleDecls(const DeclContext *DC) = 0; + /// + /// The default implementation of this method is a no-op. + virtual void MaterializeVisibleDecls(const DeclContext *DC); /// \brief Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. @@ -124,9 +133,11 @@ public: /// are returned. /// /// \return true if an error occurred + /// + /// The default implementation of this method is a no-op. virtual bool FindExternalLexicalDecls(const DeclContext *DC, bool (*isKindWeWant)(Decl::Kind), - llvm::SmallVectorImpl<Decl*> &Result) = 0; + llvm::SmallVectorImpl<Decl*> &Result); /// \brief Finds all declarations lexically contained within the given /// DeclContext. @@ -154,7 +165,7 @@ public: /// set on the ObjCInterfaceDecl via the function /// \c ObjCInterfaceDecl::setExternallyCompleted(). virtual void CompleteType(ObjCInterfaceDecl *Class) { } - + /// \brief Notify ExternalASTSource that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. @@ -179,6 +190,28 @@ public: /// /// The default implementation of this method is a no-op. virtual void PrintStats(); + + //===--------------------------------------------------------------------===// + // Queries for performance analysis. + //===--------------------------------------------------------------------===// + + struct MemoryBufferSizes { + size_t malloc_bytes; + size_t mmap_bytes; + + MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) + : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} + }; + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + MemoryBufferSizes getMemoryBufferSizes() const { + MemoryBufferSizes sizes(0, 0); + getMemoryBufferSizes(sizes); + return sizes; + } + + virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const = 0; protected: static DeclContextLookupResult @@ -270,7 +303,7 @@ typedef LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl> typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, &ExternalASTSource::GetExternalCXXBaseSpecifiers> LazyCXXBaseSpecifiersPtr; - + } // end namespace clang #endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 024bf402894b..c21c76b006ff 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -312,6 +312,146 @@ public: } }; +/// \brief Class that aids in the construction of nested-name-specifiers along +/// with source-location information for all of the components of the +/// nested-name-specifier. +class NestedNameSpecifierLocBuilder { + /// \brief The current representation of the nested-name-specifier we're + /// building. + NestedNameSpecifier *Representation; + + /// \brief Buffer used to store source-location information for the + /// nested-name-specifier. + /// + /// Note that we explicitly manage the buffer (rather than using a + /// SmallVector) because \c Declarator expects it to be possible to memcpy() + /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. + char *Buffer; + + /// \brief The size of the buffer used to store source-location information + /// for the nested-name-specifier. + unsigned BufferSize; + + /// \brief The capacity of the buffer used to store source-location + /// information for the nested-name-specifier. + unsigned BufferCapacity; + +public: + NestedNameSpecifierLocBuilder(); + + NestedNameSpecifierLocBuilder(const NestedNameSpecifierLocBuilder &Other); + + NestedNameSpecifierLocBuilder & + operator=(const NestedNameSpecifierLocBuilder &Other); + + ~NestedNameSpecifierLocBuilder(); + + /// \brief Retrieve the representation of the nested-name-specifier. + NestedNameSpecifier *getRepresentation() const { return Representation; } + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'type::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param TemplateKWLoc The location of the 'template' keyword, if present. + /// + /// \param TL The TypeLoc that describes the type preceding the '::'. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, + SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'identifier::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Identifier The identifier. + /// + /// \param IdentifierLoc The location of the identifier. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, IdentifierInfo *Identifier, + SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Namespace The namespace. + /// + /// \param NamespaceLoc The location of the namespace name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceDecl *Namespace, + SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); + + /// \brief Extend the current nested-name-specifier by another + /// nested-name-specifier component of the form 'namespace-alias::'. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param Alias The namespace alias. + /// + /// \param AliasLoc The location of the namespace alias + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, + SourceLocation AliasLoc, SourceLocation ColonColonLoc); + + /// \brief Turn this (empty) nested-name-specifier into the global + /// nested-name-specifier '::'. + void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + + /// \brief Make a new nested-name-specifier from incomplete source-location + /// information. + /// + /// This routine should be used very, very rarely, in cases where we + /// need to synthesize a nested-name-specifier. Most code should instead use + /// \c Adopt() with a proper \c NestedNameSpecifierLoc. + void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, + SourceRange R); + + /// \brief Adopt an existing nested-name-specifier (with source-range + /// information). + void Adopt(NestedNameSpecifierLoc Other); + + /// \brief Retrieve the source range covered by this nested-name-specifier. + SourceRange getSourceRange() const { + return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); + } + + /// \brief Retrieve a nested-name-specifier with location information, + /// copied into the given AST context. + /// + /// \param Context The context into which this nested-name-specifier will be + /// copied. + NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; + + /// \brief Clear out this builder, and prepare it to build another + /// nested-name-specifier with source-location information. + void Clear() { + Representation = 0; + BufferSize = 0; + } + + /// \brief Retrieve the underlying buffer. + /// + /// \returns A pair containing a pointer to the buffer of source-location + /// data and the size of the source-location data that resides in that + /// buffer. + std::pair<char *, unsigned> getBuffer() const { + return std::make_pair(Buffer, BufferSize); + } +}; + /// Insertion operator for diagnostics. This allows sending NestedNameSpecifiers /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index a59c302ffc1e..cf5fadbd1850 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -38,7 +38,8 @@ struct PrintingPolicy { /// \brief Create a default printing policy for C. PrintingPolicy(const LangOptions &LO) : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), - SuppressTag(false), SuppressScope(false), + SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), + SuppressInitializers(false), Dump(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true) { } @@ -64,6 +65,16 @@ struct PrintingPolicy { /// "const int" type specifier and instead only print the "*y". bool SuppressSpecifiers : 1; + /// \brief Whether type printing should skip printing the tag keyword. + /// + /// This is used when printing the inner type of elaborated types, + /// (as the tag keyword is part of the elaborated type): + /// + /// \code + /// struct Geometry::Point; + /// \endcode + bool SuppressTagKeyword : 1; + /// \brief Whether type printing should skip printing the actual tag type. /// /// This is used when the caller needs to print a tag definition in front @@ -77,6 +88,19 @@ struct PrintingPolicy { /// \brief Suppresses printing of scope specifiers. bool SuppressScope : 1; + /// \brief Suppress printing of variable initializers. + /// + /// This flag is used when printing the loop variable in a for-range + /// statement. For example, given: + /// + /// \code + /// for (auto x : coll) + /// \endcode + /// + /// SuppressInitializers will be true when printing "auto x", so that the + /// internal initializer constructed for x will not be printed. + bool SuppressInitializers : 1; + /// \brief True when we are "dumping" rather than "pretty-printing", /// where dumping involves printing the internal details of the AST /// and pretty-printing involves printing something similar to diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index e85b6dcd279a..930d19373cdc 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -600,12 +600,15 @@ bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( // FIXME: how can TSI ever be NULL? if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo()) return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); - else - return true; + else + return getDerived().TraverseType(Arg.getAsType()); } case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: + if (ArgLoc.getTemplateQualifierLoc()) + TRY_TO(getDerived().TraverseNestedNameSpecifierLoc( + ArgLoc.getTemplateQualifierLoc())); return getDerived().TraverseTemplateName( Arg.getAsTemplateOrTemplatePattern()); @@ -933,7 +936,11 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { const FunctionProtoType *T = TL.getTypePtr(); for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { - TRY_TO(TraverseDecl(TL.getArg(I))); + if (TL.getArg(I)) { + TRY_TO(TraverseDecl(TL.getArg(I))); + } else if (I < T->getNumArgs()) { + TRY_TO(TraverseType(T->getArgType(I))); + } } for (FunctionProtoType::exception_iterator E = T->exception_begin(), @@ -987,21 +994,22 @@ DEF_TRAVERSE_TYPELOC(AttributedType, { TRY_TO(TraverseTypeLoc(TL.getModifiedLoc())); }) -// FIXME: use the sourceloc on qualifier? DEF_TRAVERSE_TYPELOC(ElaboratedType, { - if (TL.getTypePtr()->getQualifier()) { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); } TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); }) -// FIXME: use the sourceloc on qualifier? DEF_TRAVERSE_TYPELOC(DependentNameType, { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); }) DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { - TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + if (TL.getQualifierLoc()) { + TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc())); + } + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); } @@ -1041,7 +1049,9 @@ bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { for (DeclContext::decl_iterator Child = DC->decls_begin(), ChildEnd = DC->decls_end(); Child != ChildEnd; ++Child) { - TRY_TO(TraverseDecl(*Child)); + // BlockDecls are traversed through BlockExprs. + if (!isa<BlockDecl>(*Child)) + TRY_TO(TraverseDecl(*Child)); } return true; @@ -1060,10 +1070,12 @@ bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \ DEF_TRAVERSE_DECL(AccessSpecDecl, { }) DEF_TRAVERSE_DECL(BlockDecl, { - // We don't traverse nodes in param_begin()/param_end(), as they - // appear in decls_begin()/decls_end() and thus are handled by the - // DEF_TRAVERSE_DECL macro already. + TRY_TO(TraverseTypeLoc(D->getSignatureAsWritten()->getTypeLoc())); TRY_TO(TraverseStmt(D->getBody())); + // This return statement makes sure the traversal of nodes in + // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) + // is skipped - don't remove it. + return true; }) DEF_TRAVERSE_DECL(FileScopeAsmDecl, { @@ -1164,9 +1176,17 @@ DEF_TRAVERSE_DECL(ObjCProtocolDecl, { }) DEF_TRAVERSE_DECL(ObjCMethodDecl, { - // We don't traverse nodes in param_begin()/param_end(), as they - // appear in decls_begin()/decls_end() and thus are handled. - TRY_TO(TraverseStmt(D->getBody())); + if (D->getResultTypeSourceInfo()) { + TRY_TO(TraverseTypeLoc(D->getResultTypeSourceInfo()->getTypeLoc())); + } + for (ObjCMethodDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseStmt(D->getBody())); + } + return true; }) DEF_TRAVERSE_DECL(ObjCPropertyDecl, { @@ -1341,6 +1361,13 @@ DEF_TRAVERSE_DECL(TypedefDecl, { // source. }) +DEF_TRAVERSE_DECL(TypeAliasDecl, { + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type alias, not something that was written in the + // source. + }) + DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { // A dependent using declaration which was marked with 'typename'. // template<class T> class A : public B<T> { using typename B<T>::foo; }; @@ -1354,7 +1381,7 @@ DEF_TRAVERSE_DECL(EnumDecl, { if (D->getTypeForDecl()) TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); // The enumerators are already traversed by // decls_begin()/decls_end(). }) @@ -1367,7 +1394,7 @@ bool RecursiveASTVisitor<Derived>::TraverseRecordHelper( // We shouldn't traverse D->getTypeForDecl(); it's a result of // declaring the type, not something that was written in the source. - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); return true; } @@ -1464,9 +1491,11 @@ DEF_TRAVERSE_DECL(IndirectFieldDecl, {}) template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); if (D->getTypeSourceInfo()) TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + else + TRY_TO(TraverseType(D->getType())); return true; } @@ -1492,7 +1521,7 @@ DEF_TRAVERSE_DECL(ObjCIvarDecl, { template<typename Derived> bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { - TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc())); // If we're an explicit template specialization, iterate over the // template args that were explicitly specified. If we were doing @@ -1678,13 +1707,14 @@ DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { }) DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) +DEF_TRAVERSE_STMT(CXXForRangeStmt, { }) DEF_TRAVERSE_STMT(ReturnStmt, { }) DEF_TRAVERSE_STMT(SwitchStmt, { }) DEF_TRAVERSE_STMT(WhileStmt, { }) DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); @@ -1692,7 +1722,7 @@ DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { }) DEF_TRAVERSE_STMT(DeclRefExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); }) @@ -1707,10 +1737,9 @@ DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { }) DEF_TRAVERSE_STMT(MemberExpr, { + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); TRY_TO(TraverseTemplateArgumentLocsHelper( S->getTemplateArgs(), S->getNumTemplateArgs())); - // FIXME: Should we be recursing on the qualifier? - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); }) DEF_TRAVERSE_STMT(ImplicitCastExpr, { @@ -1759,6 +1788,22 @@ bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { return true; } +// GenericSelectionExpr is a special case because the types and expressions +// are interleaved. We also need to watch out for null types (default +// generic associations). +template<typename Derived> +bool RecursiveASTVisitor<Derived>:: +TraverseGenericSelectionExpr(GenericSelectionExpr *S) { + TRY_TO(WalkUpFromGenericSelectionExpr(S)); + TRY_TO(TraverseStmt(S->getControllingExpr())); + for (unsigned i = 0; i != S->getNumAssocs(); ++i) { + if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i)) + TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); + TRY_TO(TraverseStmt(S->getAssocExpr(i))); + } + return true; +} + DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { // This is called for code like 'return T()' where T is a built-in // (i.e. non-class) type. @@ -1778,7 +1823,7 @@ DEF_TRAVERSE_STMT(OffsetOfExpr, { TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc())); }) -DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { +DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, { // The child-iterator will pick up the arg if it's an expression, // but not if it's a type. if (S->isArgumentType()) @@ -1808,6 +1853,14 @@ DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, { TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { + TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc())); + }) + +DEF_TRAVERSE_STMT(ExpressionTraitExpr, { + TRY_TO(TraverseStmt(S->getQueriedExpression())); + }) + DEF_TRAVERSE_STMT(VAArgExpr, { // The child-iterator will pick up the expression argument. TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc())); @@ -1834,7 +1887,10 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, { }) DEF_TRAVERSE_STMT(AddrLabelExpr, { }) DEF_TRAVERSE_STMT(ArraySubscriptExpr, { }) DEF_TRAVERSE_STMT(BlockDeclRefExpr, { }) -DEF_TRAVERSE_STMT(BlockExpr, { }) +DEF_TRAVERSE_STMT(BlockExpr, { + TRY_TO(TraverseDecl(S->getBlockDecl())); + return true; // no child statements to loop through. +}) DEF_TRAVERSE_STMT(ChooseExpr, { }) DEF_TRAVERSE_STMT(CompoundLiteralExpr, { }) DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) @@ -1869,7 +1925,7 @@ DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), S->getNumTemplateArgs())); @@ -1877,13 +1933,17 @@ DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { - TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (S->hasExplicitTemplateArgs()) { TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(), S->getNumTemplateArgs())); } }) +DEF_TRAVERSE_STMT(SEHTryStmt, {}) +DEF_TRAVERSE_STMT(SEHExceptStmt, {}) +DEF_TRAVERSE_STMT(SEHFinallyStmt,{}) + DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) DEF_TRAVERSE_STMT(OpaqueValueExpr, { }) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { }) @@ -1921,7 +1981,7 @@ DEF_TRAVERSE_STMT(ObjCStringLiteral, { }) // Candidates: // // http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html -// http://clang.llvm.org/doxygen/classclang_1_1SizeOfAlignOfExpr.html +// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html // http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html // Every class that has getQualifier. diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index d1f7d667f33d..695fb0403ead 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -158,6 +158,16 @@ protected: }; enum { NumExprBits = 15 }; + class DeclRefExprBitfields { + friend class DeclRefExpr; + friend class ASTStmtReader; // deserialization + unsigned : NumExprBits; + + unsigned HasQualifier : 1; + unsigned HasExplicitTemplateArgs : 1; + unsigned HasFoundDecl : 1; + }; + class CastExprBitfields { friend class CastExpr; unsigned : NumExprBits; @@ -180,6 +190,7 @@ protected: StmtBitfields StmtBits; CompoundStmtBitfields CompoundStmtBits; ExprBitfields ExprBits; + DeclRefExprBitfields DeclRefExprBits; CastExprBitfields CastExprBits; CallExprBitfields CallExprBits; }; @@ -383,14 +394,15 @@ public: class NullStmt : public Stmt { SourceLocation SemiLoc; - /// \brief Whether the null statement was preceded by an empty macro, e.g: + /// \brief If the null statement was preceded by an empty macro this is + /// its instantiation source location, e.g: /// @code /// #define CALL(x) /// CALL(0); /// @endcode - bool LeadingEmptyMacro; + SourceLocation LeadingEmptyMacro; public: - NullStmt(SourceLocation L, bool LeadingEmptyMacro = false) + NullStmt(SourceLocation L, SourceLocation LeadingEmptyMacro =SourceLocation()) : Stmt(NullStmtClass), SemiLoc(L), LeadingEmptyMacro(LeadingEmptyMacro) {} /// \brief Build an empty null statement. @@ -399,7 +411,8 @@ public: SourceLocation getSemiLoc() const { return SemiLoc; } void setSemiLoc(SourceLocation L) { SemiLoc = L; } - bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro; } + bool hasLeadingEmptyMacro() const { return LeadingEmptyMacro.isValid(); } + SourceLocation getLeadingEmptyMacroLoc() const { return LeadingEmptyMacro; } SourceRange getSourceRange() const { return SourceRange(SemiLoc); } @@ -424,6 +437,8 @@ public: SourceLocation LB, SourceLocation RB) : Stmt(CompoundStmtClass), LBracLoc(LB), RBracLoc(RB) { CompoundStmtBits.NumStmts = NumStmts; + assert(CompoundStmtBits.NumStmts == NumStmts && + "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); if (NumStmts == 0) { Body = 0; @@ -516,6 +531,9 @@ public: void setNextSwitchCase(SwitchCase *SC) { NextSwitchCase = SC; } Stmt *getSubStmt(); + const Stmt *getSubStmt() const { + return const_cast<SwitchCase*>(this)->getSubStmt(); + } SourceRange getSourceRange() const { return SourceRange(); } @@ -527,7 +545,7 @@ public: }; class CaseStmt : public SwitchCase { - enum { SUBSTMT, LHS, RHS, END_EXPR }; + enum { LHS, RHS, SUBSTMT, END_EXPR }; Stmt* SubExprs[END_EXPR]; // The expression for the RHS is Non-null for // GNU "case 1 ... 4" extension SourceLocation CaseLoc; @@ -688,6 +706,12 @@ public: VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this IfStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); + } + const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } const Stmt *getThen() const { return SubExprs[THEN]; } @@ -754,6 +778,12 @@ public: /// \endcode VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + + /// If this SwitchStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); + } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} const Stmt *getBody() const { return SubExprs[BODY]; } @@ -835,6 +865,12 @@ public: VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this WhileStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast<DeclStmt*>(SubExprs[VAR]); + } + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } @@ -939,6 +975,12 @@ public: VarDecl *getConditionVariable() const; void setConditionVariable(ASTContext &C, VarDecl *V); + /// If this ForStmt has a condition variable, return the faux DeclStmt + /// associated with the creation of that condition variable. + const DeclStmt *getConditionVariableDeclStmt() const { + return reinterpret_cast<DeclStmt*>(SubExprs[CONDVAR]); + } + Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } Stmt *getBody() { return SubExprs[BODY]; } @@ -1406,6 +1448,122 @@ public: } }; +class SEHExceptStmt : public Stmt { + SourceLocation Loc; + Stmt *Children[2]; + + enum { FILTER_EXPR, BLOCK }; + + SEHExceptStmt(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block); + +public: + static SEHExceptStmt* Create(ASTContext &C, + SourceLocation ExceptLoc, + Expr *FilterExpr, + Stmt *Block); + SourceRange getSourceRange() const { + return SourceRange(getExceptLoc(), getEndLoc()); + } + + SourceLocation getExceptLoc() const { return Loc; } + SourceLocation getEndLoc() const { return getBlock()->getLocEnd(); } + + Expr *getFilterExpr() const { return reinterpret_cast<Expr*>(Children[FILTER_EXPR]); } + CompoundStmt *getBlock() const { return llvm::cast<CompoundStmt>(Children[BLOCK]); } + + child_range children() { + return child_range(Children,Children+2); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHExceptStmtClass; + } + + static bool classof(SEHExceptStmt *) { return true; } + +}; + +class SEHFinallyStmt : public Stmt { + SourceLocation Loc; + Stmt *Block; + + SEHFinallyStmt(SourceLocation Loc, + Stmt *Block); + +public: + static SEHFinallyStmt* Create(ASTContext &C, + SourceLocation FinallyLoc, + Stmt *Block); + + SourceRange getSourceRange() const { + return SourceRange(getFinallyLoc(), getEndLoc()); + } + + SourceLocation getFinallyLoc() const { return Loc; } + SourceLocation getEndLoc() const { return Block->getLocEnd(); } + + CompoundStmt *getBlock() const { return llvm::cast<CompoundStmt>(Block); } + + child_range children() { + return child_range(&Block,&Block+1); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHFinallyStmtClass; + } + + static bool classof(SEHFinallyStmt *) { return true; } + +}; + +class SEHTryStmt : public Stmt { + bool IsCXXTry; + SourceLocation TryLoc; + Stmt *Children[2]; + + enum { TRY = 0, HANDLER = 1 }; + + SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try' + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); + +public: + static SEHTryStmt* Create(ASTContext &C, + bool isCXXTry, + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); + + SourceRange getSourceRange() const { + return SourceRange(getTryLoc(), getEndLoc()); + } + + SourceLocation getTryLoc() const { return TryLoc; } + SourceLocation getEndLoc() const { return Children[HANDLER]->getLocEnd(); } + + bool getIsCXXTry() const { return IsCXXTry; } + CompoundStmt* getTryBlock() const { return llvm::cast<CompoundStmt>(Children[TRY]); } + Stmt *getHandler() const { return Children[HANDLER]; } + + /// Returns 0 if not defined + SEHExceptStmt *getExceptHandler() const; + SEHFinallyStmt *getFinallyHandler() const; + + child_range children() { + return child_range(Children,Children+2); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == SEHTryStmtClass; + } + + static bool classof(SEHTryStmt *) { return true; } + +}; + } // end namespace clang #endif diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index f08815fd562d..42dcf2bb7b79 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -119,6 +119,88 @@ public: friend class ASTStmtReader; }; +/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for +/// statement, represented as 'for (range-declarator : range-expression)'. +/// +/// This is stored in a partially-desugared form to allow full semantic +/// analysis of the constituent components. The original syntactic components +/// can be extracted using getLoopVariable and getRangeInit. +class CXXForRangeStmt : public Stmt { + enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END }; + // SubExprs[RANGE] is an expression or declstmt. + // SubExprs[COND] and SubExprs[INC] are expressions. + Stmt *SubExprs[END]; + SourceLocation ForLoc; + SourceLocation ColonLoc; + SourceLocation RParenLoc; +public: + CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd, + Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, + SourceLocation FL, SourceLocation CL, SourceLocation RPL); + CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } + + + VarDecl *getLoopVariable(); + Expr *getRangeInit(); + + const VarDecl *getLoopVariable() const; + const Expr *getRangeInit() const; + + + DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); } + DeclStmt *getBeginEndStmt() { return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); } + Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } + Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } + DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } + Stmt *getBody() { return SubExprs[BODY]; } + + const DeclStmt *getRangeStmt() const { + return cast<DeclStmt>(SubExprs[RANGE]); + } + const DeclStmt *getBeginEndStmt() const { + return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); + } + const Expr *getCond() const { + return cast_or_null<Expr>(SubExprs[COND]); + } + const Expr *getInc() const { + return cast_or_null<Expr>(SubExprs[INC]); + } + const DeclStmt *getLoopVarStmt() const { + return cast<DeclStmt>(SubExprs[LOOPVAR]); + } + const Stmt *getBody() const { return SubExprs[BODY]; } + + void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } + void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } + void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; } + void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } + void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } + void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } + void setBody(Stmt *S) { SubExprs[BODY] = S; } + + + SourceLocation getForLoc() const { return ForLoc; } + void setForLoc(SourceLocation Loc) { ForLoc = Loc; } + SourceLocation getColonLoc() const { return ColonLoc; } + void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } + SourceLocation getRParenLoc() const { return RParenLoc; } + void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } + + SourceRange getSourceRange() const { + return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); + } + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXForRangeStmtClass; + } + static bool classof(const CXXForRangeStmt *) { return true; } + + // Iterators + child_range children() { + return child_range(&SubExprs[0], &SubExprs[END]); + } +}; + } // end namespace clang diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 851c001adc54..05b50db7def7 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -18,6 +18,7 @@ #include <cassert> #include <cstddef> #include <iterator> +#include <utility> namespace clang { diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index a4e074e083f6..821b4fcbb168 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -362,7 +362,10 @@ private: Expr *Expression; TypeSourceInfo *Declarator; struct { - unsigned QualifierRange[2]; + // FIXME: We'd like to just use the qualifier in the TemplateName, + // but template arguments get canonicalized too quickly. + NestedNameSpecifier *Qualifier; + void *QualifierLocData; unsigned TemplateNameLoc; unsigned EllipsisLoc; } Template; @@ -375,12 +378,12 @@ public: TemplateArgumentLocInfo(Expr *E) : Expression(E) {} - TemplateArgumentLocInfo(SourceRange QualifierRange, + TemplateArgumentLocInfo(NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc) { - Template.QualifierRange[0] = QualifierRange.getBegin().getRawEncoding(); - Template.QualifierRange[1] = QualifierRange.getEnd().getRawEncoding(); + Template.Qualifier = QualifierLoc.getNestedNameSpecifier(); + Template.QualifierLocData = QualifierLoc.getOpaqueData(); Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); Template.EllipsisLoc = EllipsisLoc.getRawEncoding(); } @@ -393,10 +396,9 @@ public: return Expression; } - SourceRange getTemplateQualifierRange() const { - return SourceRange( - SourceLocation::getFromRawEncoding(Template.QualifierRange[0]), - SourceLocation::getFromRawEncoding(Template.QualifierRange[1])); + NestedNameSpecifierLoc getTemplateQualifierLoc() const { + return NestedNameSpecifierLoc(Template.Qualifier, + Template.QualifierLocData); } SourceLocation getTemplateNameLoc() const { @@ -433,11 +435,10 @@ public: } TemplateArgumentLoc(const TemplateArgument &Argument, - SourceRange QualifierRange, + NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateNameLoc, SourceLocation EllipsisLoc = SourceLocation()) - : Argument(Argument), - LocInfo(QualifierRange, TemplateNameLoc, EllipsisLoc) { + : Argument(Argument), LocInfo(QualifierLoc, TemplateNameLoc, EllipsisLoc) { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); } @@ -477,10 +478,10 @@ public: return LocInfo.getAsExpr(); } - SourceRange getTemplateQualifierRange() const { + NestedNameSpecifierLoc getTemplateQualifierLoc() const { assert(Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion); - return LocInfo.getTemplateQualifierRange(); + return LocInfo.getTemplateQualifierLoc(); } SourceLocation getTemplateNameLoc() const { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 9b177cceed96..975a66fefa89 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_TYPE_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Linkage.h" #include "clang/Basic/PartialDiagnostic.h" @@ -72,7 +73,7 @@ namespace llvm { namespace clang { class ASTContext; - class TypedefDecl; + class TypedefNameDecl; class TemplateDecl; class TemplateTypeParmDecl; class NonTypeTemplateParmDecl; @@ -212,6 +213,11 @@ public: assert(type); setObjCGCAttr(type); } + Qualifiers withoutObjCGCAttr() const { + Qualifiers qs = *this; + qs.removeObjCGCAttr(); + return qs; + } bool hasAddressSpace() const { return Mask & AddressSpaceMask; } unsigned getAddressSpace() const { return Mask >> AddressSpaceShift; } @@ -293,8 +299,10 @@ public: (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); } - bool isSupersetOf(Qualifiers Other) const; - + /// \brief Determine whether this set of qualifiers is a strict superset of + /// another set of qualifiers, not considering qualifier compatibility. + bool isStrictSupersetOf(Qualifiers Other) const; + bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } @@ -354,7 +362,9 @@ enum CallingConv { CC_X86StdCall, // __attribute__((stdcall)) CC_X86FastCall, // __attribute__((fastcall)) CC_X86ThisCall, // __attribute__((thiscall)) - CC_X86Pascal // __attribute__((pascal)) + CC_X86Pascal, // __attribute__((pascal)) + CC_AAPCS, // __attribute__((pcs("aapcs"))) + CC_AAPCS_VFP // __attribute__((pcs("aapcs-vfp"))) }; typedef std::pair<const Type*, Qualifiers> SplitQualType; @@ -598,8 +608,14 @@ public: /// ASTContext::getUnqualifiedArrayType. inline SplitQualType getSplitUnqualifiedType() const; + /// \brief Determine whether this type is more qualified than the other + /// given type, requiring exact equality for non-CVR qualifiers. bool isMoreQualifiedThan(QualType Other) const; + + /// \brief Determine whether this type is at least as qualified as the other + /// given type, requiring exact equality for non-CVR qualifiers. bool isAtLeastAsQualifiedAs(QualType Other) const; + QualType getNonReferenceType() const; /// \brief Determine the type of a (typically non-lvalue) expression with the @@ -1163,6 +1179,20 @@ public: /// (C++0x [basic.types]p10) bool isLiteralType() const; + /// isTrivialType - Return true if this is a trivial type + /// (C++0x [basic.types]p9) + bool isTrivialType() const; + + /// \brief Test if this type is a standard-layout type. + /// (C++0x [basic.type]p9) + bool isStandardLayoutType() const; + + /// isCXX11PODType() - Return true if this is a POD type according to the + /// more relaxed rules of the C++11 standard, regardless of the current + /// compilation's language. + /// (C++0x [basic.types]p9) + bool isCXX11PODType() const; + /// Helper methods to distinguish type categories. All type predicates /// operate on the canonical type, ignoring typedefs and qualifiers. @@ -1178,6 +1208,9 @@ public: /// BuiltinTypes. bool isPlaceholderType() const; + /// isSpecificPlaceholderType - Test for a specific placeholder type. + bool isSpecificPlaceholderType(unsigned K) const; + /// isIntegerType() does *not* include complex integers (a GCC extension). /// isComplexIntegerType() can be used to test for complex integers. bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) @@ -1207,6 +1240,8 @@ public: bool isDerivedType() const; // C99 6.2.5p20 bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) bool isAggregateType() const; + bool isFundamentalType() const; + bool isCompoundType() const; // Type Predicates: Check to see if this type is structurally the specified // type, ignoring typedefs and qualifiers. @@ -1321,6 +1356,7 @@ public: // for object declared using an interface. const ObjCObjectPointerType *getAsObjCInterfacePointerType() const; const ObjCObjectPointerType *getAsObjCQualifiedIdType() const; + const ObjCObjectPointerType *getAsObjCQualifiedClassType() const; const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; const CXXRecordDecl *getCXXRecordDeclForPointerType() const; @@ -1475,25 +1511,52 @@ public: NullPtr, // This is the type of C++0x 'nullptr'. + /// The primitive Objective C 'id' type. The user-visible 'id' + /// type is a typedef of an ObjCObjectPointerType to an + /// ObjCObjectType with this as its base. In fact, this only ever + /// shows up in an AST as the base type of an ObjCObjectType. + ObjCId, + + /// The primitive Objective C 'Class' type. The user-visible + /// 'Class' type is a typedef of an ObjCObjectPointerType to an + /// ObjCObjectType with this as its base. In fact, this only ever + /// shows up in an AST as the base type of an ObjCObjectType. + ObjCClass, + + /// The primitive Objective C 'SEL' type. The user-visible 'SEL' + /// type is a typedef of a PointerType to this. + ObjCSel, + /// This represents the type of an expression whose type is /// totally unknown, e.g. 'T::foo'. It is permitted for this to /// appear in situations where the structure of the type is /// theoretically deducible. Dependent, - Overload, // This represents the type of an overloaded function declaration. - - /// The primitive Objective C 'id' type. The type pointed to by the - /// user-visible 'id' type. Only ever shows up in an AST as the base - /// type of an ObjCObjectType. - ObjCId, - - /// The primitive Objective C 'Class' type. The type pointed to by the - /// user-visible 'Class' type. Only ever shows up in an AST as the - /// base type of an ObjCObjectType. - ObjCClass, - - ObjCSel // This represents the ObjC 'SEL' type. + /// The type of an unresolved overload set. A placeholder type. + /// Expressions with this type have one of the following basic + /// forms, with parentheses generally permitted: + /// foo # possibly qualified, not if an implicit access + /// foo # possibly qualified, not if an implicit access + /// &foo # possibly qualified, not if an implicit access + /// x->foo # only if might be a static member function + /// &x->foo # only if might be a static member function + /// &Class::foo # when a pointer-to-member; sub-expr also has this type + /// OverloadExpr::find can be used to analyze the expression. + Overload, + + /// The type of a bound C++ non-static member function. + /// A placeholder type. Expressions with this type have one of the + /// following basic forms: + /// foo # if an implicit access + /// x->foo # if only contains non-static members + BoundMember, + + /// __builtin_any_type. A placeholder type. Useful for clients + /// like debuggers that don't know what type to give something. + /// Only a small number of operations are valid on expressions of + /// unknown type, most notably explicit casts. + UnknownAny }; public: @@ -1526,11 +1589,11 @@ public: return getKind() >= Float && getKind() <= LongDouble; } - /// Determines whether this type is a "forbidden" placeholder type, - /// i.e. a type which cannot appear in arbitrary positions in a - /// fully-formed expression. + /// Determines whether this type is a placeholder type, i.e. a type + /// which cannot appear in arbitrary positions in a fully-formed + /// expression. bool isPlaceholderType() const { - return getKind() == Overload; + return getKind() >= Overload; } static bool classof(const Type *T) { return T->getTypeClass() == Builtin; } @@ -1991,7 +2054,7 @@ public: friend class StmtIteratorBase; void Profile(llvm::FoldingSetNodeID &ID) { - assert(0 && "Cannnot unique VariableArrayTypes."); + assert(0 && "Cannot unique VariableArrayTypes."); } }; @@ -2257,12 +2320,13 @@ class FunctionType : public Type { // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. - // | CC |noreturn|regparm - // |0 .. 2| 3 |4 .. 6 + // | CC |noreturn|hasregparm|regparm + // |0 .. 2| 3 | 4 |5 .. 7 enum { CallConvMask = 0x7 }; enum { NoReturnMask = 0x8 }; + enum { HasRegParmMask = 0x10 }; enum { RegParmMask = ~(CallConvMask | NoReturnMask), - RegParmOffset = 4 }; + RegParmOffset = 5 }; unsigned char Bits; @@ -2273,9 +2337,10 @@ class FunctionType : public Type { public: // Constructor with no defaults. Use this when you know that you // have all the elements (when reading an AST file for example). - ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) { + ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc) { Bits = ((unsigned) cc) | (noReturn ? NoReturnMask : 0) | + (hasRegParm ? HasRegParmMask : 0) | (regParm << RegParmOffset); } @@ -2284,6 +2349,7 @@ class FunctionType : public Type { ExtInfo() : Bits(0) {} bool getNoReturn() const { return Bits & NoReturnMask; } + bool getHasRegParm() const { return Bits & HasRegParmMask; } unsigned getRegParm() const { return Bits >> RegParmOffset; } CallingConv getCC() const { return CallingConv(Bits & CallConvMask); } @@ -2305,7 +2371,7 @@ class FunctionType : public Type { } ExtInfo withRegParm(unsigned RegParm) const { - return ExtInfo((Bits & ~RegParmMask) | (RegParm << RegParmOffset)); + return ExtInfo(HasRegParmMask | (Bits & ~RegParmMask) | (RegParm << RegParmOffset)); } ExtInfo withCallingConv(CallingConv cc) const { @@ -2341,7 +2407,8 @@ protected: public: QualType getResultType() const { return ResultType; } - + + bool getHasRegParm() const { return getExtInfo().getHasRegParm(); } unsigned getRegParmType() const { return getExtInfo().getRegParm(); } bool getNoReturnAttr() const { return getExtInfo().getNoReturn(); } CallingConv getCallConv() const { return getExtInfo().getCC(); } @@ -2403,17 +2470,17 @@ public: /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { ExtProtoInfo() : - Variadic(false), HasExceptionSpec(false), HasAnyExceptionSpec(false), - TypeQuals(0), RefQualifier(RQ_None), NumExceptions(0), Exceptions(0) {} + Variadic(false), ExceptionSpecType(EST_None), TypeQuals(0), + RefQualifier(RQ_None), NumExceptions(0), Exceptions(0), NoexceptExpr(0) {} FunctionType::ExtInfo ExtInfo; bool Variadic; - bool HasExceptionSpec; - bool HasAnyExceptionSpec; + ExceptionSpecificationType ExceptionSpecType; unsigned char TypeQuals; RefQualifierKind RefQualifier; unsigned NumExceptions; const QualType *Exceptions; + Expr *NoexceptExpr; }; private: @@ -2435,13 +2502,10 @@ private: unsigned NumArgs : 20; /// NumExceptions - The number of types in the exception spec, if any. - unsigned NumExceptions : 10; + unsigned NumExceptions : 9; - /// HasExceptionSpec - Whether this function has an exception spec at all. - unsigned HasExceptionSpec : 1; - - /// HasAnyExceptionSpec - Whether this function has a throw(...) spec. - unsigned HasAnyExceptionSpec : 1; + /// ExceptionSpecType - The type of exception specification this function has. + unsigned ExceptionSpecType : 3; /// ArgInfo - There is an variable size array after the class in memory that /// holds the argument types. @@ -2449,6 +2513,9 @@ private: /// Exceptions - There is another variable size array after ArgInfo that /// holds the exception types. + /// NoexceptExpr - Instead of Exceptions, there may be a single Expr* pointing + /// to the expression in the noexcept() specifier. + friend class ASTContext; // ASTContext creates these. public: @@ -2462,29 +2529,66 @@ public: ExtProtoInfo EPI; EPI.ExtInfo = getExtInfo(); EPI.Variadic = isVariadic(); - EPI.HasExceptionSpec = hasExceptionSpec(); - EPI.HasAnyExceptionSpec = hasAnyExceptionSpec(); + EPI.ExceptionSpecType = getExceptionSpecType(); EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals()); EPI.RefQualifier = getRefQualifier(); - EPI.NumExceptions = NumExceptions; - EPI.Exceptions = exception_begin(); + if (EPI.ExceptionSpecType == EST_Dynamic) { + EPI.NumExceptions = NumExceptions; + EPI.Exceptions = exception_begin(); + } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { + EPI.NoexceptExpr = getNoexceptExpr(); + } return EPI; } - bool hasExceptionSpec() const { return HasExceptionSpec; } - bool hasAnyExceptionSpec() const { return HasAnyExceptionSpec; } + /// \brief Get the kind of exception specification on this function. + ExceptionSpecificationType getExceptionSpecType() const { + return static_cast<ExceptionSpecificationType>(ExceptionSpecType); + } + /// \brief Return whether this function has any kind of exception spec. + bool hasExceptionSpec() const { + return getExceptionSpecType() != EST_None; + } + /// \brief Return whether this function has a dynamic (throw) exception spec. + bool hasDynamicExceptionSpec() const { + return isDynamicExceptionSpec(getExceptionSpecType()); + } + /// \brief Return whether this function has a noexcept exception spec. + bool hasNoexceptExceptionSpec() const { + return isNoexceptExceptionSpec(getExceptionSpecType()); + } + /// \brief Result type of getNoexceptSpec(). + enum NoexceptResult { + NR_NoNoexcept, ///< There is no noexcept specifier. + NR_BadNoexcept, ///< The noexcept specifier has a bad expression. + NR_Dependent, ///< The noexcept specifier is dependent. + NR_Throw, ///< The noexcept specifier evaluates to false. + NR_Nothrow ///< The noexcept specifier evaluates to true. + }; + /// \brief Get the meaning of the noexcept spec on this function, if any. + NoexceptResult getNoexceptSpec(ASTContext &Ctx) const; unsigned getNumExceptions() const { return NumExceptions; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); return exception_begin()[i]; } - bool hasEmptyExceptionSpec() const { - return hasExceptionSpec() && !hasAnyExceptionSpec() && - getNumExceptions() == 0; + Expr *getNoexceptExpr() const { + if (getExceptionSpecType() != EST_ComputedNoexcept) + return 0; + // NoexceptExpr sits where the arguments end. + return *reinterpret_cast<Expr *const *>(arg_type_end()); + } + bool isNothrow(ASTContext &Ctx) const { + ExceptionSpecificationType EST = getExceptionSpecType(); + if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) + return true; + if (EST != EST_ComputedNoexcept) + return false; + return getNoexceptSpec(Ctx) == NR_Nothrow; } using FunctionType::isVariadic; - + /// \brief Determines whether this function prototype contains a /// parameter pack at the end. /// @@ -2513,6 +2617,8 @@ public: return arg_type_end(); } exception_iterator exception_end() const { + if (getExceptionSpecType() != EST_Dynamic) + return exception_begin(); return exception_begin() + NumExceptions; } @@ -2524,10 +2630,10 @@ public: } static bool classof(const FunctionProtoType *) { return true; } - void Profile(llvm::FoldingSetNodeID &ID); + void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx); static void Profile(llvm::FoldingSetNodeID &ID, QualType Result, arg_type_iterator ArgTys, unsigned NumArgs, - const ExtProtoInfo &EPI); + const ExtProtoInfo &EPI, const ASTContext &Context); }; @@ -2566,18 +2672,18 @@ public: class TypedefType : public Type { - TypedefDecl *Decl; + TypedefNameDecl *Decl; protected: - TypedefType(TypeClass tc, const TypedefDecl *D, QualType can) + TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast<TypedefDecl*>(D)) { + Decl(const_cast<TypedefNameDecl*>(D)) { assert(!isa<TypedefType>(can) && "Invalid canonical type"); } friend class ASTContext; // ASTContext creates these. public: - TypedefDecl *getDecl() const { return Decl; } + TypedefNameDecl *getDecl() const { return Decl; } bool isSugared() const { return true; } QualType desugar() const; @@ -2807,9 +2913,10 @@ public: // Enumerated operand (string or keyword). attr_objc_gc, + attr_pcs, FirstEnumOperandKind = attr_objc_gc, - LastEnumOperandKind = attr_objc_gc, + LastEnumOperandKind = attr_pcs, // No operand. attr_noreturn, @@ -2864,44 +2971,68 @@ public: }; class TemplateTypeParmType : public Type, public llvm::FoldingSetNode { - unsigned Depth : 15; - unsigned ParameterPack : 1; - unsigned Index : 16; - IdentifierInfo *Name; + // Helper data collector for canonical types. + struct CanonicalTTPTInfo { + unsigned Depth : 15; + unsigned ParameterPack : 1; + unsigned Index : 16; + }; + + union { + // Info for the canonical type. + CanonicalTTPTInfo CanTTPTInfo; + // Info for the non-canonical type. + TemplateTypeParmDecl *TTPDecl; + }; - TemplateTypeParmType(unsigned D, unsigned I, bool PP, IdentifierInfo *N, - QualType Canon) + /// Build a non-canonical type. + TemplateTypeParmType(TemplateTypeParmDecl *TTPDecl, QualType Canon) : Type(TemplateTypeParm, Canon, /*Dependent=*/true, - /*VariablyModified=*/false, PP), - Depth(D), ParameterPack(PP), Index(I), Name(N) { } + /*VariablyModified=*/false, + Canon->containsUnexpandedParameterPack()), + TTPDecl(TTPDecl) { } + /// Build the canonical type. TemplateTypeParmType(unsigned D, unsigned I, bool PP) : Type(TemplateTypeParm, QualType(this, 0), /*Dependent=*/true, - /*VariablyModified=*/false, PP), - Depth(D), ParameterPack(PP), Index(I), Name(0) { } + /*VariablyModified=*/false, PP) { + CanTTPTInfo.Depth = D; + CanTTPTInfo.Index = I; + CanTTPTInfo.ParameterPack = PP; + } friend class ASTContext; // ASTContext creates these + const CanonicalTTPTInfo& getCanTTPTInfo() const { + QualType Can = getCanonicalTypeInternal(); + return Can->castAs<TemplateTypeParmType>()->CanTTPTInfo; + } + public: - unsigned getDepth() const { return Depth; } - unsigned getIndex() const { return Index; } - bool isParameterPack() const { return ParameterPack; } - IdentifierInfo *getName() const { return Name; } + unsigned getDepth() const { return getCanTTPTInfo().Depth; } + unsigned getIndex() const { return getCanTTPTInfo().Index; } + bool isParameterPack() const { return getCanTTPTInfo().ParameterPack; } + + TemplateTypeParmDecl *getDecl() const { + return isCanonicalUnqualified() ? 0 : TTPDecl; + } + + IdentifierInfo *getIdentifier() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Depth, Index, ParameterPack, Name); + Profile(ID, getDepth(), getIndex(), isParameterPack(), getDecl()); } static void Profile(llvm::FoldingSetNodeID &ID, unsigned Depth, unsigned Index, bool ParameterPack, - IdentifierInfo *Name) { + TemplateTypeParmDecl *TTPDecl) { ID.AddInteger(Depth); ID.AddInteger(Index); ID.AddBoolean(ParameterPack); - ID.AddPointer(Name); + ID.AddPointer(TTPDecl); } static bool classof(const Type *T) { @@ -2930,8 +3061,6 @@ class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { friend class ASTContext; public: - IdentifierInfo *getName() const { return Replaced->getName(); } - /// Gets the template parameter that was substituted for. const TemplateTypeParmType *getReplacedParameter() const { return Replaced; @@ -2992,7 +3121,7 @@ class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { friend class ASTContext; public: - IdentifierInfo *getName() const { return Replaced->getName(); } + IdentifierInfo *getIdentifier() const { return Replaced->getIdentifier(); } /// Gets the template parameter that was substituted for. const TemplateTypeParmType *getReplacedParameter() const { @@ -4064,12 +4193,6 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { return getFunctionExtInfo(*t); } -/// \brief Determine whether this set of qualifiers is a superset of the given -/// set of qualifiers. -inline bool Qualifiers::isSupersetOf(Qualifiers Other) const { - return Mask != Other.Mask && (Mask | Other.Mask) == Mask; -} - /// isMoreQualifiedThan - Determine whether this type is more /// qualified than the Other type. For example, "const volatile int" /// is more qualified than "const int", "volatile int", and @@ -4105,6 +4228,40 @@ inline QualType QualType::getNonReferenceType() const { return *this; } +/// \brief Tests whether the type is categorized as a fundamental type. +/// +/// \returns True for types specified in C++0x [basic.fundamental]. +inline bool Type::isFundamentalType() const { + return isVoidType() || + // FIXME: It's really annoying that we don't have an + // 'isArithmeticType()' which agrees with the standard definition. + (isArithmeticType() && !isEnumeralType()); +} + +/// \brief Tests whether the type is categorized as a compound type. +/// +/// \returns True for types specified in C++0x [basic.compound]. +inline bool Type::isCompoundType() const { + // C++0x [basic.compound]p1: + // Compound types can be constructed in the following ways: + // -- arrays of objects of a given type [...]; + return isArrayType() || + // -- functions, which have parameters of given types [...]; + isFunctionType() || + // -- pointers to void or objects or functions [...]; + isPointerType() || + // -- references to objects or functions of a given type. [...] + isReferenceType() || + // -- classes containing a sequence of objects of various types, [...]; + isRecordType() || + // -- unions, which ar classes capable of containing objects of different types at different times; + isUnionType() || + // -- enumerations, which comprise a set of named constant values. [...]; + isEnumeralType() || + // -- pointers to non-static class members, [...]. + isMemberPointerType(); +} + inline bool Type::isFunctionType() const { return isa<FunctionType>(CanonicalType); } @@ -4236,6 +4393,12 @@ inline bool Type::isPlaceholderType() const { return false; } +inline bool Type::isSpecificPlaceholderType(unsigned K) const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + return (BT->getKind() == (BuiltinType::Kind) K); + return false; +} + /// \brief Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index c7f5ee76330c..a1df744c2a72 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -527,7 +527,7 @@ class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TypedefTypeLoc, TypedefType> { public: - TypedefDecl *getTypedefDecl() const { + TypedefNameDecl *getTypedefNameDecl() const { return getTypePtr()->getDecl(); } }; @@ -584,6 +584,8 @@ class TemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TemplateTypeParmTypeLoc, TemplateTypeParmType> { +public: + TemplateTypeParmDecl *getDecl() const { return getTypePtr()->getDecl(); } }; /// \brief Wrapper for substituted template type parameters. @@ -943,10 +945,14 @@ public: } }; +struct MemberPointerLocInfo : public PointerLikeLocInfo { + TypeSourceInfo *ClassTInfo; +}; /// \brief Wrapper for source info for member pointers. class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, - MemberPointerType> { + MemberPointerType, + MemberPointerLocInfo> { public: SourceLocation getStarLoc() const { return getSigilLoc(); @@ -954,6 +960,28 @@ public: void setStarLoc(SourceLocation Loc) { setSigilLoc(Loc); } + + const Type *getClass() const { + return getTypePtr()->getClass(); + } + TypeSourceInfo *getClassTInfo() const { + return getLocalData()->ClassTInfo; + } + void setClassTInfo(TypeSourceInfo* TI) { + getLocalData()->ClassTInfo = TI; + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + setSigilLoc(Loc); + setClassTInfo(0); + } + + SourceRange getLocalSourceRange() const { + if (TypeSourceInfo *TI = getClassTInfo()) + return SourceRange(TI->getTypeLoc().getBeginLoc(), getStarLoc()); + else + return SourceRange(getStarLoc()); + } }; /// Wraps an ObjCPointerType with source location information. @@ -1007,7 +1035,8 @@ public: struct FunctionLocInfo { - SourceLocation LParenLoc, RParenLoc; + SourceLocation LocalRangeBegin; + SourceLocation LocalRangeEnd; bool TrailingReturn; }; @@ -1017,18 +1046,18 @@ class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, FunctionType, FunctionLocInfo> { public: - SourceLocation getLParenLoc() const { - return getLocalData()->LParenLoc; + SourceLocation getLocalRangeBegin() const { + return getLocalData()->LocalRangeBegin; } - void setLParenLoc(SourceLocation Loc) { - getLocalData()->LParenLoc = Loc; + void setLocalRangeBegin(SourceLocation L) { + getLocalData()->LocalRangeBegin = L; } - SourceLocation getRParenLoc() const { - return getLocalData()->RParenLoc; + SourceLocation getLocalRangeEnd() const { + return getLocalData()->LocalRangeEnd; } - void setRParenLoc(SourceLocation Loc) { - getLocalData()->RParenLoc = Loc; + void setLocalRangeEnd(SourceLocation L) { + getLocalData()->LocalRangeEnd = L; } bool getTrailingReturn() const { @@ -1056,12 +1085,12 @@ public: } SourceRange getLocalSourceRange() const { - return SourceRange(getLParenLoc(), getRParenLoc()); + return SourceRange(getLocalRangeBegin(), getLocalRangeEnd()); } void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setLParenLoc(Loc); - setRParenLoc(Loc); + setLocalRangeBegin(Loc); + setLocalRangeEnd(Loc); setTrailingReturn(false); for (unsigned i = 0, e = getNumArgs(); i != e; ++i) setArg(i, NULL); @@ -1388,7 +1417,10 @@ class AutoTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, struct ElaboratedLocInfo { SourceLocation KeywordLoc; - SourceRange QualifierRange; + + /// \brief Opaque data pointer used to reconstruct a nested-name-specifier + /// from + void *QualifierData; }; class ElaboratedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, @@ -1403,27 +1435,29 @@ public: this->getLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; + NestedNameSpecifierLoc getQualifierLoc() const { + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceRange getLocalSourceRange() const { if (getKeywordLoc().isValid()) - if (getQualifierRange().getEnd().isValid()) - return SourceRange(getKeywordLoc(), getQualifierRange().getEnd()); + if (getQualifierLoc()) + return SourceRange(getKeywordLoc(), getQualifierLoc().getEndLoc()); else return SourceRange(getKeywordLoc()); else - return getQualifierRange(); + return getQualifierLoc().getSourceRange(); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); TypeLoc getNamedTypeLoc() const { return getInnerTypeLoc(); @@ -1444,6 +1478,9 @@ public: // type is some sort of TypeDeclTypeLoc. struct DependentNameLocInfo : ElaboratedLocInfo { SourceLocation NameLoc; + + /// \brief Data associated with the nested-name-specifier location. + void *QualifierData; }; class DependentNameTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, @@ -1458,13 +1495,18 @@ public: this->getLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; + NestedNameSpecifierLoc getQualifierLoc() const { + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } - + SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } @@ -1476,7 +1518,7 @@ public: if (getKeywordLoc().isValid()) return SourceRange(getKeywordLoc(), getNameLoc()); else - return SourceRange(getQualifierRange().getBegin(), getNameLoc()); + return SourceRange(getQualifierLoc().getBeginLoc(), getNameLoc()); } void copy(DependentNameTypeLoc Loc) { @@ -1485,16 +1527,11 @@ public: memcpy(Data, Loc.Data, size); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - setNameLoc(Loc); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); }; -// This is exactly the structure of an ElaboratedTypeLoc whose inner -// type is some sort of TemplateSpecializationTypeLoc. struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { + SourceLocation KeywordLoc; SourceLocation LAngleLoc; SourceLocation RAngleLoc; // followed by a TemplateArgumentLocInfo[] @@ -1513,11 +1550,28 @@ public: this->getLocalData()->KeywordLoc = Loc; } - SourceRange getQualifierRange() const { - return this->getLocalData()->QualifierRange; - } - void setQualifierRange(SourceRange Range) { - this->getLocalData()->QualifierRange = Range; + NestedNameSpecifierLoc getQualifierLoc() const { + if (!getLocalData()->QualifierData) + return NestedNameSpecifierLoc(); + + return NestedNameSpecifierLoc(getTypePtr()->getQualifier(), + getLocalData()->QualifierData); + } + + void setQualifierLoc(NestedNameSpecifierLoc QualifierLoc) { + if (!QualifierLoc) { + // Even if we have a nested-name-specifier in the dependent + // template specialization type, we won't record the nested-name-specifier + // location information when this type-source location information is + // part of a nested-name-specifier. + getLocalData()->QualifierData = 0; + return; + } + + assert(QualifierLoc.getNestedNameSpecifier() + == getTypePtr()->getQualifier() && + "Inconsistent nested-name-specifier pointer"); + getLocalData()->QualifierData = QualifierLoc.getOpaqueData(); } SourceLocation getNameLoc() const { @@ -1559,8 +1613,10 @@ public: SourceRange getLocalSourceRange() const { if (getKeywordLoc().isValid()) return SourceRange(getKeywordLoc(), getRAngleLoc()); + else if (getQualifierLoc()) + return SourceRange(getQualifierLoc().getBeginLoc(), getRAngleLoc()); else - return SourceRange(getQualifierRange().getBegin(), getRAngleLoc()); + return SourceRange(getNameLoc(), getRAngleLoc()); } void copy(DependentTemplateSpecializationTypeLoc Loc) { @@ -1569,16 +1625,7 @@ public: memcpy(Data, Loc.Data, size); } - void initializeLocal(ASTContext &Context, SourceLocation Loc) { - setKeywordLoc(Loc); - setQualifierRange(SourceRange(Loc)); - setNameLoc(Loc); - setLAngleLoc(Loc); - setRAngleLoc(Loc); - TemplateSpecializationTypeLoc::initializeArgLocs(Context, getNumArgs(), - getTypePtr()->getArgs(), - getArgInfos(), Loc); - } + void initializeLocal(ASTContext &Context, SourceLocation Loc); unsigned getExtraLocalDataSize() const { return getNumArgs() * sizeof(TemplateArgumentLocInfo); diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h index 72f644aaf028..a61d9e47881d 100644 --- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h +++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h @@ -29,13 +29,13 @@ class CFGBlock; // tend to have a common destination, so we lazily do a predecessor search // from the destination node and cache the results to prevent work // duplication. -class CFGReachabilityAnalysis { +class CFGReverseBlockReachabilityAnalysis { typedef llvm::BitVector ReachableSet; typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap; ReachableSet analyzed; ReachableMap reachable; public: - CFGReachabilityAnalysis(const CFG &cfg); + CFGReverseBlockReachabilityAnalysis(const CFG &cfg); /// Returns true if the block 'Dst' can be reached from block 'Src'. bool isReachable(const CFGBlock *Src, const CFGBlock *Dst); diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index cd771acb06a5..b966f3a90fff 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -1,4 +1,4 @@ -//===- UninitializedValues.h - unintialized values analysis ----*- C++ --*-===// +//= UninitializedValues.h - Finding uses of uninitialized values --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -7,71 +7,35 @@ // //===----------------------------------------------------------------------===// // -// This file provides the interface for the Unintialized Values analysis, -// a flow-sensitive analysis that detects when variable values are unintialized. +// This file defines APIs for invoking and reported uninitialized values +// warnings. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_UNITVALS_H -#define LLVM_CLANG_UNITVALS_H - -#include "clang/Analysis/Support/BlkExprDeclBitVector.h" -#include "clang/Analysis/FlowSensitive/DataflowValues.h" +#ifndef LLVM_CLANG_UNINIT_VALS_H +#define LLVM_CLANG_UNINIT_VALS_H namespace clang { - class BlockVarDecl; - class Expr; - class DeclRefExpr; - class VarDecl; - -/// UninitializedValues_ValueTypes - Utility class to wrap type declarations -/// for dataflow values and dataflow analysis state for the -/// Unitialized Values analysis. -class UninitializedValues_ValueTypes { -public: - - struct ObserverTy; - - struct AnalysisDataTy : public StmtDeclBitVector_Types::AnalysisDataTy { - AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {} - virtual ~AnalysisDataTy() {} - - ObserverTy* Observer; - bool FullUninitTaint; - }; - - typedef StmtDeclBitVector_Types::ValTy ValTy; - - //===--------------------------------------------------------------------===// - // ObserverTy - Observer for querying DeclRefExprs that use an uninitalized - // value. - //===--------------------------------------------------------------------===// - - struct ObserverTy { - virtual ~ObserverTy(); - virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD, - DeclRefExpr* DR, VarDecl* VD) = 0; - }; -}; - -/// UninitializedValues - Objects of this class encapsulate dataflow analysis -/// information regarding what variable declarations in a function are -/// potentially unintialized. -class UninitializedValues : - public DataflowValues<UninitializedValues_ValueTypes> { +class AnalysisContext; +class CFG; +class DeclContext; +class Expr; +class VarDecl; + +class UninitVariablesHandler { public: - typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy; - - UninitializedValues(CFG &cfg) { getAnalysisData().setCFG(cfg); } - - /// IntializeValues - Create initial dataflow values and meta data for - /// a given CFG. This is intended to be called by the dataflow solver. - void InitializeValues(const CFG& cfg); + UninitVariablesHandler() {} + virtual ~UninitVariablesHandler(); + + virtual void handleUseOfUninitVariable(const Expr *ex, + const VarDecl *vd, + bool isAlwaysUninit) {} }; + +void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, + AnalysisContext &ac, + UninitVariablesHandler &handler); - -void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags, - bool FullUninitTaint=false); -} // end namespace clang +} #endif diff --git a/include/clang/Analysis/Analyses/UninitializedValuesV2.h b/include/clang/Analysis/Analyses/UninitializedValuesV2.h deleted file mode 100644 index c1fe040793e1..000000000000 --- a/include/clang/Analysis/Analyses/UninitializedValuesV2.h +++ /dev/null @@ -1,40 +0,0 @@ -//= UninitializedValuesV2.h - Finding uses of uninitialized values --*- 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 APIs for invoking and reported uninitialized values -// warnings. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_UNINIT_VALS_H -#define LLVM_CLANG_UNINIT_VALS_H - -namespace clang { - -class AnalysisContext; -class CFG; -class DeclContext; -class Expr; -class VarDecl; - -class UninitVariablesHandler { -public: - UninitVariablesHandler() {} - virtual ~UninitVariablesHandler(); - - virtual void handleUseOfUninitVariable(const Expr *ex, - const VarDecl *vd) {} -}; - -void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, - AnalysisContext &ac, - UninitVariablesHandler &handler); - -} -#endif diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 851451457881..66c12a5384d4 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/Analysis/CFG.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" @@ -27,9 +28,7 @@ namespace clang { class Decl; class Stmt; -class CFG; -class CFGBlock; -class CFGReachabilityAnalysis; +class CFGReverseBlockReachabilityAnalysis; class CFGStmtMap; class LiveVariables; class ParentMap; @@ -48,33 +47,32 @@ class AnalysisContext { // TranslationUnit is NULL if we don't have multiple translation units. idx::TranslationUnit *TU; - // AnalysisContext owns the following data. - CFG *cfg, *completeCFG; - CFGStmtMap *cfgStmtMap; + llvm::OwningPtr<CFG> cfg, completeCFG; + llvm::OwningPtr<CFGStmtMap> cfgStmtMap; + + CFG::BuildOptions cfgBuildOptions; + CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; + bool builtCFG, builtCompleteCFG; - LiveVariables *liveness; - LiveVariables *relaxedLiveness; - ParentMap *PM; - PseudoConstantAnalysis *PCA; - CFGReachabilityAnalysis *CFA; - llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; + const bool useUnoptimizedCFG; + + llvm::OwningPtr<LiveVariables> liveness; + llvm::OwningPtr<LiveVariables> relaxedLiveness; + llvm::OwningPtr<ParentMap> PM; + llvm::OwningPtr<PseudoConstantAnalysis> PCA; + llvm::OwningPtr<CFGReverseBlockReachabilityAnalysis> CFA; + llvm::BumpPtrAllocator A; - bool UseUnoptimizedCFG; - bool AddEHEdges; - bool AddImplicitDtors; - bool AddInitializers; + + // FIXME: remove. + llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; + public: AnalysisContext(const Decl *d, idx::TranslationUnit *tu, bool useUnoptimizedCFG = false, bool addehedges = false, bool addImplicitDtors = false, - bool addInitializers = false) - : D(d), TU(tu), cfg(0), completeCFG(0), cfgStmtMap(0), - builtCFG(false), builtCompleteCFG(false), - liveness(0), relaxedLiveness(0), PM(0), PCA(0), CFA(0), - ReferencedBlockVars(0), UseUnoptimizedCFG(useUnoptimizedCFG), - AddEHEdges(addehedges), AddImplicitDtors(addImplicitDtors), - AddInitializers(addInitializers) {} + bool addInitializers = false); ~AnalysisContext(); @@ -87,18 +85,22 @@ public: /// callExprs. If this is false, then try/catch statements and blocks /// reachable from them can appear to be dead in the CFG, analysis passes must /// cope with that. - bool getAddEHEdges() const { return AddEHEdges; } - - bool getUseUnoptimizedCFG() const { return UseUnoptimizedCFG; } - bool getAddImplicitDtors() const { return AddImplicitDtors; } - bool getAddInitializers() const { return AddInitializers; } + bool getAddEHEdges() const { return cfgBuildOptions.AddEHEdges; } + bool getUseUnoptimizedCFG() const { + return cfgBuildOptions.PruneTriviallyFalseEdges; + } + bool getAddImplicitDtors() const { return cfgBuildOptions.AddImplicitDtors; } + bool getAddInitializers() const { return cfgBuildOptions.AddInitializers; } + void registerForcedBlockExpression(const Stmt *stmt); + const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); + Stmt *getBody(); CFG *getCFG(); CFGStmtMap *getCFGStmtMap(); - CFGReachabilityAnalysis *getCFGReachablityAnalysis(); + CFGReverseBlockReachabilityAnalysis *getCFGReachablityAnalysis(); /// Return a version of the CFG without any edges pruned. CFG *getUnoptimizedCFG(); diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h index 295d0a2133d3..dbf4e4c9aefe 100644 --- a/include/clang/Analysis/AnalysisDiagnostic.h +++ b/include/clang/Analysis/AnalysisDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define ANALYSISSTART #include "clang/Basic/DiagnosticAnalysisKinds.inc" #undef DIAG diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index b337d74495c9..ca46459afd9a 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -19,6 +19,8 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Casting.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/DenseMap.h" #include "clang/Analysis/Support/BumpVector.h" #include "clang/Basic/SourceLocation.h" #include <cassert> @@ -29,6 +31,7 @@ namespace llvm { } namespace clang { + class CXXDestructorDecl; class Decl; class Stmt; class Expr; @@ -47,45 +50,45 @@ class CFGElement { public: enum Kind { // main kind + Invalid, Statement, Initializer, - ImplicitDtor, // dtor kind AutomaticObjectDtor, BaseDtor, MemberDtor, TemporaryDtor, - DTOR_BEGIN = AutomaticObjectDtor + DTOR_BEGIN = AutomaticObjectDtor, + DTOR_END = TemporaryDtor }; protected: - // The int bits are used to mark the main kind. + // The int bits are used to mark the kind. llvm::PointerIntPair<void *, 2> Data1; - // The int bits are used to mark the dtor kind. llvm::PointerIntPair<void *, 2> Data2; - CFGElement(void *Ptr, unsigned Int) : Data1(Ptr, Int) {} - CFGElement(void *Ptr1, unsigned Int1, void *Ptr2, unsigned Int2) - : Data1(Ptr1, Int1), Data2(Ptr2, Int2) {} + CFGElement(Kind kind, const void *Ptr1, const void *Ptr2 = 0) + : Data1(const_cast<void*>(Ptr1), ((unsigned) kind) & 0x3), + Data2(const_cast<void*>(Ptr2), (((unsigned) kind) >> 2) & 0x3) {} public: CFGElement() {} - Kind getKind() const { return static_cast<Kind>(Data1.getInt()); } - - Kind getDtorKind() const { - assert(getKind() == ImplicitDtor); - return static_cast<Kind>(Data2.getInt() + DTOR_BEGIN); + Kind getKind() const { + unsigned x = Data2.getInt(); + x <<= 2; + x |= Data1.getInt(); + return (Kind) x; } - - bool isValid() const { return Data1.getPointer(); } + + bool isValid() const { return getKind() != Invalid; } operator bool() const { return isValid(); } - - template<class ElemTy> ElemTy getAs() const { + + template<class ElemTy> const ElemTy *getAs() const { if (llvm::isa<ElemTy>(this)) - return *static_cast<const ElemTy*>(this); - return ElemTy(); + return static_cast<const ElemTy*>(this); + return 0; } static bool classof(const CFGElement *E) { return true; } @@ -93,13 +96,10 @@ public: class CFGStmt : public CFGElement { public: - CFGStmt() {} - CFGStmt(Stmt *S) : CFGElement(S, 0) {} + CFGStmt(Stmt *S) : CFGElement(Statement, S) {} Stmt *getStmt() const { return static_cast<Stmt *>(Data1.getPointer()); } - operator Stmt*() const { return getStmt(); } - static bool classof(const CFGElement *E) { return E->getKind() == Statement; } @@ -109,14 +109,12 @@ public: /// constructor's initialization list. class CFGInitializer : public CFGElement { public: - CFGInitializer() {} - CFGInitializer(CXXCtorInitializer* I) - : CFGElement(I, Initializer) {} + CFGInitializer(CXXCtorInitializer *initializer) + : CFGElement(Initializer, initializer) {} CXXCtorInitializer* getInitializer() const { return static_cast<CXXCtorInitializer*>(Data1.getPointer()); } - operator CXXCtorInitializer*() const { return getInitializer(); } static bool classof(const CFGElement *E) { return E->getKind() == Initializer; @@ -127,14 +125,18 @@ public: /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { protected: - CFGImplicitDtor(unsigned K, void* P, void* S) - : CFGElement(P, ImplicitDtor, S, K - DTOR_BEGIN) {} + CFGImplicitDtor(Kind kind, const void *data1, const void *data2 = 0) + : CFGElement(kind, data1, data2) { + assert(kind >= DTOR_BEGIN && kind <= DTOR_END); + } public: - CFGImplicitDtor() {} + const CXXDestructorDecl *getDestructorDecl(ASTContext &astContext) const; + bool isNoReturn(ASTContext &astContext) const; static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor; + Kind kind = E->getKind(); + return kind >= DTOR_BEGIN && kind <= DTOR_END; } }; @@ -143,22 +145,20 @@ public: /// of leaving its local scope. class CFGAutomaticObjDtor: public CFGImplicitDtor { public: - CFGAutomaticObjDtor() {} - CFGAutomaticObjDtor(VarDecl* VD, Stmt* S) - : CFGImplicitDtor(AutomaticObjectDtor, VD, S) {} + CFGAutomaticObjDtor(const VarDecl *var, const Stmt *stmt) + : CFGImplicitDtor(AutomaticObjectDtor, var, stmt) {} - VarDecl* getVarDecl() const { + const VarDecl *getVarDecl() const { return static_cast<VarDecl*>(Data1.getPointer()); } // Get statement end of which triggered the destructor call. - Stmt* getTriggerStmt() const { + const Stmt *getTriggerStmt() const { return static_cast<Stmt*>(Data2.getPointer()); } - static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && - E->getDtorKind() == AutomaticObjectDtor; + static bool classof(const CFGElement *elem) { + return elem->getKind() == AutomaticObjectDtor; } }; @@ -166,16 +166,15 @@ public: /// base object in destructor. class CFGBaseDtor : public CFGImplicitDtor { public: - CFGBaseDtor() {} - CFGBaseDtor(const CXXBaseSpecifier *BS) - : CFGImplicitDtor(BaseDtor, const_cast<CXXBaseSpecifier*>(BS), NULL) {} + CFGBaseDtor(const CXXBaseSpecifier *base) + : CFGImplicitDtor(BaseDtor, base) {} const CXXBaseSpecifier *getBaseSpecifier() const { return static_cast<const CXXBaseSpecifier*>(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == BaseDtor; + return E->getKind() == BaseDtor; } }; @@ -183,16 +182,15 @@ public: /// member object in destructor. class CFGMemberDtor : public CFGImplicitDtor { public: - CFGMemberDtor() {} - CFGMemberDtor(FieldDecl *FD) - : CFGImplicitDtor(MemberDtor, FD, NULL) {} + CFGMemberDtor(const FieldDecl *field) + : CFGImplicitDtor(MemberDtor, field, 0) {} - FieldDecl *getFieldDecl() const { - return static_cast<FieldDecl*>(Data1.getPointer()); + const FieldDecl *getFieldDecl() const { + return static_cast<const FieldDecl*>(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == MemberDtor; + return E->getKind() == MemberDtor; } }; @@ -200,16 +198,15 @@ public: /// at the end of full expression for temporary object. class CFGTemporaryDtor : public CFGImplicitDtor { public: - CFGTemporaryDtor() {} - CFGTemporaryDtor(CXXBindTemporaryExpr *E) - : CFGImplicitDtor(TemporaryDtor, E, NULL) {} + CFGTemporaryDtor(CXXBindTemporaryExpr *expr) + : CFGImplicitDtor(TemporaryDtor, expr, 0) {} - CXXBindTemporaryExpr *getBindTemporaryExpr() const { - return static_cast<CXXBindTemporaryExpr *>(Data1.getPointer()); + const CXXBindTemporaryExpr *getBindTemporaryExpr() const { + return static_cast<const CXXBindTemporaryExpr *>(Data1.getPointer()); } static bool classof(const CFGElement *E) { - return E->getKind() == ImplicitDtor && E->getDtorKind() == TemporaryDtor; + return E->getKind() == TemporaryDtor; } }; @@ -267,6 +264,8 @@ public: /// ? operator LHS expression; RHS expression /// &&, || expression that uses result of && or ||, RHS /// +/// But note that any of that may be NULL in case of optimized-out edges. +/// class CFGBlock { class ElementList { typedef BumpVector<CFGElement> ImplTy; @@ -471,8 +470,6 @@ public: const Stmt *getLoopTarget() const { return LoopTarget; } - bool hasBinaryBranchTerminator() const; - Stmt* getLabel() { return Label; } const Stmt* getLabel() const { return Label; } @@ -537,13 +534,16 @@ public: class BuildOptions { public: + typedef llvm::DenseMap<const Stmt *, const CFGBlock*> ForcedBlkExprs; + ForcedBlkExprs **forcedBlkExprs; + bool PruneTriviallyFalseEdges:1; bool AddEHEdges:1; bool AddInitializers:1; bool AddImplicitDtors:1; BuildOptions() - : PruneTriviallyFalseEdges(true) + : forcedBlkExprs(0), PruneTriviallyFalseEdges(true) , AddEHEdges(false) , AddInitializers(false) , AddImplicitDtors(false) {} @@ -552,7 +552,7 @@ public: /// buildCFG - Builds a CFG from an AST. The responsibility to free the /// constructed CFG belongs to the caller. static CFG* buildCFG(const Decl *D, Stmt* AST, ASTContext *C, - BuildOptions BO = BuildOptions()); + const BuildOptions &BO); /// createBlock - Create a new block in the CFG. The CFG owns the block; /// the caller should not directly free it. @@ -607,8 +607,8 @@ public: for (const_iterator I=begin(), E=end(); I != E; ++I) for (CFGBlock::const_iterator BI=(*I)->begin(), BE=(*I)->end(); BI != BE; ++BI) { - if (CFGStmt S = BI->getAs<CFGStmt>()) - O(S); + if (const CFGStmt *stmt = BI->getAs<CFGStmt>()) + O(stmt->getStmt()); } } diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h index 7e6e3815400c..18e81fed79f8 100644 --- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h +++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h @@ -22,7 +22,7 @@ namespace cocoa { enum NamingConvention { NoConvention, CreateRule, InitRule }; - NamingConvention deriveNamingConvention(Selector S, bool ignorePrefix = true); + NamingConvention deriveNamingConvention(Selector S); static inline bool followsFundamentalRule(Selector S) { return deriveNamingConvention(S) == CreateRule; diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index d75d333db6b6..9561b964b5f8 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -277,8 +277,8 @@ private: for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) { CFGElement El = *I; - if (CFGStmt S = El.getAs<CFGStmt>()) - ProcessStmt(S, recordStmtValues, AnalysisDirTag()); + if (const CFGStmt *S = El.getAs<CFGStmt>()) + ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag()); } TF.VisitTerminator(const_cast<CFGBlock*>(B)); @@ -293,8 +293,8 @@ private: for (StmtItr I=ItrTraits::StmtBegin(B), E=ItrTraits::StmtEnd(B); I!=E;++I) { CFGElement El = *I; - if (CFGStmt S = El.getAs<CFGStmt>()) - ProcessStmt(S, recordStmtValues, AnalysisDirTag()); + if (const CFGStmt *S = El.getAs<CFGStmt>()) + ProcessStmt(S->getStmt(), recordStmtValues, AnalysisDirTag()); } } diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 54cfc3dc0db6..07b4dea987de 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -43,6 +43,7 @@ public: PostStoreKind, PostPurgeDeadSymbolsKind, PostStmtCustomKind, + PostConditionKind, PostLValueKind, PostInitializerKind, CallEnterKind, @@ -221,7 +222,17 @@ public: } }; - +// PostCondition represents the post program point of a branch condition. +class PostCondition : public PostStmt { +public: + PostCondition(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostConditionKind, L, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostConditionKind; + } +}; + class LocationCheck : public StmtPoint { protected: LocationCheck(const Stmt *S, const LocationContext *L, diff --git a/include/clang/Analysis/Visitors/CFGStmtVisitor.h b/include/clang/Analysis/Visitors/CFGStmtVisitor.h index d197e69babde..7fb4ab3ebad9 100644 --- a/include/clang/Analysis/Visitors/CFGStmtVisitor.h +++ b/include/clang/Analysis/Visitors/CFGStmtVisitor.h @@ -82,6 +82,7 @@ public: DISPATCH_CASE(ConditionalOperator) DISPATCH_CASE(BinaryConditionalOperator) DISPATCH_CASE(ObjCForCollectionStmt) + DISPATCH_CASE(CXXForRangeStmt) case Stmt::BinaryOperatorClass: { BinaryOperator* B = cast<BinaryOperator>(S); @@ -109,6 +110,10 @@ public: return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); } + RetTy BlockStmt_VisitCXXForRangeStmt(CXXForRangeStmt* S) { + return static_cast<ImplClass*>(this)->BlockStmt_VisitStmt(S); + } + RetTy BlockStmt_VisitImplicitControlFlowExpr(Expr* E) { return static_cast<ImplClass*>(this)->BlockStmt_VisitExpr(E); } diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h new file mode 100644 index 000000000000..d44a9c3b0361 --- /dev/null +++ b/include/clang/Basic/AddressSpaces.h @@ -0,0 +1,44 @@ +//===--- AddressSpaces.h - Language-specific address spaces -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides definitions for the various language-specific address +// spaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H +#define LLVM_CLANG_BASIC_ADDRESSSPACES_H + +namespace clang { + +namespace LangAS { + +/// This enum defines the set of possible language-specific address spaces. +/// It uses a high starting offset so as not to conflict with any address +/// space used by a target. +enum ID { + Offset = 0xFFFF00, + + opencl_global = Offset, + opencl_local, + opencl_constant, + + Last, + Count = Last-Offset +}; + +/// The type of a lookup table which maps from language-specific address spaces +/// to target-specific ones. +typedef unsigned Map[Count]; + +} + +} + +#endif diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 3e62d411d51a..e4c6722e8378 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -46,6 +46,7 @@ class Argument<string name> { string Name = name; } +class BoolArgument<string name> : Argument<name>; class IdentifierArgument<string name> : Argument<name>; class IntArgument<string name> : Argument<name>; class StringArgument<string name> : Argument<name>; @@ -55,6 +56,9 @@ class TypeArgument<string name> : Argument<name>; class UnsignedArgument<string name> : Argument<name>; class VariadicUnsignedArgument<string name> : Argument<name>; +// A version of the form major.minor[.subminor]. +class VersionArgument<string name> : Argument<name>; + // This one's a doozy, so it gets its own special type // It can be an unsigned integer, or a type. Either can // be dependent. @@ -89,8 +93,13 @@ class Attr { code AdditionalMembers = [{}]; } +/// An inheritable attribute is inherited by later redeclarations. class InheritableAttr : Attr; +/// An inheritable parameter attribute is inherited by later +/// redeclarations, even when it's written on a parameter. +class InheritableParamAttr : InheritableAttr; + // // Attributes begin here // @@ -129,12 +138,26 @@ def AsmLabel : InheritableAttr { let Args = [StringArgument<"Label">]; } +def Availability : InheritableAttr { + let Spellings = ["availability"]; + let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">, + VersionArgument<"deprecated">, VersionArgument<"obsoleted">, + BoolArgument<"unavailable">]; + let AdditionalMembers = +[{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) { + return llvm::StringSwitch<llvm::StringRef>(Platform) + .Case("ios", "iOS") + .Case("macosx", "Mac OS X") + .Default(llvm::StringRef()); +} }]; +} + def Blocks : InheritableAttr { let Spellings = ["blocks"]; let Args = [EnumArgument<"Type", "BlockType", ["byref"], ["ByRef"]>]; } -def CarriesDependency : InheritableAttr { +def CarriesDependency : InheritableParamAttr { let Spellings = ["carries_dependency"]; let Subjects = [ParmVar, Function]; let Namespaces = ["", "std"]; @@ -154,7 +177,7 @@ def CFReturnsNotRetained : InheritableAttr { let Subjects = [ObjCMethod, Function]; } -def CFConsumed : InheritableAttr { +def CFConsumed : InheritableParamAttr { let Spellings = ["cf_consumed"]; let Subjects = [ParmVar]; } @@ -224,10 +247,6 @@ def DLLImport : InheritableAttr { let Spellings = ["dllimport"]; } -def Explicit : InheritableAttr { - let Spellings = []; -} - def FastCall : InheritableAttr { let Spellings = ["fastcall", "__fastcall"]; } @@ -236,6 +255,10 @@ def Final : InheritableAttr { let Spellings = []; } +def MsStruct : InheritableAttr { + let Spellings = ["__ms_struct__"]; +} + def Format : InheritableAttr { let Spellings = ["format"]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, @@ -261,7 +284,7 @@ def IBOutlet : InheritableAttr { def IBOutletCollection : InheritableAttr { let Spellings = ["iboutletcollection"]; - let Args = [TypeArgument<"Interface">]; + let Args = [TypeArgument<"InterFace">]; } def Malloc : InheritableAttr { @@ -355,7 +378,7 @@ def NSConsumesSelf : InheritableAttr { let Subjects = [ObjCMethod]; } -def NSConsumed : InheritableAttr { +def NSConsumed : InheritableParamAttr { let Spellings = ["ns_consumed"]; let Subjects = [ParmVar]; } @@ -364,6 +387,15 @@ def ObjCException : InheritableAttr { let Spellings = ["objc_exception"]; } +def ObjCMethodFamily : InheritableAttr { + let Spellings = ["objc_method_family"]; + let Subjects = [ObjCMethod]; + let Args = [EnumArgument<"Family", "FamilyKind", + ["none", "alloc", "copy", "init", "mutableCopy", "new"], + ["OMF_None", "OMF_alloc", "OMF_copy", "OMF_init", + "OMF_mutableCopy", "OMF_new"]>]; +} + def ObjCNSObject : InheritableAttr { let Spellings = ["NSObject"]; } @@ -388,6 +420,13 @@ def Packed : InheritableAttr { let Spellings = ["packed"]; } +def Pcs : InheritableAttr { + let Spellings = ["pcs"]; + let Args = [EnumArgument<"PCS", "PCSType", + ["aapcs", "aapcs-vfp"], + ["AAPCS", "AAPCS_VFP"]>]; +} + def Pure : InheritableAttr { let Spellings = ["pure"]; } diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h index 65c4f98c952c..9d5ae588c50f 100644 --- a/include/clang/Basic/AttrKinds.h +++ b/include/clang/Basic/AttrKinds.h @@ -22,6 +22,7 @@ namespace attr { enum Kind { #define ATTR(X) X, #define LAST_INHERITABLE_ATTR(X) X, LAST_INHERITABLE = X, +#define LAST_INHERITABLE_PARAM_ATTR(X) X, LAST_INHERITABLE_PARAM = X, #include "clang/Basic/AttrList.inc" NUM_ATTRS }; diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index b73ac1f4dd45..9a4c768dc649 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -443,7 +443,7 @@ BUILTIN(__builtin_dwarf_sp_column, "Ui", "n") BUILTIN(__builtin_extend_pointer, "ULLiv*", "n") // _Unwind_Word == uint64_t // GCC Object size checking builtins -BUILTIN(__builtin_object_size, "zv*i", "n") +BUILTIN(__builtin_object_size, "zvC*i", "n") BUILTIN(__builtin___memcpy_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___memmove_chk, "v*v*vC*zz", "nF") BUILTIN(__builtin___mempcpy_chk, "v*v*vC*zz", "nF") @@ -577,6 +577,13 @@ BUILTIN(__sync_lock_release_4, "viD*.", "n") BUILTIN(__sync_lock_release_8, "vLLiD*.", "n") BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n") +BUILTIN(__sync_swap, "v.", "") +BUILTIN(__sync_swap_1, "ccD*c.", "n") +BUILTIN(__sync_swap_2, "ssD*s.", "n") +BUILTIN(__sync_swap_4, "iiD*i.", "n") +BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "n") +BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "n") + // Non-overloaded atomic builtins. diff --git a/include/clang/Basic/BuiltinsPTX.def b/include/clang/Basic/BuiltinsPTX.def new file mode 100644 index 000000000000..f90a43f7f404 --- /dev/null +++ b/include/clang/Basic/BuiltinsPTX.def @@ -0,0 +1,62 @@ +//===--- BuiltinsPTX.def - PTX Builtin function database ----*- 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 PTX-specific builtin function database. Users of +// this file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +BUILTIN(__builtin_ptx_read_tid_x, "i", "nc") +BUILTIN(__builtin_ptx_read_tid_y, "i", "nc") +BUILTIN(__builtin_ptx_read_tid_z, "i", "nc") +BUILTIN(__builtin_ptx_read_tid_w, "i", "nc") + +BUILTIN(__builtin_ptx_read_ntid_x, "i", "nc") +BUILTIN(__builtin_ptx_read_ntid_y, "i", "nc") +BUILTIN(__builtin_ptx_read_ntid_z, "i", "nc") +BUILTIN(__builtin_ptx_read_ntid_w, "i", "nc") + +BUILTIN(__builtin_ptx_read_ctaid_x, "i", "nc") +BUILTIN(__builtin_ptx_read_ctaid_y, "i", "nc") +BUILTIN(__builtin_ptx_read_ctaid_z, "i", "nc") +BUILTIN(__builtin_ptx_read_ctaid_w, "i", "nc") + +BUILTIN(__builtin_ptx_read_nctaid_x, "i", "nc") +BUILTIN(__builtin_ptx_read_nctaid_y, "i", "nc") +BUILTIN(__builtin_ptx_read_nctaid_z, "i", "nc") +BUILTIN(__builtin_ptx_read_nctaid_w, "i", "nc") + +BUILTIN(__builtin_ptx_read_laneid, "i", "nc") +BUILTIN(__builtin_ptx_read_warpid, "i", "nc") +BUILTIN(__builtin_ptx_read_nwarpid, "i", "nc") + +BUILTIN(__builtin_ptx_read_smid, "i", "nc") +BUILTIN(__builtin_ptx_read_nsmid, "i", "nc") +BUILTIN(__builtin_ptx_read_gridid, "i", "nc") + +BUILTIN(__builtin_ptx_read_lanemask_eq, "i", "nc") +BUILTIN(__builtin_ptx_read_lanemask_le, "i", "nc") +BUILTIN(__builtin_ptx_read_lanemask_lt, "i", "nc") +BUILTIN(__builtin_ptx_read_lanemask_ge, "i", "nc") +BUILTIN(__builtin_ptx_read_lanemask_gt, "i", "nc") + +BUILTIN(__builtin_ptx_read_clock, "i", "n") +BUILTIN(__builtin_ptx_read_clock64, "Li", "n") + +BUILTIN(__builtin_ptx_read_pm0, "i", "n") +BUILTIN(__builtin_ptx_read_pm1, "i", "n") +BUILTIN(__builtin_ptx_read_pm2, "i", "n") +BUILTIN(__builtin_ptx_read_pm3, "i", "n") + +BUILTIN(__builtin_ptx_bar_sync, "vi", "n") + + +#undef BUILTIN diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index da106daf26ec..2c2a84ab30ae 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -24,6 +24,37 @@ // FIXME: Are these nothrow/const? +// 3DNow! +// +BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc") +BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc") +BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc") +BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc") +// GCC has pfrsqrtit1, even though this is not the name of the instruction. +BUILTIN(__builtin_ia32_pfrsqrtit1, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc") +BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc") +// 3DNow! Extensions. +BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc") +BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc") +BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "nc") +BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "nc") +BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc") + // MMX // // FIXME: All MMX instructions will be generated via builtins. Any MMX vector @@ -209,7 +240,6 @@ BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "") BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "") BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "") BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "") -BUILTIN(__builtin_ia32_loadups, "V4ffC*", "") BUILTIN(__builtin_ia32_storeups, "vf*V4f", "") BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "") BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "") @@ -223,7 +253,6 @@ BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "") BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "") BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "") BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "") -BUILTIN(__builtin_ia32_loadupd, "V2ddC*", "") BUILTIN(__builtin_ia32_storeupd, "vd*V2d", "") BUILTIN(__builtin_ia32_movmskpd, "iV2d", "") BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "") @@ -342,10 +371,10 @@ BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16cic","") BUILTIN(__builtin_ia32_pcmpgtq, "V2LLiV2LLiV2LLi", "") -BUILTIN(__builtin_ia32_crc32qi, "iic", "") -BUILTIN(__builtin_ia32_crc32hi, "iis", "") -BUILTIN(__builtin_ia32_crc32si, "iii", "") -BUILTIN(__builtin_ia32_crc32di, "LLiLLiLLi", "") +BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "") +BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "") +BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "") +BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "") // AES BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "") diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index 19066e4c0eef..df49dc6a1c9f 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -17,6 +17,10 @@ clang_tablegen(DiagnosticGroups.inc -gen-clang-diag-groups SOURCE Diagnostic.td TARGET ClangDiagnosticGroups) +clang_tablegen(DiagnosticIndexName.inc -gen-clang-diags-index-name + SOURCE Diagnostic.td + TARGET ClangDiagnosticIndexName) + clang_tablegen(AttrList.inc -gen-clang-attr-list -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE Attr.td diff --git a/include/clang/Basic/ConvertUTF.h b/include/clang/Basic/ConvertUTF.h index 4da2ad757223..d928f9d0f66b 100644 --- a/include/clang/Basic/ConvertUTF.h +++ b/include/clang/Basic/ConvertUTF.h @@ -87,6 +87,9 @@ ------------------------------------------------------------------------ */ +#ifndef CLANG_BASIC_CONVERTUTF_H +#define CLANG_BASIC_CONVERTUTF_H + /* --------------------------------------------------------------------- The following 4 definitions are compiler-specific. The C standard does not guarantee that wchar_t has at least @@ -156,4 +159,6 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd); } #endif +#endif + /* --------------------------------------------------------------------- */ diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 2ec7427cf758..9e69492e13c7 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -17,7 +17,9 @@ def Named : Decl<1>; def NamespaceAlias : DDecl<Named>; def Label : DDecl<Named>; def Type : DDecl<Named, 1>; - def Typedef : DDecl<Type>; + def TypedefName : DDecl<Type, 1>; + def Typedef : DDecl<TypedefName>; + def TypeAlias : DDecl<TypedefName>; def UnresolvedUsingTypename : DDecl<Type>; def Tag : DDecl<Type, 1>, DeclContext; def Enum : DDecl<Tag>; diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 3fc60d136b5c..7fc400f31bb0 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -585,7 +585,7 @@ private: /// DiagArgumentsVal - The values for the various substitution positions. This /// is used when the argument is not an std::string. The specific value is - /// mangled into an intptr_t and the intepretation depends on exactly what + /// mangled into an intptr_t and the interpretation depends on exactly what /// sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; @@ -741,9 +741,6 @@ public: } void AddFixItHint(const FixItHint &Hint) const { - if (Hint.isNull()) - return; - assert(NumFixItHints < Diagnostic::MaxFixItHints && "Too many fix-it hints!"); if (DiagObj) diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td index be510ed844e1..50a22c4a9120 100644 --- a/include/clang/Basic/Diagnostic.td +++ b/include/clang/Basic/Diagnostic.td @@ -18,6 +18,8 @@ def MAP_IGNORE : DiagMapping; def MAP_WARNING : DiagMapping; def MAP_ERROR : DiagMapping; def MAP_FATAL : DiagMapping; +def MAP_WARNING_NO_WERROR : DiagMapping; +def MAP_WARNING_SHOW_IN_SYSTEM_HEADER : DiagMapping; // Define the diagnostic classes. class DiagClass; @@ -60,6 +62,8 @@ class Diagnostic<string text, DiagClass DC, DiagMapping defaultmapping> { DiagMapping DefaultMapping = defaultmapping; DiagGroup Group; string CategoryName = ""; + string Brief = ""; + string Explanation = ""; } class Error<string str> : Diagnostic<str, CLASS_ERROR, MAP_ERROR>; @@ -73,10 +77,20 @@ class DefaultIgnore { DiagMapping DefaultMapping = MAP_IGNORE; } class DefaultWarn { DiagMapping DefaultMapping = MAP_WARNING; } class DefaultError { DiagMapping DefaultMapping = MAP_ERROR; } class DefaultFatal { DiagMapping DefaultMapping = MAP_FATAL; } +class DefaultWarnNoWerror { DiagMapping DefaultMapping= MAP_WARNING_NO_WERROR; } +class DefaultWarnShowInSystemHeader { + DiagMapping DefaultMapping = MAP_WARNING_SHOW_IN_SYSTEM_HEADER; +} class NoSFINAE { bit SFINAE = 0; } class AccessControl { bit AccessControl = 1; } +class Brief<string str> { string Brief = str; } +class FullExplanation<string brief, string full> { + string Brief = brief; + string Explanation = full; +} + // Definitions for Diagnostics. include "DiagnosticASTKinds.td" include "DiagnosticAnalysisKinds.td" diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 85c64c5cef65..0b0bca0395cb 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -45,6 +45,8 @@ def ext_no_declarators : ExtWarn<"declaration does not declare anything">, InGroup<MissingDeclarations>; def err_param_redefinition : Error<"redefinition of parameter %0">; def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">; +def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">, + InGroup<DuplicateArgDecl>, DefaultIgnore; def err_invalid_storage_class_in_func_decl : Error< "invalid storage class specifier in function declarator">; def err_expected_namespace_name : Error<"expected namespace name">; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index ef1c9e7d8b9a..908a69b162c4 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -39,8 +39,10 @@ def err_drv_invalid_darwin_version : Error< "invalid Darwin version number: %0">; def err_drv_missing_argument : Error< "argument to '%0' is missing (expected %1 %plural{1:value|:values}1)">; -def err_drv_invalid_Xarch_argument : Error< - "invalid Xarch argument: '%0'">; +def err_drv_invalid_Xarch_argument_with_args : Error< + "invalid Xarch argument: '%0', options requiring arguments are unsupported">; +def err_drv_invalid_Xarch_argument_isdriver : Error< + "invalid Xarch argument: '%0', cannot change driver behavior inside Xarch argument">; def err_drv_argument_only_allowed_with : Error< "invalid argument '%0' only allowed with '%1'">; def err_drv_argument_not_allowed_with : Error< @@ -76,6 +78,10 @@ def err_drv_cc_print_options_failure : Error< "unable to open CC_PRINT_OPTIONS file: %0">; def err_drv_preamble_format : Error< "incorrect format for -preamble-bytes=N,END">; +def err_drv_conflicting_deployment_targets : Error< + "conflicting deployment targets, both '%0' and '%1' are present in environment">; +def err_drv_invalid_arch_for_deployment_target : Error< + "invalid architecture '%0' for deployment target '%1'">; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for c++ and objective-c++ only">; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 30706769d45e..67fc22e410fe 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -79,6 +79,8 @@ def warn_fe_macro_contains_embedded_newline : Warning< "macro '%0' contains embedded newline, text after the newline is ignored.">; def warn_fe_cc_print_header_failure : Warning< "unable to open CC_PRINT_HEADERS file: %0 (using stderr)">; +def warn_fe_cc_log_diagnostics_failure : Warning< + "unable to open CC_LOG_DIAGNOSTICS file: %0 (using stderr)">; def err_verify_missing_start : Error< "cannot find start ('{{') of expected %0">; @@ -113,6 +115,9 @@ def warn_pch_target_triple : Error< def warn_pch_c99 : Error< "C99 support was %select{disabled|enabled}0 in PCH file but is " "currently %select{disabled|enabled}1">; +def warn_pch_c1x : Error< + "C1X support was %select{disabled|enabled}0 in PCH file but is " + "currently %select{disabled|enabled}1">; def warn_pch_cplusplus : Error< "C++ support was %select{disabled|enabled}0 in PCH file but is " "currently %select{disabled|enabled}1">; @@ -230,6 +235,9 @@ def warn_pch_gnu_inline : Error< def warn_pch_no_inline : Error< "the macro '__NO_INLINE__' was %select{not defined|defined}0 in " "the PCH file but is currently %select{undefined|defined}1">; +def warn_pch_deprecated : Error< + "the macro '__DEPRECATED' was %select{not defined|defined}0 in " + "the PCH file but is currently %select{undefined|defined}1">; def warn_pch_gc_mode : Error< "the PCH file was built with %select{no||hybrid}0 garbage collection but " "the current translation unit will compiled with %select{no||hybrid}1 " diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 412fb587108e..c85acc510770 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -24,6 +24,7 @@ def : DiagGroup<"aggregate-return">; def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; def : DiagGroup<"attributes">; def : DiagGroup<"bad-function-cast">; +def Availability : DiagGroup<"availability">; def BoolConversions : DiagGroup<"bool-conversions">; def CXXCompat: DiagGroup<"c++-compat">; def CastAlign : DiagGroup<"cast-align">; @@ -54,6 +55,7 @@ def CXXHexFloats : DiagGroup<"c++-hex-floats">; def : DiagGroup<"c++0x-compat", [CXXHexFloats]>; def : DiagGroup<"effc++">; +def ExitTimeDestructors : DiagGroup<"exit-time-destructors">; def FourByteMultiChar : DiagGroup<"four-char-constants">; def GlobalConstructors : DiagGroup<"global-constructors">; def : DiagGroup<"idiomatic-parentheses">; @@ -94,6 +96,8 @@ def Padded : DiagGroup<"padded">; def PointerArith : DiagGroup<"pointer-arith">; def PoundWarning : DiagGroup<"#warnings">, DiagCategory<"#warning Directive">; +def PoundPragmaMessage : DiagGroup<"#pragma messages">, + DiagCategory<"#pragma message Directive">; def : DiagGroup<"pointer-to-int-cast">; def : DiagGroup<"redundant-decls">; def ReturnType : DiagGroup<"return-type">; @@ -109,6 +113,7 @@ def : DiagGroup<"stack-protector">; def : DiagGroup<"switch-default">; def : DiagGroup<"synth">; def TautologicalCompare : DiagGroup<"tautological-compare">; +def HeaderHygiene : DiagGroup<"header-hygiene">; // Preprocessor warnings. def : DiagGroup<"builtin-macro-redefined">; @@ -137,13 +142,17 @@ def Trigraphs : DiagGroup<"trigraphs">; def : DiagGroup<"type-limits">; def Uninitialized : DiagGroup<"uninitialized">; +def UninitializedMaybe : DiagGroup<"conditional-uninitialized">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; def UnknownAttributes : DiagGroup<"unknown-attributes">; def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args">; def UnusedArgument : DiagGroup<"unused-argument">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; -def UnusedFunction : DiagGroup<"unused-function">; -def UnusedMemberFunction : DiagGroup<"unused-member-function">; +def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">; +def UnneededMemberFunction : DiagGroup<"unneeded-member-function">; +def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>; +def UnusedMemberFunction : DiagGroup<"unused-member-function", + [UnneededMemberFunction]>; def UnusedLabel : DiagGroup<"unused-label">; def UnusedParameter : DiagGroup<"unused-parameter">; def UnusedValue : DiagGroup<"unused-value">; @@ -165,17 +174,22 @@ def VariadicMacros : DiagGroup<"variadic-macros">; def VectorConversions : DiagGroup<"vector-conversions">; // clang specific def VLA : DiagGroup<"vla">; def VolatileRegisterVar : DiagGroup<"volatile-register-var">; -def : DiagGroup<"write-strings">; + +// GCC calls -Wdeprecated-writable-strings -Wwrite-strings. +def GCCWriteStrings : DiagGroup<"write-strings" , [DeprecatedWritableStr]>; + def CharSubscript : DiagGroup<"char-subscripts">; def LargeByValueCopy : DiagGroup<"large-by-value-copy">; +def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">; // Aggregation warning settings. // -Widiomatic-parentheses contains warnings about 'idiomatic' -// missing parentheses; it is off by default. +// missing parentheses; it is off by default. We do not include it +// in -Wparentheses because most users who use -Wparentheses explicitly +// do not want these warnings. def Parentheses : DiagGroup<"parentheses", - [LogicalOpParentheses, - DiagGroup<"idiomatic-parentheses">]>; + [LogicalOpParentheses]>; // -Wconversion has its own warnings, but we split a few out for // legacy reasons: @@ -187,6 +201,7 @@ def Conversion : DiagGroup<"conversion", [DiagGroup<"shorten-64-to-32">, DiagGroup<"constant-conversion">, DiagGroup<"literal-conversion">, + DiagGroup<"sign-conversion">, BoolConversions]>, DiagCategory<"Value Conversion Issue">; @@ -253,7 +268,9 @@ def NonGCC : DiagGroup<"non-gcc", // A warning group for warnings about using C++0x features as extensions in // earlier C++ versions. -def CXX0x : DiagGroup<"c++0x-extensions">; +def CXX0xStaticNonIntegralInitializer : + DiagGroup<"c++0x-static-nonintegral-init">; +def CXX0x : DiagGroup<"c++0x-extensions", [CXX0xStaticNonIntegralInitializer]>; // A warning group for warnings about GCC extensions. def GNU : DiagGroup<"gnu", [GNUDesignator, VLA]>; diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index 2b03cae565c8..0296b96d00f6 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -42,7 +42,8 @@ namespace clang { // Get typedefs for common diagnostics. enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #include "clang/Basic/DiagnosticCommonKinds.inc" NUM_BUILTIN_COMMON_DIAGNOSTICS #undef DIAG @@ -63,9 +64,12 @@ namespace clang { /// Map this diagnostic to "warning", but make it immune to -Werror. This /// happens when you specify -Wno-error=foo. MAP_WARNING_NO_WERROR = 5, + /// Map this diagnostic to "warning", but make it immune to + /// -Wno-system-headers. + MAP_WARNING_SHOW_IN_SYSTEM_HEADER = 6, /// Map this diagnostic to "error", but make it immune to -Wfatal-errors. /// This happens for -Wno-fatal-errors=foo. - MAP_ERROR_NO_WFATAL = 6 + MAP_ERROR_NO_WFATAL = 7 }; } @@ -99,7 +103,7 @@ public: /// issue. const char *getDescription(unsigned DiagID) const; - /// isNoteWarningOrExtension - Return true if the unmapped diagnostic + /// isBuiltinWarningOrExtension - Return true if the unmapped diagnostic /// level of the specified diagnostic ID is a Warning or Extension. /// This only works on builtin diagnostics, not custom ones, and is not legal to /// call on NOTEs. @@ -130,7 +134,7 @@ public: /// the diagnostic, this returns null. static const char *getWarningOptionForDiag(unsigned DiagID); - /// getWarningOptionForDiag - Return the category number that a specified + /// getCategoryNumberForDiag - Return the category number that a specified /// DiagID belongs to, or 0 if no category. static unsigned getCategoryNumberForDiag(unsigned DiagID); @@ -174,6 +178,20 @@ public: /// are not SFINAE errors. static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); + /// getName - Given a diagnostic ID, return its name + static const char *getName(unsigned DiagID); + + /// getIdFromName - Given a diagnostic name, return its ID, or 0 + static unsigned getIdFromName(char const *Name); + + /// getBriefExplanation - Given a diagnostic ID, return a brief explanation + /// of the issue + static const char *getBriefExplanation(unsigned DiagID); + + /// getFullExplanation - Given a diagnostic ID, return a full explanation + /// of the issue + static const char *getFullExplanation(unsigned DiagID); + private: /// setDiagnosticGroupMapping - Change an entire diagnostic group (e.g. /// "unknown-pragmas" to have the specified mapping. This returns true and diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 6d1d9b6ad869..3514ccace22a 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -114,7 +114,8 @@ def err_invalid_pth_file : Error< //===----------------------------------------------------------------------===// // Preprocessor Diagnostics //===----------------------------------------------------------------------===// -def pp_hash_warning : Warning<"#warning%0">, InGroup<PoundWarning>; +def pp_hash_warning : Warning<"#warning%0">, + InGroup<PoundWarning>, DefaultWarnShowInSystemHeader; def pp_include_next_in_primary : Warning< "#include_next in primary source file">; def pp_include_macros_out_of_predefines : Error< @@ -239,7 +240,8 @@ def err_pragma_push_pop_macro_malformed : Error< "pragma %0 requires a parenthesized string">; def warn_pragma_pop_macro_no_push : Warning< "pragma pop_macro could not pop '%0', no matching push_macro">; -def warn_pragma_message : Warning<"%0">; +def warn_pragma_message : Warning<"%0">, + InGroup<PoundPragmaMessage>, DefaultWarnNoWerror; def warn_pragma_ignored : Warning<"unknown pragma ignored">, InGroup<UnknownPragmas>, DefaultIgnore; def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, @@ -247,8 +249,8 @@ def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, def ext_on_off_switch_syntax : ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">, InGroup<UnknownPragmas>; -def ext_pragma_syntax_eom : - ExtWarn<"expected end of macro in pragma">, +def ext_pragma_syntax_eod : + ExtWarn<"expected end of directive in pragma">, InGroup<UnknownPragmas>; def warn_stdc_fenv_access_not_supported : Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 9a68af9c45ca..c37e510b3479 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -67,6 +67,13 @@ def ext_ms_enum_fixed_underlying_type : Extension< "enumeration types with a fixed underlying type are a Microsoft extension">, InGroup<Microsoft>; +def ext_c1x_generic_selection : Extension< + "generic selections are a C1X-specific feature">; +def err_duplicate_default_assoc : Error< + "duplicate default generic association">; +def note_previous_default_assoc : Note< + "previous default generic association is here">; + def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">, InGroup<GNU>; def ext_gnu_address_of_label : Extension< @@ -111,7 +118,7 @@ def err_expected_semi_declaration : Error< "expected ';' at end of declaration">; def err_expected_semi_decl_list : Error< "expected ';' at end of declaration list">; -def ext_expected_semi_decl_list : Extension< +def ext_expected_semi_decl_list : ExtWarn< "expected ';' at end of declaration list">; def err_expected_member_name_or_semi : Error< "expected member name or ';' after declaration specifiers">; @@ -119,6 +126,10 @@ def err_function_declared_typedef : Error< "function definition declared 'typedef'">; def err_iboutletcollection_builtintype : Error< "type argument of iboutletcollection attribute cannot be a builtin type">; + +def err_at_defs_cxx : Error<"@defs is not supported in Objective-C++">; +def err_at_in_class : Error<"unexpected '@' in member specification">; + def err_expected_fn_body : Error< "expected function body after function declarator">; def err_expected_method_body : Error<"expected method body">; @@ -130,6 +141,7 @@ def err_expected_statement : Error<"expected statement">; def err_expected_lparen_after : Error<"expected '(' after '%0'">; def err_expected_lparen_after_id : Error<"expected '(' after %0">; def err_expected_less_after : Error<"expected '<' after '%0'">; +def err_expected_equal_after : Error<"expected '=' after %0">; def err_expected_comma : Error<"expected ','">; def err_expected_lbrace_in_compound_literal : Error< "expected '{' in compound literal">; @@ -178,6 +190,9 @@ def ext_ref_qualifier : ExtWarn< "reference qualifiers on functions are a C++0x extension">, InGroup<CXX0x>; def ext_inline_namespace : ExtWarn< "inline namespaces are a C++0x feature">, InGroup<CXX0x>; +def ext_generalized_initializer_lists : ExtWarn< + "generalized initializer lists are a C++0x extension unsupported in Clang">, + InGroup<CXX0x>; def err_argument_required_after_attribute : Error< "argument required after attribute">; def err_missing_param : Error<"expected parameter declarator">; @@ -189,6 +204,9 @@ def err_expected_class_name : Error<"expected class name">; def err_unspecified_vla_size_with_static : Error< "'static' may not be used with an unspecified variable length array size">; +def err_expected_case_before_expression: Error< + "expected 'case' keyword before expression">; + // Declarations. def err_typename_requires_specqual : Error< "type name requires a specifier or qualifier">; @@ -226,6 +244,8 @@ def err_unexected_colon_in_nested_name_spec : Error< "unexpected ':' in nested name specifier">; def err_bool_redeclaration : Error< "redeclaration of C++ built-in type 'bool'">; +def ext_c1x_static_assert : Extension< + "_Static_assert is a C1X-specific feature">; /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< @@ -266,7 +286,7 @@ def err_missing_id_definition : Error<"cannot find definition of 'id'">; def err_missing_proto_definition : Error< "cannot find definition of 'Protocol'">; def err_missing_class_definition : Error<"cannot find definition of 'Class'">; -def warn_expected_implementation : Warning< +def err_expected_implementation : Error< "@end must appear in an @implementation context">; def error_property_ivar_decl : Error< "property synthesize requires specification of an ivar">; @@ -300,6 +320,8 @@ def err_expected_lbrace_after_base_specifiers : Error< "expected '{' after base class list">; def ext_ellipsis_exception_spec : Extension< "exception specification of '...' is a Microsoft extension">; +def err_dynamic_and_noexcept_specification : Error< + "cannot have both throw() and noexcept() clause on the same function">; def err_expected_catch : Error<"expected catch">; def err_expected_lbrace_or_comma : Error<"expected '{' or ','">; def err_using_namespace_in_class : Error< @@ -363,6 +385,8 @@ def err_enum_template : Error<"enumeration cannot be a template">; def err_missing_dependent_template_keyword : Error< "use 'template' keyword to treat '%0' as a dependent template name">; +def warn_missing_dependent_template_keyword : ExtWarn< + "use 'template' keyword to treat '%0' as a dependent template name">; def warn_static_inline_explicit_inst_ignored : Warning< "ignoring '%select{static|inline}0' keyword on explicit template " @@ -380,6 +404,8 @@ def err_out_of_line_type_names_constructor : Error< def err_expected_qualified_after_typename : Error< "expected a qualified name after 'typename'">; +def warn_expected_qualified_after_typename : ExtWarn< + "expected a qualified name after 'typename'">; def err_expected_semi_after_tagdecl : Error< "expected ';' after %0">; @@ -401,15 +427,23 @@ def err_ctor_init_missing_comma : Error< // C++ declarations def err_friend_decl_defines_class : Error< "cannot define a type in a friend declaration">; +def err_missing_whitespace_digraph : Error< + "found '<::' after a " + "%select{template name|const_cast|dynamic_cast|reinterpret_cast|static_cast}0" + " which forms the digraph '<:' (aka '[') and a ':', did you mean '< ::'?">; def warn_deleted_function_accepted_as_extension: ExtWarn< "deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>; +// C++0x alias-declaration +def ext_alias_declaration : ExtWarn< + "alias declarations accepted as a C++0x extension">, InGroup<CXX0x>; +def err_alias_declaration_not_identifier : Error< + "name defined in alias declaration must be an identifier">; + // C++0x override control def ext_override_control_keyword : Extension< "'%0' keyword accepted as a C++0x extension">, InGroup<CXX0x>; -def ext_override_inline: Extension< - "'%0' keyword only allowed in declarations, allowed as an extension">; def err_duplicate_virt_specifier : Error< "class member already marked '%0'">; @@ -426,6 +460,23 @@ def err_paren_sizeof_parameter_pack : Error< def err_sizeof_parameter_pack : Error< "expected parenthesized parameter pack name in 'sizeof...' expression">; +// Availability attribute +def err_expected_version : Error< + "expected a version of the form 'major[.minor[.subminor]]'">; +def err_zero_version : Error< + "version number must have non-zero major, minor, or sub-minor version">; +def err_availability_expected_platform : Error< + "expected a platform name, e.g., 'macosx'">; +def err_availability_expected_change : Error< + "expected 'introduced', 'deprecated', or 'obsoleted'">; +def err_availability_unknown_change : Error< + "%0 is not an availability stage; use 'introduced', 'deprecated', or " + "'obsoleted'">; +def err_availability_redundant : Error< + "redundant %0 availability change; only the last specified change will " "be used">; +def warn_availability_and_unavailable : Warning< + "'unavailable' availability overrides all other availability information">; + // Language specific pragmas // - Generic warnings def warn_pragma_expected_lparen : Warning< @@ -434,6 +485,8 @@ def warn_pragma_expected_rparen : Warning< "missing ')' after '#pragma %0' - ignoring">; def warn_pragma_expected_identifier : Warning< "expected identifier in '#pragma %0' - ignored">; +def warn_pragma_ms_struct : Warning< + "incorrect use of '#pragma ms_struct on|off' - ignored">; def warn_pragma_extra_tokens_at_eol : Warning< "extra tokens at end of '#pragma %0' - ignored">; // - #pragma options @@ -468,5 +521,17 @@ def warn_pragma_expected_enable_disable : Warning< def warn_pragma_unknown_extension : Warning< "unknown OpenCL extension %0 - ignoring">; +def err_seh_expected_handler : Error< + "expected '__except' or '__finally' block">; + +def err_seh___except_block : Error< + "%0 only allowed in __except block">; + +def err_seh___except_filter : Error< + "%0 only allowed in __except filter expression">; + +def err_seh___finally_block : Error< + "%0 only allowed in __finally block">; + } // end of Parse Issue category. } // end of Parser diagnostics diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a9fb2da00176..0a0c91ac9144 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -30,6 +30,8 @@ def warn_float_overflow : Warning< def warn_float_underflow : Warning< "magnitude of floating-point constant too small for type %0; minimum is %1">, InGroup<LiteralRange>; +def warn_double_const_requires_fp64 : Warning< + "double precision constant requires cl_khr_fp64, casting to single precision">; // C99 variable-length arrays def ext_vla : Extension< @@ -57,6 +59,8 @@ def err_variably_modified_new_type : Error< // C99 Designated Initializers def ext_designated_init : Extension< + "designated initializers are a C99 feature">; +def ext_designated_init_cxx : Extension< "designated initializers are a C99 feature, accepted in C++ as an extension">; def err_array_designator_negative : Error< "array designator value '%0' is negative">; @@ -114,6 +118,12 @@ def warn_unused_member_function : Warning<"unused member function %0">, InGroup<UnusedMemberFunction>, DefaultIgnore; def warn_used_but_marked_unused: Warning<"%0 was marked unused but was used">, InGroup<UsedButMarkedUnused>, DefaultIgnore; +def warn_unneeded_internal_decl : Warning< + "%select{function|variable}0 %1 is not needed and will not be emitted">, + InGroup<UnneededInternalDecl>, DefaultIgnore; +def warn_unneeded_member_function : Warning< + "member function %0 is not needed and will not be emitted">, + InGroup<UnneededMemberFunction>, DefaultIgnore; def warn_parameter_size: Warning< "%0 is a large (%1 bytes) pass-by-value argument; " @@ -202,6 +212,9 @@ def warn_global_constructor : Warning< def warn_global_destructor : Warning< "declaration requires a global destructor">, InGroup<GlobalConstructors>, DefaultIgnore; +def warn_exit_time_destructor : Warning< + "declaration requires an exit-time destructor">, + InGroup<ExitTimeDestructors>, DefaultIgnore; def err_invalid_thread : Error< "'__thread' is only allowed on variable declarations">; @@ -248,6 +261,11 @@ def err_builtin_definition : Error<"definition of builtin function %0">; def err_types_compatible_p_in_cplusplus : Error< "__builtin_types_compatible_p is not valid in C++">; def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError; +def warn_non_pod_memset : Warning< + "destination for this memset call is a pointer to a non-POD type %0">, + InGroup<DiagGroup<"non-pod-memset">>, DefaultIgnore; +def note_non_pod_memset_silence : Note< + "explicitly cast the pointer to silence this warning">; /// main() // static/inline main() are not errors in C, just in C++. @@ -382,7 +400,7 @@ def note_declared_at : Note<"declared here">; def note_method_declared_at : Note<"method declared here">; 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_missing_atend : Error<"'@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< @@ -540,7 +558,7 @@ def ext_using_undefined_std : ExtWarn< // C++ exception specifications def err_exception_spec_in_typedef : Error< - "exception specifications are not allowed in typedefs">; + "exception specifications are not allowed in %select{typedefs|type aliases}0">; def err_distant_exception_spec : Error< "exception specifications are not allowed beyond a single level " "of indirection">; @@ -549,6 +567,8 @@ def err_incomplete_in_exception_spec : Error< "in exception specification">; def err_mismatched_exception_spec : Error< "exception specification in declaration does not match previous declaration">; +def warn_mismatched_exception_spec : ExtWarn< + "exception specification in declaration does not match previous declaration">; def err_override_exception_spec : Error< "exception specification of overriding function is more lax than " "base version">; @@ -558,6 +578,8 @@ def err_deep_exception_specs_differ : Error< "exception specifications of %select{return|argument}0 types differ">; def warn_missing_exception_specification : Warning< "%0 is missing exception specification '%1'">; +def err_noexcept_needs_constant_expression : Error< + "argument to noexcept specifier must be a constant expression">; // C++ access checking def err_class_redeclared_with_different_access : Error< @@ -786,20 +808,28 @@ def err_destructor_redeclared : Error<"destructor cannot be redeclared">; def err_destructor_with_params : Error<"destructor cannot have any parameters">; def err_destructor_variadic : Error<"destructor cannot be variadic">; def err_destructor_typedef_name : Error< - "destructor cannot be declared using a typedef %0 of the class name">; + "destructor cannot be declared using a %select{typedef|type alias}1 %0 of the class name">; def err_destructor_name : Error< "expected the class name after '~' to name the enclosing class">; def err_destructor_class_name : Error< "expected the class name after '~' to name a destructor">; -def err_ident_in_pseudo_dtor_not_a_type : Error< - "identifier %0 in pseudo-destructor expression does not name a type">; +def err_ident_in_dtor_not_a_type : Error< + "identifier %0 in object destruction expression does not name a type">; +def err_destructor_expr_type_mismatch : Error< + "destructor type %0 in object destruction expression does not match the " + "type %1 of the object being destroyed">; +def note_destructor_type_here : Note< + "type %0 is declared here">; + +def err_destructor_template : Error< + "destructor cannot be declared as a template">; // C++ initialization def err_init_conversion_failed : Error< "cannot initialize %select{a variable|a parameter|return object|an " "exception object|a member subobject|an array element|a new value|a value|a " - "base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of " - "type %3">; + "base class|a constructor delegation|a vector element}0 of type %1 with an " + "%select{rvalue|lvalue}2 of type %3">; def err_lvalue_to_rvalue_ref : Error<"rvalue reference to type %0 cannot bind " "to lvalue of type %1">; @@ -854,13 +884,23 @@ def note_uninit_reference_member : Note< "uninitialized reference member is here">; def warn_field_is_uninit : Warning<"field is uninitialized when used here">, InGroup<Uninitialized>; -def warn_uninit_var : Warning<"variable %0 is possibly uninitialized when used here">, - InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore; +def warn_uninit_self_reference_in_init : Warning< + "variable %0 is uninitialized when used within its own initialization">, + InGroup<Uninitialized>; +def warn_uninit_var : Warning< + "variable %0 is uninitialized when used here">, + InGroup<Uninitialized>, DefaultIgnore; +def warn_maybe_uninit_var : + Warning<"variable %0 may be uninitialized when used here">, + InGroup<UninitializedMaybe>, DefaultIgnore; def note_uninit_var_def : Note< "variable %0 is declared here">; def warn_uninit_var_captured_by_block : Warning< - "variable %0 is possibly uninitialized when captured by block">, - InGroup<DiagGroup<"uninitialized-experimental">>, DefaultIgnore; + "variable %0 is uninitialized when captured by block">, + InGroup<Uninitialized>, DefaultIgnore; +def warn_maybe_uninit_var_captured_by_block : Warning< + "variable %0 may be uninitialized when captured by block">, + InGroup<UninitializedMaybe>, DefaultIgnore; def note_var_fixit_add_initialization : Note< "add initialization to silence this warning">; def err_init_incomplete_type : Error<"initialization of incomplete type %0">; @@ -905,7 +945,7 @@ def err_auto_not_allowed : Error< "'auto' not allowed %select{in function prototype|in struct member" "|in union member|in class member|in exception declaration" "|in template parameter|in block literal|in template argument" - "|in typedef|in function return type|here}0">; + "|in typedef|in type alias|in function return type|here}0">; def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< @@ -944,9 +984,6 @@ def err_final_function_overridden : Error< def err_final_base : Error< "derivation from 'final' %0">; -def err_function_overriding_without_override : Error< - "%0 overrides function%s1 without being marked 'override'">; - // C++0x scoped enumerations def err_enum_invalid_underlying : Error< "non-integral type %0 is an invalid underlying type">; @@ -969,6 +1006,34 @@ def err_delegation_0x_only : Error< "delegating constructors are permitted only in C++0x">; def err_delegation_unimplemented : Error< "delegating constructors are not fully implemented">; +def err_delegating_initializer_alone : Error< + "an initializer for a delegating constructor must appear alone">; +def err_delegating_ctor_loop : Error< + "constructor %0 delegates to itself (possibly indirectly)">; +def err_delegating_codegen_not_implemented : Error< + "code generation for delegating constructors not implemented">; + +// C++0x range-based for loop +def err_for_range_decl_must_be_var : Error< + "for range declaration must declare a variable">; +def err_for_range_storage_class : Error< + "loop variable %0 may not be declared %select{'extern'|'static'|" + "'__private_extern__'|'auto'|'register'|'constexpr'}1">; +def err_type_defined_in_for_range : Error< + "types may not be defined in a for range declaration">; +def err_for_range_deduction_failure : Error< + "cannot use type %0 as a range">; +def err_for_range_incomplete_type : Error< + "cannot use incomplete type %0 as a range">; +def err_for_range_iter_deduction_failure : Error< + "cannot use type %0 as an iterator">; +def err_for_range_member_begin_end_mismatch : Error< + "range type %0 has '%select{begin|end}1' member but no '%select{end|begin}1' member">; +def err_for_range_begin_end_types_differ : Error< + "'begin' and 'end' must return the same type (got %0 and %1)">; +def note_for_range_type : Note<"range has type %0">; +def note_for_range_begin_end : Note< + "selected '%select{begin|end}0' %select{function|template }1%2 with iterator type %3">; // Objective-C++ def err_objc_decls_may_only_appear_in_global_scope : Error< @@ -982,7 +1047,10 @@ def err_attribute_can_be_applied_only_to_symbol_declaration : Error< def err_attributes_are_not_compatible : Error< "%0 and %1 attributes are not compatible">; def err_attribute_wrong_number_arguments : Error< - "attribute requires %0 argument(s)">; + "attribute %plural{0:takes no arguments|1:takes one argument|" + ":requires exactly %0 arguments}0">; +def err_attribute_too_many_arguments : Error< + "attribute takes no more than %0 argument%s0">; def err_iboutletcollection_type : Error< "invalid type %0 as argument of iboutletcollection attribute">; def err_iboutletcollection_object_type : Error< @@ -1026,6 +1094,7 @@ def err_format_attribute_result_not : Error<"function does not return %0">; def err_format_attribute_implicit_this_format_string : Error< "format attribute cannot specify the implicit this argument as the format " "string">; +def warn_unknown_method_family : Warning<"unrecognized method family">; def err_attribute_invalid_size : Error< "vector size not an integral multiple of component size">; def err_attribute_zero_size : Error<"zero vector size">; @@ -1101,7 +1170,9 @@ def err_attribute_wrong_decl_type : Error< "classes and virtual methods|functions, methods, and parameters|" "classes|virtual methods|class members|variables|methods}1">; def warn_function_attribute_wrong_type : Warning< - "%0 only applies to function types; type here is %1">; + "'%0' only applies to function types; type here is %1">; +def warn_pointer_attribute_wrong_type : Warning< + "'%0' only applies to pointer types; type here is %1">; def warn_gnu_inline_attribute_requires_inline : Warning< "'gnu_inline' attribute requires function to be marked 'inline'," " attribute ignored">; @@ -1119,6 +1190,15 @@ def err_cconv_varargs : Error< def err_regparm_mismatch : Error<"function declared with with regparm(%0) " "attribute was previously declared " "%plural{0:without the regparm|:with the regparm(%1)}1 attribute">; +def err_invalid_pcs : Error<"Invalid PCS type">; + +// Availability attribute +def warn_availability_unknown_platform : Warning< + "unknown platform %0 in availability macro">; +def warn_availability_version_ordering : Warning< + "feature cannot be %select{introduced|deprecated|obsoleted}0 in %1 version " + "%2 before it was %select{introduced|deprecated|obsoleted}3 in version %4; " + "attribute ignored">; def warn_impcast_vector_scalar : Warning< "implicit conversion turns vector to scalar: %0 to %1">, @@ -1134,10 +1214,10 @@ def warn_impcast_float_integer : Warning< InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_integer_sign : Warning< "implicit conversion changes signedness: %0 to %1">, - InGroup<DiagGroup<"conversion">>, DefaultIgnore; + InGroup<DiagGroup<"sign-conversion">>, DefaultIgnore; def warn_impcast_integer_sign_conditional : Warning< "operand of ? changes signedness: %0 to %1">, - InGroup<DiagGroup<"conversion">>, DefaultIgnore; + InGroup<DiagGroup<"sign-conversion">>, DefaultIgnore; def warn_impcast_integer_precision : Warning< "implicit conversion loses integer precision: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; @@ -1154,9 +1234,15 @@ def warn_impcast_literal_float_to_integer : Warning< "implicit conversion turns literal floating-point number into integer: " "%0 to %1">, InGroup<DiagGroup<"literal-conversion">>, DefaultIgnore; +def note_fix_integral_float_as_integer : Note< + "this can be rewritten as an integer literal with the exact same value">; def warn_impcast_different_enum_types : Warning< "implicit conversion from enumeration type %0 to different enumeration type " "%1">, InGroup<DiagGroup<"conversion">>; +def warn_impcast_bool_to_null_pointer : Warning< + "initialization of pointer of type %0 to NULL from a constant boolean " + "expression">, InGroup<BoolConversions>; + def warn_cast_align : Warning< "cast from %0 to %1 increases required alignment from %2 to %3">, @@ -1252,11 +1338,13 @@ def err_ident_list_in_fn_declaration : Error< def ext_param_not_declared : Extension< "parameter %0 was not declared, defaulting to type 'int'">; def err_param_typedef_of_void : Error< - "empty parameter list defined with a typedef of 'void' not allowed in C++">; + "empty parameter list defined with a %select{typedef|type alias}0 of 'void' not allowed%select{ in C++|}0">; def err_param_default_argument : Error< "C does not support default arguments">; def err_param_default_argument_redefinition : Error< "redefinition of default argument">; +def warn_param_default_argument_redefinition : ExtWarn< + "redefinition of default argument">; def err_param_default_argument_missing : Error< "missing default argument on parameter">; def err_param_default_argument_missing_name : Error< @@ -1311,11 +1399,11 @@ def err_ovl_no_viable_member_function_in_call : Error< def err_ovl_ambiguous_call : Error< "call to %0 is ambiguous">; def err_ovl_deleted_call : Error< - "call to %select{unavailable|deleted}0 function %1 %2">; + "call to %select{unavailable|deleted}0 function %1%2">; def err_ovl_ambiguous_member_call : Error< "call to member function %0 is ambiguous">; def err_ovl_deleted_member_call : Error< - "call to %select{unavailable|deleted}0 member function %1 %2">; + "call to %select{unavailable|deleted}0 member function %1%2">; def note_ovl_too_many_candidates : Note< "remaining %0 candidate%s0 omitted; " "pass -fshow-overloads=all to show them">; @@ -1327,10 +1415,6 @@ def note_ovl_candidate : Note<"candidate " "is the implicit copy assignment operator|" "is an inherited constructor}0%1">; -def warn_init_pointer_from_false : Warning< - "initialization of pointer of type %0 from literal 'false'">, - InGroup<BoolConversions>; - def note_ovl_candidate_inherited_constructor : Note<"inherited from here">; def note_ovl_candidate_bad_deduction : Note< "candidate template ignored: failed template argument deduction">; @@ -1408,6 +1492,15 @@ def note_ovl_candidate_bad_addrspace : Note<"candidate " "constructor (inherited)}0%1 not viable: " "%select{%ordinal6|'this'}5 argument (%2) is in " "address space %3, but parameter must be in address space %4">; +def note_ovl_candidate_bad_gc : Note<"candidate " + "%select{function|function|constructor|" + "function |function |constructor |" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "function (the implicit copy assignment operator)|" + "constructor (inherited)}0%1 not viable: " + "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 " + "lifetime, but parameter has %select{no|__weak|__strong}4 lifetime">; def note_ovl_candidate_bad_cvr_this : Note<"candidate " "%select{|function|||function||||" "function (the implicit copy assignment operator)|}0 not viable: " @@ -1467,13 +1560,13 @@ def err_ovl_ambiguous_oper_binary : Error< "use of overloaded operator '%0' is ambiguous (with operand types %1 and %2)">; def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">; def err_ovl_deleted_oper : Error< - "overload resolution selected %select{unavailable|deleted}0 operator '%1' %2">; + "overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">; def err_ovl_no_viable_subscript : Error<"no viable overloaded operator[] for type %0">; def err_ovl_no_oper : Error<"type %0 does not provide a %select{subscript|call}1 operator">; def err_ovl_unresolvable : - Error<"cannot resolve overloaded function from context">; + Error<"cannot resolve overloaded function %0 from context">; def err_ovl_no_viable_object_call : Error< @@ -1481,7 +1574,7 @@ def err_ovl_no_viable_object_call : Error< def err_ovl_ambiguous_object_call : Error< "call to object of type %0 is ambiguous">; def err_ovl_deleted_object_call : Error< - "call to %select{unavailable|deleted}0 function call operator in type %1 %2">; + "call to %select{unavailable|deleted}0 function call operator in type %1%2">; def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">; def err_member_call_without_object : Error< "call to non-static member function without an object argument">; @@ -1707,6 +1800,8 @@ def err_template_spec_default_arg : Error< def err_not_class_template_specialization : Error< "cannot specialize a %select{dependent template|template template " "parameter}0">; +def err_function_specialization_in_class : Error< + "cannot specialize a function %0 within class scope">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< @@ -1777,6 +1872,9 @@ def err_template_recursion_depth_exceeded : Error< def note_template_recursion_depth : Note< "use -ftemplate-depth-N to increase recursive template instantiation depth">; +def err_template_instantiate_within_definition : Error< + "%select{implicit|explicit}0 instantiation of template %1 within its" + " own definition">; def err_template_instantiate_undefined : Error< "%select{implicit|explicit}0 instantiation of undefined template %1">; def err_implicit_instantiate_member_undefined : Error< @@ -1900,6 +1998,8 @@ def note_typename_refers_here : Note< "referenced member %0 is declared here">; def err_typename_missing : Error< "missing 'typename' prior to dependent type name '%0%1'">; +def warn_typename_missing : ExtWarn< + "missing 'typename' prior to dependent type name '%0%1'">; def ext_typename_outside_of_template : ExtWarn< "'typename' occurs outside of a template">, InGroup<CXX0x>; def err_typename_refers_to_using_value_decl : Error< @@ -1921,6 +2021,14 @@ def err_template_kw_missing : Error< def ext_template_outside_of_template : ExtWarn< "'template' keyword outside of a template">, InGroup<CXX0x>; +def err_non_type_template_in_nested_name_specifier : Error< + "qualified name refers into a specialization of function template '%0'">; +def err_template_id_not_a_type : Error< + "template name refers to non-type template '%0'">; +def note_template_declared_here : Note< + "%select{function template|class template|template template parameter}0 " + "%1 declared here">; + // C++0x Variadic Templates def err_template_param_pack_default_arg : Error< "template parameter pack cannot have a default argument">; @@ -2039,6 +2147,8 @@ def err_inline_declaration_block_scope : Error< "inline declaration of %0 not allowed in block scope">; def err_static_non_static : Error< "static declaration of %0 follows non-static declaration">; +def warn_static_non_static : ExtWarn< + "static declaration of %0 follows non-static declaration">; def err_non_static_static : Error< "non-static declaration of %0 follows static declaration">; def err_extern_non_extern : Error< @@ -2054,17 +2164,17 @@ def err_redefinition_different_type : Error< def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; def err_redefinition_different_typedef : Error< - "typedef redefinition with different types (%0 vs %1)">; + "%select{typedef|type alias}0 redefinition with different types (%1 vs %2)">; def err_tag_reference_non_tag : Error< - "elaborated type refers to %select{a non-tag type|a typedef|a template}0">; + "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template}0">; def err_tag_reference_conflict : Error< "implicit declaration introduced by elaborated type conflicts with " - "%select{a declaration|a typedef|a template}0 of the same name">; + "%select{a declaration|a typedef|a type alias|a template}0 of the same name">; def err_dependent_tag_decl : Error< "%select{declaration|definition}0 of %select{struct|union|class|enum}1 " "in a dependent scope">; def err_tag_definition_of_typedef : Error< - "definition of type %0 conflicts with typedef of the same name">; + "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">; def err_conflicting_types : Error<"conflicting types for %0">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< @@ -2154,6 +2264,8 @@ def err_excess_initializers_in_char_array_initializer : Error< "excess elements in char array initializer">; def warn_excess_initializers_in_char_array_initializer : ExtWarn< "excess elements in char array initializer">; +def err_initializer_string_for_char_array_too_long : Error< + "initializer-string for char array is too long">; def warn_initializer_string_for_char_array_too_long : ExtWarn< "initializer-string for char array is too long">; def warn_missing_field_initializers : Warning< @@ -2180,6 +2292,8 @@ def err_bitfield_width_exceeds_type_size : Error< "size of bit-field %0 (%1 bits) exceeds size of its type (%2 bits)">; def err_anon_bitfield_width_exceeds_type_size : Error< "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">; +def err_incorrect_number_of_vector_initializers : Error< + "number of elements must be either one or match the size of the vector">; // Used by C++ which allows bit-fields that are wider than the type. def warn_bitfield_width_exceeds_type_size: Warning< @@ -2212,6 +2326,8 @@ def note_protected_by_cleanup : Note< "jump bypasses initialization of variable with __attribute__((cleanup))">; def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; +def note_protected_by_vla_type_alias : Note< + "jump bypasses initialization of VLA type alias">; def note_protected_by_vla : Note< "jump bypasses initialization of variable length array">; def note_protected_by_objc_try : Note< @@ -2266,12 +2382,17 @@ def ext_flexible_array_in_array : Extension< "%0 may not be used as an array element due to flexible array member">; def err_flexible_array_init_nonempty : Error< "non-empty initialization of flexible array member inside subobject">; -def ext_flexible_array_empty_aggregate : Extension< +def ext_flexible_array_empty_aggregate_ms : Extension< "flexible array member %0 in otherwise empty %select{struct|class}1 " "is a Microsoft extension">, InGroup<Microsoft>; -def ext_flexible_array_union : Extension< +def ext_flexible_array_union_ms : Extension< "flexible array member %0 in a union is a Microsoft extension">, InGroup<Microsoft>; +def ext_flexible_array_empty_aggregate_gnu : Extension< + "flexible array member %0 in otherwise empty %select{struct|class}1 " + "is a GNU extension">, InGroup<GNU>; +def ext_flexible_array_union_gnu : Extension< + "flexible array member %0 in a union is a GNU extension">, InGroup<GNU>; def err_flexible_array_init_needs_braces : Error< "flexible array requires brace-enclosed initializer">; @@ -2314,14 +2435,18 @@ def err_func_def_incomplete_result : Error< def ext_sizeof_function_type : Extension< "invalid application of 'sizeof' to a function type">, InGroup<PointerArith>; def err_sizeof_alignof_overloaded_function_type : Error< - "invalid application of '%select{sizeof|__alignof}0' to an overloaded " - "function">; + "invalid application of '%select{sizeof|__alignof|vec_step}0' to an " + "overloaded function">; def ext_sizeof_void_type : Extension< - "invalid application of '%0' to a void type">, InGroup<PointerArith>; + "invalid application of '%select{sizeof|__alignof|vec_step}0' to a void " + "type">, InGroup<PointerArith>; def err_sizeof_alignof_incomplete_type : Error< - "invalid application of '%select{sizeof|__alignof}0' to an incomplete type %1">; + "invalid application of '%select{sizeof|__alignof|vec_step}0' to an " + "incomplete type %1">; def err_sizeof_alignof_bitfield : Error< "invalid application of '%select{sizeof|__alignof}0' to bit-field">; +def err_vecstep_non_scalar_vector_type : Error< + "'vec_step' requires built-in scalar or vector type, %0 invalid">; def err_offsetof_incomplete_type : Error< "offsetof of incomplete type %0">; def err_offsetof_record_type : Error< @@ -2417,6 +2542,11 @@ def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">; def err_no_member : Error<"no member named %0 in %1">; +def err_member_not_yet_instantiated : Error< + "no member %0 in %1; it has not yet been instantiated">; +def note_non_instantiated_member_here : Note< + "not-yet-instantiated member is declared here">; + def err_member_redeclared : Error<"class member cannot be redeclared">; def err_member_name_of_class : Error<"member %0 has the same name as its class">; def err_member_def_undefined_record : Error< @@ -2483,6 +2613,7 @@ def err_typecheck_sclass_fscope : Error< "illegal storage class on file-scoped variable">; def err_unsupported_global_register : Error< "global register variables are not supported">; +def warn_standalone_specifier : Warning<"'%0' ignored on this declaration">; def err_typecheck_sclass_func : Error<"illegal storage class on function">; def err_static_block_func : Error< "function declared in block scope cannot have 'static' storage class">; @@ -2618,6 +2749,8 @@ def err_ref_array_type : Error< "cannot refer to declaration with an array type inside block">; def err_property_not_found : Error< "property %0 not found on object of type %1">; +def err_invalid_property_name : Error< + "%0 is not a valid property name (accessing an object of type %1)">; def err_getter_not_found : Error< "expected getter method not found on object of type %0">; def err_property_not_found_forward_class : Error< @@ -2636,6 +2769,8 @@ def ext_gnu_ptr_func_arith : Extension< InGroup<PointerArith>; def error_readonly_property_assignment : Error< "assigning to property with 'readonly' attribute not allowed">; +def error_readonly_message_assignment : Error< + "assigning to 'readonly' return result of an objective-c message not allowed">; def ext_integer_increment_complex : Extension< "ISO C does not support '++'/'--' on complex integer type %0">; def ext_integer_complement_complex : Extension< @@ -2655,9 +2790,11 @@ def err_imaginary_not_supported : Error<"imaginary types are not supported">; def warn_root_inst_method_not_found : Warning< "instance method %0 is being used on 'Class' which is not in the root class">; def warn_class_method_not_found : Warning< - "method %objcclass0 not found (return type defaults to 'id')">; + "class method %objcclass0 not found (return type defaults to 'id')">; +def warn_instance_method_on_class_found : Warning< + "instance method %0 found instead of class method %1">; def warn_inst_method_not_found : Warning< - "method %objcinstance0 not found (return type defaults to 'id')">; + "instance method %objcinstance0 not found (return type defaults to 'id')">; def error_no_super_class_message : Error< "no @interface declaration found in class messaging of %0">; def error_root_class_cannot_use_super : Error< @@ -2735,9 +2872,9 @@ def err_bad_cxx_cast_generic : Error< def err_bad_cxx_cast_rvalue : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from rvalue to reference type %2">; -def err_bad_cxx_cast_const_away : Error< +def err_bad_cxx_cast_qualifiers_away : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" - "functional-style cast}0 from %1 to %2 casts away constness">; + "functional-style cast}0 from %1 to %2 casts away qualifiers">; def err_bad_const_cast_dest : Error< "%select{const_cast||||C-style cast|functional-style cast}0 to %2, " "which is not a reference, pointer-to-object, or pointer-to-data-member">; @@ -2765,6 +2902,8 @@ def err_bad_cxx_cast_member_pointer_size : Error< "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer " "type %1 to member pointer type %2 of different size">; def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">; +def err_bad_reinterpret_cast_reference : Error< + "reinterpret_cast of a %0 to %1 needs its address which is not allowed">; // These messages don't adhere to the pattern. // FIXME: Display the path somehow better. @@ -2823,7 +2962,11 @@ def ext_array_size_conversion : Extension< "implicit conversion from array size expression of type %0 to " "%select{integral|enumeration}1 type %2 is a C++0x extension">, InGroup<CXX0x>; - +def err_address_space_qualified_new : Error< + "'new' cannot allocate objects of type %0 in address space '%1'">; +def err_address_space_qualified_delete : Error< + "'delete' cannot delete objects of type %0 in address space '%1'">; + def err_default_init_const : Error< "default initialization of an object of const type %0" "%select{| requires a user-provided default constructor}1">; @@ -2878,6 +3021,9 @@ def warn_overloaded_virtual : Warning< InGroup<OverloadedVirtual>, DefaultIgnore; def note_hidden_overloaded_virtual_declared_here : Note< "hidden overloaded virtual function %q0 declared here">; +def warn_using_directive_in_header : Warning< + "using namespace directive in global context in header">, + InGroup<HeaderHygiene>, DefaultIgnore; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " @@ -3067,11 +3213,6 @@ def err_typecheck_incompatible_address_space : Error< " changes address space of pointer">; def err_typecheck_convert_ambiguous : Error< "ambiguity in initializing value of type %0 with initializer of type %1">; -def err_cannot_initialize_decl_noname : Error< - "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 " - "of type %2">; -def err_cannot_initialize_decl : Error< - "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">; def err_typecheck_comparison_of_distinct_blocks : Error< "comparison of distinct block types (%0 and %1)">; @@ -3109,6 +3250,8 @@ def err_typecheck_call_too_few_args_at_least : Error< def err_typecheck_call_too_many_args : Error< "too many arguments to %select{function|block|method}0 call, " "expected %1, have %2">; +def note_typecheck_call_too_many_args : Note< + "%0 declared here">; def err_typecheck_call_too_many_args_at_most : Error< "too many arguments to %select{function|block|method}0 call, " "expected at most %1, have %2">; @@ -3196,6 +3339,8 @@ def warn_unused_call : Warning< def err_incomplete_type_used_in_type_trait_expr : Error< "incomplete type %0 used in type trait expression">; +def err_dimension_expr_not_constant_integer : Error< + "dimension expression does not evaluate to a constant unsigned int">; def err_expected_ident_or_lparen : Error<"expected identifier or '('">; def err_typecheck_cond_incompatible_operands_null : Error< @@ -3278,7 +3423,7 @@ def err_in_class_initializer_bad_type : Error< "static data member of type %0 must be initialized out of line">; def ext_in_class_initializer_float_type : ExtWarn< "in-class initializer for static data member of type %0 " - "is a C++0x extension">, InGroup<CXX0x>; + "is a C++0x extension">, InGroup<CXX0xStaticNonIntegralInitializer>; def err_in_class_initializer_non_constant : Error< "in-class initializer is not a constant expression">; @@ -3544,6 +3689,21 @@ def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " "unspecified (use strncmp instead)">; +// Generic selections. +def err_assoc_type_incomplete : Error< + "type %0 in generic association incomplete">; +def err_assoc_type_nonobject : Error< + "type %0 in generic association not an object type">; +def err_assoc_type_variably_modified : Error< + "type %0 in generic association is a variably modified type">; +def err_assoc_compatible_types : Error< + "type %0 in generic association compatible with previously specified type %1">; +def note_compat_assoc : Note< + "compatible type %0 specified here">; +def err_generic_sel_no_match : Error< + "controlling expression type %0 not compatible with any generic association type">; +def err_generic_sel_multi_match : Error< + "controlling expression type %0 compatible with %1 generic association types">; // Blocks @@ -3559,8 +3719,6 @@ def err_block_returning_array_function : Error< // CFString checking def err_cfstring_literal_not_string_constant : Error< "CFString literal is not a string constant">; -def warn_cfstring_literal_contains_nul_character : Warning< - "CFString literal contains NUL character">; def warn_cfstring_truncated : Warning< "input conversion stopped due to an input byte that does not " "belong to the input codeset UTF-8">; @@ -3722,6 +3880,8 @@ def warn_ivar_use_hidden : Warning< "local declaration of %0 hides instance variable">; def error_ivar_use_in_class_method : Error< "instance variable %0 accessed in class method">; +def error_implicit_ivar_access : Error< + "instance variable %0 cannot be accessed because 'self' has been redeclared">; def error_private_ivar_access : Error<"instance variable %0 is private">, AccessControl; def error_protected_ivar_access : Error<"instance variable %0 is protected">, @@ -3776,6 +3936,26 @@ def err_sizeof_pack_no_pack_name_suggest : Error< "%0 does not refer to the name of a parameter pack; did you mean %1?">; def note_parameter_pack_here : Note<"parameter pack %0 declared here">; +def err_uncasted_use_of_unknown_any : Error< + "%0 has unknown type; cast it to its declared type to use it">; +def err_uncasted_call_of_unknown_any : Error< + "%0 has unknown return type; cast the call to its declared return type">; +def err_unsupported_unknown_any_decl : Error< + "%0 has unknown type, which is unsupported for this kind of declaration">; +def err_unsupported_unknown_any_expr : Error< + "unsupported expression with unknown type">; +def err_unsupported_unknown_any_call : Error< + "call to unsupported expression with unknown type">; +def err_unknown_any_addrof : Error< + "the address of a declaration with unknown type " + "can only be cast to a pointer type">; +def err_unknown_any_var_function_type : Error< + "variable %0 with unknown type cannot be given a function type">; + +def err_filter_expression_integral : Error< + "filter expression type should be an integral value not %0">; + } // end of sema category + } // end of sema component. diff --git a/include/clang/Basic/ExceptionSpecificationType.h b/include/clang/Basic/ExceptionSpecificationType.h new file mode 100644 index 000000000000..aecf6eb269b7 --- /dev/null +++ b/include/clang/Basic/ExceptionSpecificationType.h @@ -0,0 +1,39 @@ +//===--- ExceptionSpecificationType.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 ExceptionSpecificationType enumeration and various +// utility functions. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H +#define LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H + +namespace clang { + +/// \brief The various types of exception specifications that exist in C++0x. +enum ExceptionSpecificationType { + EST_None, ///< no exception specification + EST_DynamicNone, ///< throw() + EST_Dynamic, ///< throw(T1, T2) + EST_MSAny, ///< Microsoft throw(...) extension + EST_BasicNoexcept, ///< noexcept + EST_ComputedNoexcept ///< noexcept(expression) +}; + +inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) { + return ESpecType >= EST_DynamicNone && ESpecType <= EST_MSAny; +} + +inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) { + return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept; +} + +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_EXCEPTIONSPECIFICATIONTYPE_H diff --git a/include/clang/Basic/ExpressionTraits.h b/include/clang/Basic/ExpressionTraits.h new file mode 100644 index 000000000000..403a59a8d19c --- /dev/null +++ b/include/clang/Basic/ExpressionTraits.h @@ -0,0 +1,25 @@ +//===--- ExpressionTraits.h - C++ Expression Traits Support Enumerations ----*- 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 enumerations for expression traits intrinsics. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_EXPRESSIONTRAITS_H +#define LLVM_CLANG_EXPRESSIONTRAITS_H + +namespace clang { + + enum ExpressionTrait { + ET_IsLValueExpr, + ET_IsRValueExpr + }; +} + +#endif diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 563157fa8fbe..2ca344d55370 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_FILEMANAGER_H #include "clang/Basic/FileSystemOptions.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" @@ -105,7 +106,7 @@ public: /// properties, such as uniquing files based on "inode", so that a file with two /// names (e.g. symlinked) will be treated as a single file. /// -class FileManager { +class FileManager : public llvm::RefCountedBase<FileManager> { FileSystemOptions FileSystemOpts; class UniqueDirContainer; @@ -176,10 +177,11 @@ public: /// const DirectoryEntry *getDirectory(llvm::StringRef DirName); - /// getFile - Lookup, cache, and verify the specified file (real or + /// \brief Lookup, cache, and verify the specified file (real or /// virtual). This returns NULL if the file doesn't exist. /// - const FileEntry *getFile(llvm::StringRef Filename); + /// \param openFile if true and the file exists, it will be opened. + const FileEntry *getFile(llvm::StringRef Filename, bool openFile = false); /// \brief Retrieve a file entry for a "virtual" file that acts as /// if there were a file with the given name on disk. The file @@ -194,13 +196,16 @@ public: llvm::MemoryBuffer *getBufferForFile(llvm::StringRef Filename, std::string *ErrorStr = 0); + // getNoncachedStatValue - Will get the 'stat' information for the given path. + // If the path is relative, it will be resolved against the WorkingDir of the + // FileManager's FileSystemOptions. + bool getNoncachedStatValue(llvm::StringRef Path, struct stat &StatBuf); + /// \brief If path is not absolute and FileSystemOptions set the working /// directory, the path is modified to be relative to the given /// working directory. - static void FixupRelativePath(llvm::sys::Path &path, - const FileSystemOptions &FSOpts); + void FixupRelativePath(llvm::SmallVectorImpl<char> &path) const; - /// \brief Produce an array mapping from the unique IDs assigned to each /// file to the corresponding FileEntry pointer. void GetUniqueIDMapping( diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index d576643550bd..683ec8312e91 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -255,6 +255,25 @@ private: } }; +/// \brief an RAII object for [un]poisoning an identifier +/// within a certain scope. II is allowed to be null, in +/// which case, objects of this type have no effect. +class PoisonIdentifierRAIIObject { + IdentifierInfo *const II; + const bool OldValue; +public: + PoisonIdentifierRAIIObject(IdentifierInfo *II, bool NewValue) + : II(II), OldValue(II ? II->isPoisoned() : false) { + if(II) + II->setIsPoisoned(NewValue); + } + + ~PoisonIdentifierRAIIObject() { + if(II) + II->setIsPoisoned(OldValue); + } +}; + /// \brief An iterator that walks over all of the known identifiers /// in the lookup table. /// @@ -325,7 +344,7 @@ public: /// IdentifierTable - This table implements an efficient mapping from strings to /// IdentifierInfo nodes. It has no other purpose, but this is an -/// extremely performance-critical piece of the code, as each occurrance of +/// extremely performance-critical piece of the code, as each occurrence of /// every identifier goes through here when lexed. class IdentifierTable { // Shark shows that using MallocAllocator is *much* slower than using this @@ -443,6 +462,52 @@ public: void AddKeywords(const LangOptions &LangOpts); }; +/// ObjCMethodFamily - A family of Objective-C methods. These +/// families have no inherent meaning in the language, but are +/// nonetheless central enough in the existing implementations to +/// merit direct AST support. While, in theory, arbitrary methods can +/// be considered to form families, we focus here on the methods +/// involving allocation and retain-count management, as these are the +/// most "core" and the most likely to be useful to diverse clients +/// without extra information. +/// +/// Both selectors and actual method declarations may be classified +/// into families. Method families may impose additional restrictions +/// beyond their selector name; for example, a method called '_init' +/// that returns void is not considered to be in the 'init' family +/// (but would be if it returned 'id'). It is also possible to +/// explicitly change or remove a method's family. Therefore the +/// method's family should be considered the single source of truth. +enum ObjCMethodFamily { + /// \brief No particular method family. + OMF_None, + + // Selectors in these families may have arbitrary arity, may be + // written with arbitrary leading underscores, and may have + // additional CamelCase "words" in their first selector chunk + // following the family name. + OMF_alloc, + OMF_copy, + OMF_init, + OMF_mutableCopy, + OMF_new, + + // These families are singletons consisting only of the nullary + // selector with the given name. + OMF_autorelease, + OMF_dealloc, + OMF_release, + OMF_retain, + OMF_retainCount +}; + +/// Enough bits to store any enumerator in ObjCMethodFamily or +/// InvalidObjCMethodFamily. +enum { ObjCMethodFamilyBitWidth = 4 }; + +/// An invalid value of ObjCMethodFamily. +enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 }; + /// Selector - This smart pointer class efficiently represents Objective-C /// method names. This class will either point to an IdentifierInfo or a /// MultiKeywordSelector (which is private). This enables us to optimize @@ -479,6 +544,8 @@ class Selector { return InfoPtr & ArgFlags; } + static ObjCMethodFamily getMethodFamilyImpl(Selector sel); + public: friend class SelectorTable; // only the SelectorTable can create these friend class DeclarationName; // and the AST's DeclarationName. @@ -541,6 +608,11 @@ public: /// it as an std::string. std::string getAsString() const; + /// getMethodFamily - Derive the conventional family of this method. + ObjCMethodFamily getMethodFamily() const { + return getMethodFamilyImpl(*this); + } + static Selector getEmptyMarker() { return Selector(uintptr_t(-1)); } @@ -571,6 +643,9 @@ public: return Selector(ID, 0); } + /// Return the total amount of memory allocated for managing selectors. + size_t getTotalMemory() const; + /// constructSetterName - Return the setter name for the given /// identifier, i.e. "set" + Name where the initial character of Name /// has been capitalized. diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 0bd983e8e6c6..a5f6789b7d1f 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -34,6 +34,7 @@ public: unsigned Digraphs : 1; // C94, C99 and C++ unsigned HexFloats : 1; // C99 Hexadecimal float constants. unsigned C99 : 1; // C99 Support + unsigned C1X : 1; // C1X Support unsigned Microsoft : 1; // Microsoft extensions. unsigned Borland : 1; // Borland extensions. unsigned CPlusPlus : 1; // C++ Support @@ -56,6 +57,7 @@ public: unsigned ObjCExceptions : 1; // Support Objective-C exceptions. unsigned CXXExceptions : 1; // Support C++ exceptions. unsigned SjLjExceptions : 1; // Use setjmp-longjump exception handling. + unsigned TraditionalCPP : 1; /// Enable some traditional CPP emulation. unsigned RTTI : 1; // Support RTTI information. unsigned MSBitfields : 1; // MS-compatible structure layout @@ -87,6 +89,8 @@ public: // used (instead of C99 semantics). unsigned NoInline : 1; // Should __NO_INLINE__ be defined. + unsigned Deprecated : 1; // Should __DEPRECATED be defined. + unsigned ObjCGCBitmapPrint : 1; // Enable printing of gc's bitmap layout // for __weak/__strong ivars. @@ -112,6 +116,7 @@ public: unsigned NoConstantCFStrings : 1; // Do not do CF strings unsigned InlineVisibilityHidden : 1; // Whether inline C++ methods have // hidden visibility by default. + unsigned ParseUnknownAnytype: 1; /// Let the user write __unknown_anytype. unsigned SpellChecking : 1; // Whether to perform spell-checking for error // recovery. @@ -123,6 +128,11 @@ public: unsigned DefaultFPContract : 1; // Default setting for FP_CONTRACT // FIXME: This is just a temporary option, for testing purposes. unsigned NoBitFieldTypeAlign : 1; + unsigned FakeAddressSpaceMap : 1; // Use a fake address space map, for + // testing languages such as OpenCL. + + unsigned MRTD : 1; // -mrtd calling convention + unsigned DelayedTemplateParsing : 1; // Delayed template parsing private: // We declare multibit enums as unsigned because MSVC insists on making enums @@ -164,10 +174,10 @@ public: AppleKext = 0; ObjCDefaultSynthProperties = 0; NoConstantCFStrings = 0; InlineVisibilityHidden = 0; - C99 = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; + C99 = C1X = Microsoft = Borland = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; Exceptions = ObjCExceptions = CXXExceptions = SjLjExceptions = 0; - Freestanding = NoBuiltin = 0; + TraditionalCPP = Freestanding = NoBuiltin = 0; MSBitfields = 0; NeXTRuntime = 1; RTTI = 1; @@ -205,6 +215,8 @@ public: GNUInline = 0; NoInline = 0; + Deprecated = 0; + CharIsSigned = 1; ShortWChar = 0; ShortEnums = 0; @@ -216,6 +228,10 @@ public: FastRelaxedMath = 0; DefaultFPContract = 0; NoBitFieldTypeAlign = 0; + FakeAddressSpaceMap = 0; + MRTD = 0; + DelayedTemplateParsing = 0; + ParseUnknownAnytype = 0; } GCMode getGCMode() const { return (GCMode) GC; } @@ -240,8 +256,8 @@ public: SignedOverflowBehavior = (unsigned)V; } - bool areExceptionsEnabled() const { - return Exceptions; + bool isSignedOverflowDefined() const { + return getSignedOverflowBehavior() == SOB_Defined; } }; diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile index bc64f6aab555..1338464fd5d9 100644 --- a/include/clang/Basic/Makefile +++ b/include/clang/Basic/Makefile @@ -4,7 +4,7 @@ BUILT_SOURCES = \ DiagnosticCommonKinds.inc DiagnosticDriverKinds.inc \ DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \ DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \ - DiagnosticGroups.inc AttrList.inc arm_neon.inc \ + DiagnosticIndexName.inc DiagnosticGroups.inc AttrList.inc arm_neon.inc \ Version.inc TABLEGEN_INC_FILES_COMMON = 1 @@ -33,6 +33,10 @@ $(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) $(TableGen) -gen-clang-diags-defs -clang-component=$(patsubst Diagnostic%Kinds.inc.tmp,%,$(@F)) -o $(call SYSPATH, $@) $< +$(ObjDir)/DiagnosticIndexName.inc.tmp : Diagnostic.td $(INPUT_TDS) $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang diagnostic name index with tblgen" + $(Verb) $(TableGen) -gen-clang-diags-index-name -o $(call SYSPATH, $@) $< + $(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_TDS) $(TBLGEN) $(ObjDir)/.dir $(Echo) "Building Clang diagnostic groups with tblgen" $(Verb) $(TableGen) -gen-clang-diag-groups -o $(call SYSPATH, $@) $< diff --git a/include/clang/Basic/OpenCL.h b/include/clang/Basic/OpenCL.h new file mode 100644 index 000000000000..6f9785f25677 --- /dev/null +++ b/include/clang/Basic/OpenCL.h @@ -0,0 +1,28 @@ +//===--- OpenCL.h - OpenCL enums --------------------------------*- 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 some OpenCL-specific enums. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_OPENCL_H +#define LLVM_CLANG_BASIC_OPENCL_H + +namespace clang { + +/// Names for the OpenCL image access qualifiers (OpenCL 1.1 6.6). +enum OpenCLImageAccess { + CLIA_read_only = 1, + CLIA_write_only = 2, + CLIA_read_write = 3 +}; + +} + +#endif diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index c63619440551..7d7c0896f505 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -53,7 +53,7 @@ public: /// DiagArgumentsVal - The values for the various substitution positions. /// This is used when the argument is not an std::string. The specific value - /// is mangled into an intptr_t and the intepretation depends on exactly + /// is mangled into an intptr_t and the interpretation depends on exactly /// what sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index 605c4bbafc74..14bb2b724fd4 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -16,6 +16,7 @@ #include "llvm/Support/PointerLikeTypeTraits.h" #include <utility> +#include <functional> #include <cassert> namespace llvm { @@ -295,6 +296,14 @@ public: return isBeforeInTranslationUnitThan((SourceLocation)Loc); } + /// \brief Comparison function class, useful for sorting FullSourceLocs. + struct BeforeThanCompare : public std::binary_function<FullSourceLoc, + FullSourceLoc, bool> { + bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { + return lhs.isBeforeInTranslationUnitThan(rhs); + } + }; + /// Prints information about this FullSourceLoc to stderr. Useful for /// debugging. void dump() const { SourceLocation::dump(*SrcMgr); } diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index b1443dad09fd..c121bbb34f34 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -19,12 +19,13 @@ #include "llvm/Support/DataTypes.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/MemoryBuffer.h" #include <vector> #include <cassert> namespace llvm { -class MemoryBuffer; class StringRef; } @@ -66,10 +67,16 @@ namespace SrcMgr { mutable llvm::PointerIntPair<const llvm::MemoryBuffer *, 2> Buffer; public: - /// Reference to the file entry. This reference does not own - /// the FileEntry object. It is possible for this to be NULL if + /// Reference to the file entry representing this ContentCache. + /// This reference does not own the FileEntry object. + /// It is possible for this to be NULL if /// the ContentCache encapsulates an imaginary text buffer. - const FileEntry *Entry; + const FileEntry *OrigEntry; + + /// \brief References the file which the contents were actually loaded from. + /// Can be different from 'Entry' if we overridden the contents of one file + /// with the contents of another file. + const FileEntry *ContentsEntry; /// SourceLineCache - A bump pointer allocated array of offsets for each /// source line. This is lazily computed. This is owned by the @@ -104,6 +111,10 @@ namespace SrcMgr { /// this ContentCache. This can be 0 if the MemBuffer was not actually /// instantiated. unsigned getSizeBytesMapped() const; + + /// Returns the kind of memory used to back the memory buffer for + /// this content cache. This is used for performance analysis. + llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; void setBuffer(const llvm::MemoryBuffer *B) { assert(!Buffer.getPointer() && "MemoryBuffer already set."); @@ -132,17 +143,23 @@ namespace SrcMgr { } ContentCache(const FileEntry *Ent = 0) - : Buffer(0, false), Entry(Ent), SourceLineCache(0), NumLines(0) {} + : Buffer(0, false), OrigEntry(Ent), ContentsEntry(Ent), + SourceLineCache(0), NumLines(0) {} + + ContentCache(const FileEntry *Ent, const FileEntry *contentEnt) + : Buffer(0, false), OrigEntry(Ent), ContentsEntry(contentEnt), + SourceLineCache(0), NumLines(0) {} ~ContentCache(); /// The copy ctor does not allow copies where source object has either /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory - /// is not transfered, so this is a logical error. + /// is not transferred, so this is a logical error. ContentCache(const ContentCache &RHS) : Buffer(0, false), SourceLineCache(0) { - Entry = RHS.Entry; + OrigEntry = RHS.OrigEntry; + ContentsEntry = RHS.ContentsEntry; assert (RHS.Buffer.getPointer() == 0 && RHS.SourceLineCache == 0 && "Passed ContentCache object cannot own a buffer."); @@ -301,7 +318,10 @@ public: virtual ~ExternalSLocEntrySource(); /// \brief Read the source location entry with index ID. - virtual void ReadSLocEntry(unsigned ID) = 0; + /// + /// \returns true if an error occurred that prevented the source-location + /// entry from being loaded. + virtual bool ReadSLocEntry(unsigned ID) = 0; }; @@ -364,9 +384,9 @@ public: /// Spelling locations represent where the bytes corresponding to a token came /// from and instantiation locations represent where the location is in the /// user's view. In the case of a macro expansion, for example, the spelling -/// location indicates where the expanded token came from and the instantiation +/// location indicates where the expanded token came from and the instantiation /// location specifies where it was expanded. -class SourceManager { +class SourceManager : public llvm::RefCountedBase<SourceManager> { /// \brief Diagnostic object. Diagnostic &Diag; @@ -380,6 +400,13 @@ class SourceManager { /// non-null, FileEntry pointers. llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos; + /// \brief True if the ContentCache for files that are overriden by other + /// files, should report the original file name. Defaults to true. + bool OverridenFilesKeepOriginalName; + + /// \brief Files that have been overriden with the contents from another file. + llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles; + /// MemBufferInfos - Information about various memory buffers that we have /// read in. All FileEntry* within the stored ContentCache objects are NULL, /// as they do not refer to a file. @@ -425,6 +452,9 @@ class SourceManager { // Cache results for the isBeforeInTranslationUnit method. mutable IsBeforeInTranslationUnitCache IsBeforeInTUCache; + // Cache for the "fake" buffer used for error-recovery purposes. + mutable llvm::MemoryBuffer *FakeBufferForRecovery; + // SourceManager doesn't support copy construction. explicit SourceManager(const SourceManager&); void operator=(const SourceManager&); @@ -438,6 +468,12 @@ public: FileManager &getFileManager() const { return FileMgr; } + /// \brief Set true if the SourceManager should report the original file name + /// for contents of files that were overriden by other files.Defaults to true. + void setOverridenFilesKeepOriginalName(bool value) { + OverridenFilesKeepOriginalName = value; + } + //===--------------------------------------------------------------------===// // MainFileID creation and querying methods. //===--------------------------------------------------------------------===// @@ -527,6 +563,15 @@ public: const llvm::MemoryBuffer *Buffer, bool DoNotFree = false); + /// \brief Override the the given source file with another one. + /// + /// \param SourceFile the source file which will be overriden. + /// + /// \param NewFile the file whose contents will be used as the + /// data instead of the contents of the given source file. + void overrideFileContents(const FileEntry *SourceFile, + const FileEntry *NewFile); + //===--------------------------------------------------------------------===// // FileID manipulation methods. //===--------------------------------------------------------------------===// @@ -536,18 +581,48 @@ public: /// buffer and returns a non-empty error string. const llvm::MemoryBuffer *getBuffer(FileID FID, SourceLocation Loc, bool *Invalid = 0) const { - return getSLocEntry(FID).getFile().getContentCache() - ->getBuffer(Diag, *this, Loc, Invalid); + bool MyInvalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); + if (MyInvalid || !Entry.isFile()) { + if (Invalid) + *Invalid = true; + + return getFakeBufferForRecovery(); + } + + return Entry.getFile().getContentCache()->getBuffer(Diag, *this, Loc, + Invalid); } const llvm::MemoryBuffer *getBuffer(FileID FID, bool *Invalid = 0) const { - return getSLocEntry(FID).getFile().getContentCache() - ->getBuffer(Diag, *this, SourceLocation(), Invalid); + bool MyInvalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); + if (MyInvalid || !Entry.isFile()) { + if (Invalid) + *Invalid = true; + + return getFakeBufferForRecovery(); + } + + return Entry.getFile().getContentCache()->getBuffer(Diag, *this, + SourceLocation(), + Invalid); } /// getFileEntryForID - Returns the FileEntry record for the provided FileID. const FileEntry *getFileEntryForID(FileID FID) const { - return getSLocEntry(FID).getFile().getContentCache()->Entry; + bool MyInvalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); + if (MyInvalid || !Entry.isFile()) + return 0; + + return Entry.getFile().getContentCache()->OrigEntry; + } + + /// Returns the FileEntry record for the provided SLocEntry. + const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const + { + return sloc.getFile().getContentCache()->OrigEntry; } /// getBufferData - Return a StringRef to the source buffer data for the @@ -581,8 +656,12 @@ public: /// first byte of the specified file. SourceLocation getLocForStartOfFile(FileID FID) const { assert(FID.ID < SLocEntryTable.size() && "FileID out of range"); - assert(getSLocEntry(FID).isFile() && "FileID is not a file"); - unsigned FileOffset = getSLocEntry(FID).getOffset(); + bool Invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); + if (Invalid || !Entry.isFile()) + return SourceLocation(); + + unsigned FileOffset = Entry.getOffset(); return SourceLocation::getFileLoc(FileOffset); } @@ -775,6 +854,28 @@ public: LineTableInfo &getLineTable(); //===--------------------------------------------------------------------===// + // Queries for performance analysis. + //===--------------------------------------------------------------------===// + + /// Return the total amount of physical memory allocated by the + /// ContentCache allocator. + size_t getContentCacheSize() const { + return ContentCacheAlloc.getTotalMemory(); + } + + struct MemoryBufferSizes { + const size_t malloc_bytes; + const size_t mmap_bytes; + + MemoryBufferSizes(size_t malloc_bytes, size_t mmap_bytes) + : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} + }; + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + MemoryBufferSizes getMemoryBufferSizes() const; + + //===--------------------------------------------------------------------===// // Other miscellaneous methods. //===--------------------------------------------------------------------===// @@ -810,17 +911,22 @@ public: // any other external source). unsigned sloc_loaded_entry_size() const { return SLocEntryLoaded.size(); } - const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const { + const SrcMgr::SLocEntry &getSLocEntry(unsigned ID, bool *Invalid = 0) const { assert(ID < SLocEntryTable.size() && "Invalid id"); + // If we haven't loaded this source-location entry from the external source + // yet, do so now. if (ExternalSLocEntries && ID < SLocEntryLoaded.size() && - !SLocEntryLoaded[ID]) - ExternalSLocEntries->ReadSLocEntry(ID); + !SLocEntryLoaded[ID] && + ExternalSLocEntries->ReadSLocEntry(ID) && + Invalid) + *Invalid = true; + return SLocEntryTable[ID]; } - const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const { - return getSLocEntry(FID.ID); + const SrcMgr::SLocEntry &getSLocEntry(FileID FID, bool *Invalid = 0) const { + return getSLocEntry(FID.ID, Invalid); } unsigned getNextOffset() const { return NextOffset; } @@ -836,6 +942,8 @@ public: void ClearPreallocatedSLocEntries(); private: + const llvm::MemoryBuffer *getFakeBufferForRecovery() const; + /// isOffsetInFileID - Return true if the specified FileID contains the /// specified SourceLocation offset. This is a very hot method. inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const { diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index e6b6218100ad..2f0ad9ffb688 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -55,6 +55,7 @@ namespace clang { TST_typeofExpr, TST_decltype, // C++0x decltype TST_auto, // C++0x auto + TST_unknown_anytype, // __unknown_anytype extension TST_error // erroneous type }; diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index be0d8ff091e8..15ac760ce725 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -41,6 +41,7 @@ def ObjCForCollectionStmt : Stmt; // C++ statments def CXXCatchStmt : Stmt; def CXXTryStmt : Stmt; +def CXXForRangeStmt : Stmt; // Expressions def Expr : Stmt<1>; @@ -54,7 +55,7 @@ def CharacterLiteral : DStmt<Expr>; def ParenExpr : DStmt<Expr>; def UnaryOperator : DStmt<Expr>; def OffsetOfExpr : DStmt<Expr>; -def SizeOfAlignOfExpr : DStmt<Expr>; +def UnaryExprOrTypeTraitExpr : DStmt<Expr>; def ArraySubscriptExpr : DStmt<Expr>; def CallExpr : DStmt<Expr>; def MemberExpr : DStmt<Expr>; @@ -74,6 +75,7 @@ def DesignatedInitExpr : DStmt<Expr>; def ImplicitValueInitExpr : DStmt<Expr>; def ParenListExpr : DStmt<Expr>; def VAArgExpr : DStmt<Expr>; +def GenericSelectionExpr : DStmt<Expr>; // GNU Extensions. def AddrLabelExpr : DStmt<Expr>; @@ -102,6 +104,8 @@ def CXXDeleteExpr : DStmt<Expr>; def CXXPseudoDestructorExpr : DStmt<Expr>; def UnaryTypeTraitExpr : DStmt<Expr>; def BinaryTypeTraitExpr : DStmt<Expr>; +def ArrayTypeTraitExpr : DStmt<Expr>; +def ExpressionTraitExpr : DStmt<Expr>; def DependentScopeDeclRefExpr : DStmt<Expr>; def CXXConstructExpr : DStmt<Expr>; def CXXBindTemporaryExpr : DStmt<Expr>; @@ -138,4 +142,7 @@ def OpaqueValueExpr : DStmt<Expr>; // Microsoft Extensions. def CXXUuidofExpr : DStmt<Expr>; +def SEHTryStmt : Stmt; +def SEHExceptStmt : Stmt; +def SEHFinallyStmt : Stmt; diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index f1edd1d45162..8bc60ff5386d 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -35,6 +35,17 @@ namespace clang { }; } + /// PTX builtins + namespace PTX { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, +#define BUILTIN(ID, TYPE, ATTRS) BI##ID, +#include "clang/Basic/BuiltinsPTX.def" + LastTSBuiltin + }; + } + + /// X86 builtins namespace X86 { enum { diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index b9087f2c47e8..b830bf2f82cd 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -14,18 +14,20 @@ #ifndef LLVM_CLANG_BASIC_TARGETINFO_H #define LLVM_CLANG_BASIC_TARGETINFO_H -// FIXME: Daniel isn't smart enough to use a prototype for this. +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/DataTypes.h" +#include "clang/Basic/AddressSpaces.h" +#include "clang/Basic/VersionTuple.h" #include <cassert> #include <vector> #include <string> namespace llvm { struct fltSemantics; -class StringRef; } namespace clang { @@ -56,7 +58,7 @@ enum TargetCXXABI { /// TargetInfo - This class exposes information about the current target. /// -class TargetInfo { +class TargetInfo : public llvm::RefCountedBase<TargetInfo> { llvm::Triple Triple; protected: // Target values set by the ctor of the actual target implementation. Default @@ -78,6 +80,10 @@ protected: const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat; unsigned char RegParmMax, SSERegParmMax; TargetCXXABI CXXABI; + const LangAS::Map *AddrSpaceMap; + + mutable llvm::StringRef PlatformName; + mutable VersionTuple PlatformMinVersion; unsigned HasAlignMac68kSupport : 1; unsigned RealTypeUsesObjCFPRet : 3; @@ -530,6 +536,19 @@ public: virtual const char *getStaticInitSectionSpecifier() const { return 0; } + + const LangAS::Map &getAddressSpaceMap() const { + return *AddrSpaceMap; + } + + /// \brief Retrieve the name of the platform as it is used in the + /// availability attribute. + llvm::StringRef getPlatformName() const { return PlatformName; } + + /// \brief Retrieve the minimum desired version of the platform, to + /// which the program should be compiled. + VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; } + protected: virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return PointerWidth; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index b84b04da3de2..f9d1f4ef158e 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -38,6 +38,9 @@ #ifndef OBJC2_AT_KEYWORD #define OBJC2_AT_KEYWORD(X) #endif +#ifndef TESTING_KEYWORD +#define TESTING_KEYWORD(X, L) KEYWORD(X, L) +#endif #ifndef ANNOTATION #define ANNOTATION(X) TOK(annot_ ## X) #endif @@ -94,7 +97,8 @@ PPKEYWORD(unassert) TOK(unknown) // Not a token. TOK(eof) // End of file. -TOK(eom) // End of macro (end of line inside a macro). +TOK(eod) // End of preprocessing directive (end of line inside a + // directive). TOK(code_completion) // Code completion marker TOK(cxx_defaultarg_end) // C++ default argument end marker @@ -186,6 +190,7 @@ PUNCTUATOR(greatergreatergreater, ">>>") // is a keyword in the implementation namespace that should // always be treated as a keyword // KEYC99 - This is a keyword introduced to C in C99 +// KEYC1X - This is a keyword introduced to C in C1X // KEYCXX - This is a C++ keyword, or a C++-specific keyword in the // implementation namespace // KEYNOCXX - This is a keyword in every non-C++ dialect. @@ -195,6 +200,7 @@ PUNCTUATOR(greatergreatergreater, ">>>") // KEYOPENCL - This is a keyword in OpenCL // KEYALTIVEC - This is a keyword in AltiVec // KEYBORLAND - This is a keyword if Borland extensions are enabled +// BOOLSUPPORT - This is a keyword if 'bool' is a built-in type // KEYWORD(auto , KEYALL) KEYWORD(break , KEYALL) @@ -232,7 +238,9 @@ KEYWORD(volatile , KEYALL) KEYWORD(while , KEYALL) KEYWORD(_Bool , KEYNOCXX) KEYWORD(_Complex , KEYALL) +KEYWORD(_Generic , KEYALL) KEYWORD(_Imaginary , KEYALL) +KEYWORD(_Static_assert , KEYALL) KEYWORD(__func__ , KEYALL) // C++ 2.11p1: Keywords. @@ -251,7 +259,7 @@ KEYWORD(mutable , KEYCXX) KEYWORD(namespace , KEYCXX) KEYWORD(new , KEYCXX) KEYWORD(operator , KEYCXX) -KEYWORD(private , KEYCXX) +KEYWORD(private , KEYCXX|KEYOPENCL) KEYWORD(protected , KEYCXX) KEYWORD(public , KEYCXX) KEYWORD(reinterpret_cast , KEYCXX) @@ -328,11 +336,50 @@ KEYWORD(__is_class , KEYCXX) KEYWORD(__is_convertible_to , KEYCXX) KEYWORD(__is_empty , KEYCXX) KEYWORD(__is_enum , KEYCXX) +// Tentative name - there's no implementation of std::is_literal_type yet. +KEYWORD(__is_literal , KEYCXX) +// Name for GCC 4.6 compatibility - people have already written libraries using +// this name unfortunately. +KEYWORD(__is_literal_type , KEYCXX) KEYWORD(__is_pod , KEYCXX) KEYWORD(__is_polymorphic , KEYCXX) +KEYWORD(__is_trivial , KEYCXX) KEYWORD(__is_union , KEYCXX) -// Tentative name - there's no implementation of std::is_literal_type yet. -KEYWORD(__is_literal , KEYCXX) + +// Embarcadero Expression Traits +KEYWORD(__is_lvalue_expr , KEYCXX) +KEYWORD(__is_rvalue_expr , KEYCXX) + +// Embarcadero Unary Type Traits +KEYWORD(__is_arithmetic , KEYCXX) +KEYWORD(__is_floating_point , KEYCXX) +KEYWORD(__is_integral , KEYCXX) +KEYWORD(__is_complete_type , KEYCXX) +KEYWORD(__is_void , KEYCXX) +KEYWORD(__is_array , KEYCXX) +KEYWORD(__is_function , KEYCXX) +KEYWORD(__is_reference , KEYCXX) +KEYWORD(__is_lvalue_reference , KEYCXX) +KEYWORD(__is_rvalue_reference , KEYCXX) +KEYWORD(__is_fundamental , KEYCXX) +KEYWORD(__is_object , KEYCXX) +KEYWORD(__is_scalar , KEYCXX) +KEYWORD(__is_compound , KEYCXX) +KEYWORD(__is_pointer , KEYCXX) +KEYWORD(__is_member_object_pointer , KEYCXX) +KEYWORD(__is_member_function_pointer, KEYCXX) +KEYWORD(__is_member_pointer , KEYCXX) +KEYWORD(__is_const , KEYCXX) +KEYWORD(__is_volatile , KEYCXX) +KEYWORD(__is_standard_layout , KEYCXX) +KEYWORD(__is_signed , KEYCXX) +KEYWORD(__is_unsigned , KEYCXX) + +// Embarcadero Binary Type Traits +KEYWORD(__is_same , KEYCXX) +KEYWORD(__is_convertible , KEYCXX) +KEYWORD(__array_rank , KEYCXX) +KEYWORD(__array_extent , KEYCXX) // Apple Extension. KEYWORD(__private_extern__ , KEYALL) @@ -345,9 +392,23 @@ KEYWORD(__fastcall , KEYALL) KEYWORD(__thiscall , KEYALL) KEYWORD(__forceinline , KEYALL) -// OpenCL-specific keywords (see OpenCL 1.1 [6.1.9]) +// OpenCL-specific keywords KEYWORD(__kernel , KEYOPENCL) ALIAS("kernel", __kernel , KEYOPENCL) +KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC) +KEYWORD(__private , KEYOPENCL) +KEYWORD(__global , KEYOPENCL) +KEYWORD(__local , KEYOPENCL) +KEYWORD(__constant , KEYOPENCL) +ALIAS("global", __global , KEYOPENCL) +ALIAS("local", __local , KEYOPENCL) +ALIAS("constant", __constant , KEYOPENCL) +KEYWORD(__read_only , KEYOPENCL) +KEYWORD(__write_only , KEYOPENCL) +KEYWORD(__read_write , KEYOPENCL) +ALIAS("read_only", __read_only , KEYOPENCL) +ALIAS("write_only", __write_only , KEYOPENCL) +ALIAS("read_write", __read_write , KEYOPENCL) // Borland Extensions. KEYWORD(__pascal , KEYALL) @@ -358,18 +419,19 @@ KEYWORD(__pixel , KEYALTIVEC) // Alternate spelling for various tokens. There are GCC extensions in all // languages, but should not be disabled in strict conformance mode. -ALIAS("__attribute__", __attribute, KEYALL) -ALIAS("__const" , const , KEYALL) -ALIAS("__const__" , const , KEYALL) ALIAS("__alignof__" , __alignof , KEYALL) ALIAS("__asm" , asm , KEYALL) ALIAS("__asm__" , asm , KEYALL) +ALIAS("__attribute__", __attribute, KEYALL) ALIAS("__complex" , _Complex , KEYALL) ALIAS("__complex__" , _Complex , KEYALL) +ALIAS("__const" , const , KEYALL) +ALIAS("__const__" , const , KEYALL) +ALIAS("__decltype" , decltype , KEYCXX) ALIAS("__imag__" , __imag , KEYALL) ALIAS("__inline" , inline , KEYALL) ALIAS("__inline__" , inline , KEYALL) -ALIAS("__nullptr" , nullptr , KEYCXX) +ALIAS("__nullptr" , nullptr , KEYCXX) ALIAS("__real__" , __real , KEYALL) ALIAS("__restrict" , restrict , KEYALL) ALIAS("__restrict__" , restrict , KEYALL) @@ -384,6 +446,14 @@ ALIAS("__volatile__" , volatile , KEYALL) KEYWORD(__ptr64 , KEYMS) KEYWORD(__w64 , KEYMS) KEYWORD(__uuidof , KEYMS | KEYBORLAND) +KEYWORD(__try , KEYMS | KEYBORLAND) +KEYWORD(__except , KEYMS | KEYBORLAND) +KEYWORD(__finally , KEYMS | KEYBORLAND) +KEYWORD(__leave , KEYMS | KEYBORLAND) +KEYWORD(__int64 , KEYMS) +ALIAS("__int8" , char , KEYMS) +ALIAS("__int16" , short , KEYMS) +ALIAS("__int32" , int , KEYMS) ALIAS("_asm" , asm , KEYMS) ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND) ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND) @@ -391,6 +461,8 @@ ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND) ALIAS("_thiscall" , __thiscall , KEYMS) ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) ALIAS("_inline" , inline , KEYMS) +ALIAS("_declspec" , __declspec , KEYMS) +ALIAS("__interface" , class , KEYMS) // Borland Extensions which should be disabled in strict conformance mode. ALIAS("_pascal" , __pascal , KEYBORLAND) @@ -399,9 +471,12 @@ ALIAS("_pascal" , __pascal , KEYBORLAND) ALIAS("__char16_t" , char16_t , KEYCXX) ALIAS("__char32_t" , char32_t , KEYCXX) +// Clang-specific keywords enabled only in testing. +TESTING_KEYWORD(__unknown_anytype , KEYALL) + //===----------------------------------------------------------------------===// -// Objective-C @-preceeded keywords. +// Objective-C @-preceded keywords. //===----------------------------------------------------------------------===// // These have meaning after an '@' in Objective-C mode. These define enums in @@ -443,6 +518,7 @@ ANNOTATION(typename) // annotation for a C typedef name, a C++ (possibly ANNOTATION(template_id) // annotation for a C++ template-id that names a // function template specialization (not a type), // e.g., "std::swap<int>" +ANNOTATION(primary_expr) // annotation for a primary expression // Annotation for #pragma unused(...) // For each argument inside the parentheses the pragma handler will produce @@ -450,6 +526,7 @@ ANNOTATION(template_id) // annotation for a C++ template-id that names a ANNOTATION(pragma_unused) #undef ANNOTATION +#undef TESTING_KEYWORD #undef OBJC2_AT_KEYWORD #undef OBJC1_AT_KEYWORD #undef CXX_KEYWORD_OPERATOR diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 00c6e9ed5000..4a2a2c67e0eb 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -27,20 +27,59 @@ namespace clang { UTT_HasTrivialDestructor, UTT_HasVirtualDestructor, UTT_IsAbstract, + UTT_IsArithmetic, + UTT_IsArray, UTT_IsClass, + UTT_IsCompleteType, + UTT_IsCompound, + UTT_IsConst, UTT_IsEmpty, UTT_IsEnum, + UTT_IsFloatingPoint, + UTT_IsFunction, + UTT_IsFundamental, + UTT_IsIntegral, + UTT_IsLiteral, + UTT_IsLvalueReference, + UTT_IsMemberFunctionPointer, + UTT_IsMemberObjectPointer, + UTT_IsMemberPointer, + UTT_IsObject, UTT_IsPOD, + UTT_IsPointer, UTT_IsPolymorphic, + UTT_IsReference, + UTT_IsRvalueReference, + UTT_IsScalar, + UTT_IsSigned, + UTT_IsStandardLayout, + UTT_IsTrivial, UTT_IsUnion, - UTT_IsLiteral + UTT_IsUnsigned, + UTT_IsVoid, + UTT_IsVolatile }; /// BinaryTypeTrait - Names for the binary type traits. enum BinaryTypeTrait { BTT_IsBaseOf, - BTT_TypeCompatible, - BTT_IsConvertibleTo + BTT_IsConvertible, + BTT_IsConvertibleTo, + BTT_IsSame, + BTT_TypeCompatible + }; + + /// ArrayTypeTrait - Names for the array type traits. + enum ArrayTypeTrait { + ATT_ArrayRank, + ATT_ArrayExtent + }; + + /// UnaryExprOrTypeTrait - Names for the "expression or type" traits. + enum UnaryExprOrTypeTrait { + UETT_SizeOf, + UETT_AlignOf, + UETT_VecStep }; } diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h index ede68ed50d52..15cdf1fa02e6 100644 --- a/include/clang/Basic/Version.h +++ b/include/clang/Basic/Version.h @@ -58,6 +58,11 @@ namespace clang { /// which includes the clang version number, the repository version, /// and the vendor tag. std::string getClangFullVersion(); + + /// \brief Retrieves a string representing the complete clang version suitable + /// for use in the CPP __VERSION__ macro, which includes the clang version + /// number, the repository version, and the vendor tag. + std::string getClangFullCPPVersion(); } #endif // LLVM_CLANG_BASIC_VERSION_H diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h new file mode 100644 index 000000000000..91eb68eaad9f --- /dev/null +++ b/include/clang/Basic/VersionTuple.h @@ -0,0 +1,126 @@ +//===- VersionTuple.h - Version Number Handling -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the VersionTuple class, which represents a version in +// the form major[.minor[.subminor]]. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H +#define LLVM_CLANG_BASIC_VERSIONTUPLE_H + +#include "llvm/ADT/Optional.h" +#include <string> + +namespace llvm { + class raw_ostream; +} + +namespace clang { + +/// \brief Represents a version number in the form major[.minor[.subminor]]. +class VersionTuple { + unsigned Major; + unsigned Minor : 31; + unsigned Subminor : 31; + unsigned HasMinor : 1; + unsigned HasSubminor : 1; + +public: + VersionTuple() + : Major(0), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false) { } + + explicit VersionTuple(unsigned Major) + : Major(Major), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false) + { } + + explicit VersionTuple(unsigned Major, unsigned Minor) + : Major(Major), Minor(Minor), Subminor(0), HasMinor(true), + HasSubminor(false) + { } + + explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor) + : Major(Major), Minor(Minor), Subminor(Subminor), HasMinor(true), + HasSubminor(true) + { } + + /// \brief Determine whether this version information is empty + /// (e.g., all version components are zero). + bool empty() const { return Major == 0 && Minor == 0 && Subminor == 0; } + + /// \brief Retrieve the major version number. + unsigned getMajor() const { return Major; } + + /// \brief Retrieve the minor version number, if provided. + llvm::Optional<unsigned> getMinor() const { + if (!HasMinor) + return llvm::Optional<unsigned>(); + return Minor; + } + + /// \brief Retrieve the subminor version number, if provided. + llvm::Optional<unsigned> getSubminor() const { + if (!HasSubminor) + return llvm::Optional<unsigned>(); + return Subminor; + } + + /// \brief Determine if two version numbers are equivalent. If not + /// provided, minor and subminor version numbers are considered to be zero. + friend bool operator==(const VersionTuple& X, const VersionTuple &Y) { + return X.Major == Y.Major && X.Minor == Y.Minor && X.Subminor == Y.Subminor; + } + + /// \brief Determine if two version numbers are not equivalent. If + /// not provided, minor and subminor version numbers are considered to be + /// zero. + friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) { + return !(X == Y); + } + + /// \brief Determine whether one version number precedes another. If not + /// provided, minor and subminor version numbers are considered to be zero. + friend bool operator<(const VersionTuple &X, const VersionTuple &Y) { + if (X.Major != Y.Major) + return X.Major < Y.Major; + + if (X.Minor != Y.Minor) + return X.Minor < Y.Minor; + + return X.Subminor < Y.Subminor; + } + + /// \brief Determine whether one version number follows another. If not + /// provided, minor and subminor version numbers are considered to be zero. + friend bool operator>(const VersionTuple &X, const VersionTuple &Y) { + return Y < X; + } + + /// \brief Determine whether one version number precedes or is + /// equivalent to another. If not provided, minor and subminor + /// version numbers are considered to be zero. + friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) { + return !(Y < X); + } + + /// \brief Determine whether one version number follows or is + /// equivalent to another. If not provided, minor and subminor + /// version numbers are considered to be zero. + friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) { + return !(X < Y); + } + + /// \brief Retrieve a string representation of the version number/ + std::string getAsString() const; +}; + +/// \brief Print a version number. +llvm::raw_ostream& operator<<(llvm::raw_ostream &Out, const VersionTuple &V); + +} // end namespace clang +#endif // LLVM_CLANG_BASIC_VERSIONTUPLE_H diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 880a0da6bc68..6d6c7c7bede3 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -22,13 +22,11 @@ def OP_SUB : Op; def OP_SUBL : Op; def OP_SUBW : Op; def OP_MUL : Op; -def OP_MULL : Op; def OP_MLA : Op; def OP_MLAL : Op; def OP_MLS : Op; def OP_MLSL : Op; def OP_MUL_N : Op; -def OP_MULL_N: Op; def OP_MLA_N : Op; def OP_MLS_N : Op; def OP_MLAL_N : Op; @@ -144,8 +142,7 @@ def VQDMULH : SInst<"vqdmulh", "ddd", "siQsQi">; def VQRDMULH : SInst<"vqrdmulh", "ddd", "siQsQi">; def VQDMLAL : SInst<"vqdmlal", "wwdd", "si">; def VQDMLSL : SInst<"vqdmlsl", "wwdd", "si">; -def VMULL : Inst<"vmull", "wdd", "csiUcUsUi", OP_MULL>; -def VMULLP : SInst<"vmull", "wdd", "Pc">; +def VMULL : SInst<"vmull", "wdd", "csiUcUsUiPc">; def VQDMULL : SInst<"vqdmull", "wdd", "si">; //////////////////////////////////////////////////////////////////////////////// @@ -331,7 +328,7 @@ def VMLSL_LANE : Inst<"vmlsl_lane", "wwddi", "siUsUi", OP_MLSL_LN>; def VQDMLSL_LANE : Inst<"vqdmlsl_lane", "wwddi", "si", OP_QDMLSL_LN>; def VMUL_N : Inst<"vmul_n", "dds", "sifUsUiQsQiQfQUsQUi", OP_MUL_N>; def VMUL_LANE : Inst<"vmul_lane", "ddgi", "sifUsUiQsQiQfQUsQUi", OP_MUL_LN>; -def VMULL_N : Inst<"vmull_n", "wda", "siUsUi", OP_MULL_N>; +def VMULL_N : SInst<"vmull_n", "wda", "siUsUi">; def VMULL_LANE : Inst<"vmull_lane", "wddi", "siUsUi", OP_MULL_LN>; def VQDMULL_N : SInst<"vqdmull_n", "wda", "si">; def VQDMULL_LANE : Inst<"vqdmull_lane", "wddi", "si", OP_QDMULL_LN>; diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h index a52789e69929..265d6d871672 100644 --- a/include/clang/Driver/Arg.h +++ b/include/clang/Driver/Arg.h @@ -13,7 +13,6 @@ #include "Util.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include <vector> #include <string> namespace clang { diff --git a/include/clang/Driver/CC1AsOptions.td b/include/clang/Driver/CC1AsOptions.td index 50472ffdf9cd..2643c4f0e854 100644 --- a/include/clang/Driver/CC1AsOptions.td +++ b/include/clang/Driver/CC1AsOptions.td @@ -29,6 +29,10 @@ def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">, HelpText<"Add directory to include search path">; def n : Flag<"-n">, HelpText<"Don't automatically start assembly file with a text section">; +def L : Flag<"-L">, + HelpText<"Save temporary labels in the symbol table. " + "Note this may change .s semantics, it should almost never be used " + "on compiler generated code!">; //===----------------------------------------------------------------------===// // Frontend Options @@ -72,4 +76,4 @@ def relax_all : Flag<"-relax-all">, HelpText<"Relax all fixups (for performance testing)">; def no_exec_stack : Flag<"--noexecstack">, - HelpText<"Mark the file as not needing an executable stack">;
\ No newline at end of file + HelpText<"Mark the file as not needing an executable stack">; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 748e6cf32691..d243bf989fda 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -42,14 +42,6 @@ def analysis_CFGAddImplicitDtors : Flag<"-cfg-add-implicit-dtors">, HelpText<"Add C++ implicit destructors to CFGs for all analyses">; def analysis_CFGAddInitializers : Flag<"-cfg-add-initializers">, HelpText<"Add C++ initializers to CFGs for all analyses">; -def analysis_WarnUninitVals : Flag<"-warn-uninit-values">, - HelpText<"Warn about uses of uninitialized variables">; -def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">, - HelpText<"Run the [Core] Foundation reference count checker">; -def analysis_AnalyzerStats : Flag<"-analyzer-stats">, - HelpText<"Emit warnings with analyzer statistics">; -def analysis_WarnBufferOverflows : Flag<"-analyzer-check-buffer-overflows">, - HelpText<"Warn about buffer overflows">; def analyzer_store : Separate<"-analyzer-store">, HelpText<"Source Code Analysis - Abstract Memory Store Models">; @@ -71,8 +63,6 @@ def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-bloc HelpText<"Analyze the definitions of blocks in addition to functions">; def analyzer_display_progress : Flag<"-analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">; -def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">, - HelpText<"Use experimental path-sensitive checks">; def analyze_function : Separate<"-analyze-function">, HelpText<"Run analysis on specific function">; def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>; @@ -120,7 +110,10 @@ def disable_red_zone : Flag<"-disable-red-zone">, HelpText<"Do not emit code that uses the red zone.">; def dwarf_debug_flags : Separate<"-dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; +def fforbid_guard_variables : Flag<"-fforbid-guard-variables">, + HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; def g : Flag<"-g">, HelpText<"Generate source level debug information">; +def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, HelpText<"Don't use the cfi directives">; def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, HelpText<"Generate runtime checks for undefined behavior.">; def flimit_debug_info : Flag<"-flimit-debug-info">, @@ -143,6 +136,10 @@ def fdata_sections : Flag<"-fdata-sections">, HelpText<"Place each data in its own section (ELF Only)">; def funroll_loops : Flag<"-funroll-loops">, HelpText<"Turn on loop unroller">; +def femit_coverage_notes : Flag<"-femit-coverage-notes">, + HelpText<"Emit a gcov coverage notes file when compiling.">; +def femit_coverage_data: Flag<"-femit-coverage-data">, + HelpText<"Instrument the program to emit gcov coverage data when run.">; def relaxed_aliasing : Flag<"-relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; def masm_verbose : Flag<"-masm-verbose">, @@ -163,10 +160,16 @@ def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, HelpText<"Omit frame pointer setup for leaf functions.">; def msoft_float : Flag<"-msoft-float">, HelpText<"Use software floating point">; +def backend_option : Separate<"-backend-option">, + HelpText<"Additional arguments to forward to LLVM backend (during code gen)">; def mregparm : Separate<"-mregparm">, HelpText<"Limit the number of registers available for integer arguments">; def mrelax_all : Flag<"-mrelax-all">, - HelpText<"Relax all machine instructions">; + HelpText<"(integrated-as) Relax all machine instructions">; +def msave_temp_labels : Flag<"-msave-temp-labels">, + HelpText<"(integrated-as) Save temporary labels">; +def mrtd: Flag<"-mrtd">, + HelpText<"Make StdCall calling convention the default">; def mrelocation_model : Separate<"-mrelocation-model">, HelpText<"The relocation model to use">; def munwind_tables : Flag<"-munwind-tables">, @@ -177,6 +180,7 @@ def mms_bitfields : Flag<"-mms-bitfields">, HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard.">; def O : Joined<"-O">, HelpText<"Optimization level">; def Os : Flag<"-Os">, HelpText<"Optimize for size">; +def Oz : Flag<"-Oz">, HelpText<"Optimize for size, regardless of performance">; def pg : Flag<"-pg">, HelpText<"Enable mcount instrumentation">; //===----------------------------------------------------------------------===// @@ -203,6 +207,8 @@ def MP : Flag<"-MP">, def dump_build_information : Separate<"-dump-build-information">, MetaVarName<"<filename>">, HelpText<"output a dump of some build information to a file">; +def diagnostic_log_file : Separate<"-diagnostic-log-file">, + HelpText<"Filename (or -) to log diagnostics to">; def fno_show_column : Flag<"-fno-show-column">, HelpText<"Do not include column number on diagnostics">; def fno_show_source_location : Flag<"-fno-show-source-location">, @@ -214,6 +220,9 @@ def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, HelpText<"Do not include source line and caret with diagnostics">; def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, HelpText<"Do not include fixit information in diagnostics">; +def fno_diagnostics_show_note_include_stack : + Flag<"-fno-diagnostics-show-note-include-stack">, + HelpText<"Display include stacks for diagnostic notes">; def w : Flag<"-w">, HelpText<"Suppress all warnings">; def pedantic : Flag<"-pedantic">; def pedantic_errors : Flag<"-pedantic-errors">; @@ -227,11 +236,15 @@ def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-rang HelpText<"Print source range spans in numeric form">; def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, HelpText<"Print fix-its in machine parseable form">; +def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, + HelpText<"Print diagnostic name">; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, - HelpText<"Print diagnostic name with mappable diagnostics">; + HelpText<"Print option name with mappable diagnostics">; def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">, HelpText<"Print diagnostic category">; - +def fdiagnostics_show_note_include_stack : + Flag<"-fdiagnostics-show-note-include-stack">, + HelpText<"Display include stacks for diagnostic notes">; def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">, HelpText<"Set the tab stop distance.">; def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">, @@ -246,8 +259,6 @@ def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, HelpText<"Use colors in diagnostics">; def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">, HelpText<"Silence ObjC rewriting warnings">; -def Wwrite_strings : Flag<"-Wwrite-strings">, - HelpText<"Remove const qualifier from string literals">; def verify : Flag<"-verify">, HelpText<"Verify emitted diagnostics and warnings">; @@ -326,8 +337,6 @@ def emit_html : Flag<"-emit-html">, HelpText<"Output input source as HTML">; def ast_print : Flag<"-ast-print">, HelpText<"Build ASTs and then pretty-print them">; -def ast_print_xml : Flag<"-ast-print-xml">, - HelpText<"Build ASTs and then print them in XML format">; def ast_dump : Flag<"-ast-dump">, HelpText<"Build ASTs and then debug dump them">; def ast_dump_xml : Flag<"-ast-dump-xml">, @@ -517,8 +526,25 @@ def trigraphs : Flag<"-trigraphs">, HelpText<"Process trigraph sequences">; def fwritable_strings : Flag<"-fwritable-strings">, HelpText<"Store string literals as writable data">; +def fconst_strings : Flag<"-fconst-strings">, + HelpText<"Use a const qualified type for string literals in C and ObjC">; +def fno_const_strings : Flag<"-fno-const-strings">, + HelpText<"Don't use a const qualified type for string literals in C and ObjC">; def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">, HelpText<"Ignore bit-field types when aligning structures">; +def traditional_cpp : Flag<"-traditional-cpp">, + HelpText<"Enable some traditional CPP emulation">; +def ffake_address_space_map : Flag<"-ffake-address-space-map">, + HelpText<"Use a fake address space map; OpenCL testing purposes only">; +def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, + HelpText<"Parse templated function definitions at the end of the " + "translation unit ">; +def funknown_anytype : Flag<"-funknown-anytype">, + HelpText<"Enable parser support for the __unknown_anytype type; for testing purposes only">; +def fdeprecated_macro : Flag<"-fdeprecated-macro">, + HelpText<"Defines the __DEPRECATED macro">; +def fno_deprecated_macro : Flag<"-fno-deprecated-macro">, + HelpText<"Undefines the __DEPRECATED macro">; //===----------------------------------------------------------------------===// // Header Search Options @@ -570,6 +596,8 @@ def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">, HelpText<"Include precompiled header file">; def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">, HelpText<"Include file before parsing">; +def chain_include : Separate<"-chain-include">, MetaVarName<"<file>">, + HelpText<"Include and chain a header file after turning it into PCH">; def preamble_bytes_EQ : Joined<"-preamble-bytes=">, HelpText<"Assume that the precompiled header is a precompiled preamble " "covering the first N bytes of the main file">; diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 03fa0ef972d0..5a7d830b069d 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -25,6 +25,7 @@ namespace llvm { class raw_ostream; + template<typename T> class ArrayRef; } namespace clang { namespace driver { @@ -77,6 +78,12 @@ public: typedef llvm::SmallVector<std::string, 4> prefix_list; prefix_list PrefixDirs; + /// sysroot, if present + std::string SysRoot; + + /// If the standard library is used + bool UseStdLib; + /// Default host triple. std::string DefaultHostTriple; @@ -90,7 +97,7 @@ public: /// will generally be the actual host platform, but not always. const HostInfo *Host; - /// Information about the host which can be overriden by the user. + /// Information about the host which can be overridden by the user. std::string HostBits, HostMachine, HostSystem, HostRelease; /// The file to log CC_PRINT_OPTIONS output to, if enabled. @@ -99,9 +106,15 @@ public: /// The file to log CC_PRINT_HEADERS output to, if enabled. const char *CCPrintHeadersFilename; + /// The file to log CC_LOG_DIAGNOSTICS output to, if enabled. + const char *CCLogDiagnosticsFilename; + /// Whether the driver should follow g++ like behavior. unsigned CCCIsCXX : 1; + /// Whether the driver is just the preprocessor + unsigned CCCIsCPP : 1; + /// Echo commands while executing (in -v style). unsigned CCCEcho : 1; @@ -116,8 +129,13 @@ public: /// information to CCPrintHeadersFilename or to stderr. unsigned CCPrintHeaders : 1; + /// Set CC_LOG_DIAGNOSTICS mode, which causes the frontend to log diagnostics + /// to CCLogDiagnosticsFilename or to stderr, in a stable machine readable + /// format. + unsigned CCLogDiagnostics : 1; + private: - /// Name to use when calling the generic gcc. + /// Name to use when invoking gcc/g++. std::string CCCGenericGCCName; /// Whether to check that input files exist when constructing compilation @@ -165,7 +183,7 @@ public: /// @name Accessors /// @{ - /// Name to use when calling the generic gcc. + /// Name to use when invoking gcc/g++. const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; } @@ -206,14 +224,14 @@ public: /// argument vector. A null return value does not necessarily /// indicate an error condition, the diagnostics should be queried /// to determine if an error occurred. - Compilation *BuildCompilation(int argc, const char **argv); + Compilation *BuildCompilation(llvm::ArrayRef<const char *> Args); /// @name Driver Steps /// @{ /// ParseArgStrings - Parse the given list of strings into an /// ArgList. - InputArgList *ParseArgStrings(const char **ArgBegin, const char **ArgEnd); + InputArgList *ParseArgStrings(llvm::ArrayRef<const char *> Args); /// BuildActions - Construct the list of actions to perform for the /// given arguments, which are only done for a single architecture. @@ -221,7 +239,7 @@ public: /// \param TC - The default host tool chain. /// \param Args - The input arguments. /// \param Actions - The list to store the resulting actions onto. - void BuildActions(const ToolChain &TC, const ArgList &Args, + void BuildActions(const ToolChain &TC, const DerivedArgList &Args, ActionList &Actions) const; /// BuildUniversalActions - Construct the list of actions to perform @@ -230,7 +248,7 @@ public: /// \param TC - The default host tool chain. /// \param Args - The input arguments. /// \param Actions - The list to store the resulting actions onto. - void BuildUniversalActions(const ToolChain &TC, const ArgList &Args, + void BuildUniversalActions(const ToolChain &TC, const DerivedArgList &Args, ActionList &Actions) const; /// BuildJobs - Bind actions to concrete tools and translate diff --git a/include/clang/Driver/DriverDiagnostic.h b/include/clang/Driver/DriverDiagnostic.h index 0733c51027d9..0f9376b8dea1 100644 --- a/include/clang/Driver/DriverDiagnostic.h +++ b/include/clang/Driver/DriverDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define DRIVERSTART #include "clang/Basic/DiagnosticDriverKinds.inc" #undef DIAG diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td index 04efd00fb1d8..25ecbc35f92e 100644 --- a/include/clang/Driver/OptParser.td +++ b/include/clang/Driver/OptParser.td @@ -78,7 +78,7 @@ def RenderSeparate : OptionFlag; def Unsupported : OptionFlag; // HelpHidden - The option should not be displayed in --help, even if it has -// help text. Clients *can* use this in conjuction with the OptTable::PrintHelp +// help text. Clients *can* use this in conjunction with the OptTable::PrintHelp // arguments to implement hidden help groups. def HelpHidden : OptionFlag; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 288c10f52354..38f0c57af73e 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -29,6 +29,7 @@ def X_Group : OptionGroup<"<X group>">; def a_Group : OptionGroup<"<a group>">; def d_Group : OptionGroup<"<d group>">; def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>; +def f_clang_Group : OptionGroup<"<f (clang-only) group>">, Group<CompileOnly_Group>; def g_Group : OptionGroup<"<g group>">; def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>; def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>; @@ -165,6 +166,8 @@ def Wa_COMMA : CommaJoined<"-Wa,">, HelpText<"Pass the comma separated arguments in <arg> to the assembler">, MetaVarName<"<arg>">; def Wall : Flag<"-Wall">, Group<W_Group>; +def Wdeprecated : Flag<"-Wdeprecated">, Group<W_Group>; +def Wno_deprecated : Flag<"-Wno-deprecated">, Group<W_Group>; def Wextra : Flag<"-Wextra">, Group<W_Group>; def Wl_COMMA : CommaJoined<"-Wl,">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass the comma separated arguments in <arg> to the linker">, @@ -174,6 +177,8 @@ def Wnonportable_cfstrings : Joined<"-Wnonportable-cfstrings">, Group<W_Group>; def Wp_COMMA : CommaJoined<"-Wp,">, HelpText<"Pass the comma separated arguments in <arg> to the preprocessor">, MetaVarName<"<arg>">; +def Wwrite_strings : Flag<"-Wwrite-strings">, Group<W_Group>; +def Wno_write_strings : Flag<"-Wno-write-strings">, Group<W_Group>; def W_Joined : Joined<"-W">, Group<W_Group>; def Xanalyzer : Separate<"-Xanalyzer">, HelpText<"Pass <arg> to the static analyzer">, MetaVarName<"<arg>">; @@ -264,18 +269,24 @@ def fcompile_resource_EQ : Joined<"-fcompile-resource=">, Group<f_Group>; def fconstant_cfstrings : Flag<"-fconstant-cfstrings">, Group<f_Group>; def fconstant_string_class_EQ : Joined<"-fconstant-string-class=">, Group<f_Group>; def fcreate_profile : Flag<"-fcreate-profile">, Group<f_Group>; +def fcxx_exceptions: Flag<"-fcxx-exceptions">, Group<f_Group>; def fdebug_pass_arguments : Flag<"-fdebug-pass-arguments">, Group<f_Group>; def fdebug_pass_structure : Flag<"-fdebug-pass-structure">, Group<f_Group>; -def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_Group>; -def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_Group>; -def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_Group>; +def fdiagnostics_fixit_info : Flag<"-fdiagnostics-fixit-info">, Group<f_clang_Group>; +def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">, Group<f_clang_Group>; +def fdiagnostics_parseable_fixits : Flag<"-fdiagnostics-parseable-fixits">, Group<f_clang_Group>; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, Group<f_Group>; -def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_Group>; +def fdiagnostics_show_name : Flag<"-fdiagnostics-show-name">, Group<f_Group>; +def fdiagnostics_show_note_include_stack : Flag<"-fdiagnostics-show-note-include-stack">, Group<f_Group>; +def fdiagnostics_show_category_EQ : Joined<"-fdiagnostics-show-category=">, Group<f_clang_Group>; def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">, Group<f_Group>; +def fdwarf2_cfi_asm : Flag<"-fdwarf2-cfi-asm">, Group<f_Group>; +def fno_dwarf2_cfi_asm : Flag<"-fno-dwarf2-cfi-asm">, Group<f_Group>; def felide_constructors : Flag<"-felide-constructors">, Group<f_Group>; def feliminate_unused_debug_symbols : Flag<"-feliminate-unused-debug-symbols">, Group<f_Group>; def femit_all_decls : Flag<"-femit-all-decls">, Group<f_Group>; def fencoding_EQ : Joined<"-fencoding=">, Group<f_Group>; +def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>; def fexceptions : Flag<"-fexceptions">, Group<f_Group>; def fextdirs_EQ : Joined<"-fextdirs=">, Group<f_Group>; def fhosted : Flag<"-fhosted">, Group<f_Group>; @@ -301,6 +312,7 @@ def flimit_debug_info : Flag<"-flimit-debug-info">, Group<f_Group>, HelpText<"Limit debug information produced to reduce size of debug binary">; def flimited_precision_EQ : Joined<"-flimited-precision=">, Group<f_Group>; def flto : Flag<"-flto">, Group<f_Group>; +def fno_lto : Flag<"-fno-lto">, Group<f_Group>; def fmacro_backtrace_limit_EQ : Joined<"-fmacro-backtrace-limit=">, Group<f_Group>; def fmath_errno : Flag<"-fmath-errno">, Group<f_Group>; @@ -308,6 +320,7 @@ def fmerge_all_constants : Flag<"-fmerge-all-constants">, Group<f_Group>; def fmessage_length_EQ : Joined<"-fmessage-length=">, Group<f_Group>; def fms_extensions : Flag<"-fms-extensions">, Group<f_Group>; def fmsc_version : Joined<"-fmsc-version=">, Group<f_Group>; +def fdelayed_template_parsing : Flag<"-fdelayed-template-parsing">, Group<f_Group>; def fmudflapth : Flag<"-fmudflapth">, Group<f_Group>; def fmudflap : Flag<"-fmudflap">, Group<f_Group>; def fnested_functions : Flag<"-fnested-functions">, Group<f_Group>; @@ -325,8 +338,11 @@ def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">, Group<f_Group>; def fno_color_diagnostics : Flag<"-fno-color-diagnostics">, Group<f_Group>; def fno_common : Flag<"-fno-common">, Group<f_Group>; def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">, Group<f_Group>; +def fno_cxx_exceptions: Flag<"-fno-cxx-exceptions">, Group<f_Group>; def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">, Group<f_Group>; +def fno_diagnostics_show_name : Flag<"-fno-diagnostics-show-name">, Group<f_Group>; def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_Group>; +def fno_diagnostics_show_note_include_stack : Flag<"-fno-diagnostics-show-note-include-stack">, Group<f_Group>; def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>; def fno_elide_constructors : Flag<"-fno-elide-constructors">, Group<f_Group>; def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>; @@ -340,6 +356,7 @@ def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">, Group<f_Gr def fno_math_errno : Flag<"-fno-math-errno">, Group<f_Group>; def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, Group<f_Group>; def fno_ms_extensions : Flag<"-fno-ms-extensions">, Group<f_Group>; +def fno_delayed_template_parsing : Flag<"-fno-delayed-template-parsing">, Group<f_Group>; def fno_objc_default_synthesize_properties : Flag<"-fno-objc-default-synthesize-properties">, Group<f_Group>; def fno_objc_exceptions: Flag<"-fno-objc-exceptions">, Group<f_Group>; @@ -353,12 +370,14 @@ def fno_show_source_location : Flag<"-fno-show-source-location">, Group<f_Group> def fno_spell_checking : Flag<"-fno-spell-checking">, Group<f_Group>; def fno_stack_protector : Flag<"-fno-stack-protector">, Group<f_Group>; def fno_strict_aliasing : Flag<"-fno-strict-aliasing">, Group<f_Group>; +def fno_strict_overflow : Flag<"-fno-strict-overflow">, Group<f_Group>; def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>; def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, Group<f_Group>; def fno_unit_at_a_time : Flag<"-fno-unit-at-a-time">, Group<f_Group>; def fno_unwind_tables : Flag<"-fno-unwind-tables">, Group<f_Group>; def fno_verbose_asm : Flag<"-fno-verbose-asm">, Group<f_Group>; def fno_working_directory : Flag<"-fno-working-directory">, Group<f_Group>; +def fno_wrapv : Flag<"-fno-wrapv">, Group<f_Group>; def fno_zero_initialized_in_bss : Flag<"-fno-zero-initialized-in-bss">, Group<f_Group>; def fobjc_atdefs : Flag<"-fobjc-atdefs">, Group<clang_ignored_f_Group>; def fobjc_call_cxx_cdtors : Flag<"-fobjc-call-cxx-cdtors">, Group<clang_ignored_f_Group>; @@ -406,19 +425,30 @@ def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>; def fstack_protector_all : Flag<"-fstack-protector-all">, Group<f_Group>; def fstack_protector : Flag<"-fstack-protector">, Group<f_Group>; def fstrict_aliasing : Flag<"-fstrict-aliasing">, Group<f_Group>; +def fstrict_overflow : Flag<"-fstrict-overflow">, Group<f_Group>; def fsyntax_only : Flag<"-fsyntax-only">, Flags<[DriverOption]>; def ftabstop_EQ : Joined<"-ftabstop=">, Group<f_Group>; -def ferror_limit_EQ : Joined<"-ferror-limit=">, Group<f_Group>; def ftemplate_depth_ : Joined<"-ftemplate-depth-">, Group<f_Group>; def ftemplate_backtrace_limit_EQ : Joined<"-ftemplate-backtrace-limit=">, Group<f_Group>; +def ftest_coverage : Flag<"-ftest-coverage">, Group<f_Group>; def Wlarge_by_value_copy_def : Flag<"-Wlarge-by-value-copy">; def Wlarge_by_value_copy_EQ : Joined<"-Wlarge-by-value-copy=">; + +// Just silence warnings about -Wlarger-than, -Wframe-larger-than for now. +def Wlarger_than : Separate<"-Wlarger-than">, Group<clang_ignored_f_Group>; +def Wlarger_than_EQ : Joined<"-Wlarger-than=">, Alias<Wlarger_than>; +def Wlarger_than_ : Joined<"-Wlarger-than-">, Alias<Wlarger_than>; +def Wframe_larger_than : Separate<"-Wframe-larger-than">, Group<clang_ignored_f_Group>; +def Wframe_larger_than_EQ : Joined<"-Wframe-larger-than=">, Alias<Wframe_larger_than>; + def fterminated_vtables : Flag<"-fterminated-vtables">, Group<f_Group>; def fthreadsafe_statics : Flag<"-fthreadsafe-statics">, Group<f_Group>; def ftime_report : Flag<"-ftime-report">, Group<f_Group>; def ftrapv : Flag<"-ftrapv">, Group<f_Group>; def ftrapv_handler_EQ : Joined<"-ftrapv-handler=">, Group<f_Group>; +def ftrap_function_EQ : Joined<"-ftrap-function=">, Group<f_Group>, + HelpText<"Issue call to specified function rather than a trap instruction">; def funit_at_a_time : Flag<"-funit-at-a-time">, Group<f_Group>; def funroll_loops : Flag<"-funroll-loops">, Group<f_Group>; def funsigned_bitfields : Flag<"-funsigned-bitfields">, Group<f_Group>; @@ -465,11 +495,11 @@ def m32 : Flag<"-m32">, Group<m_Group>, Flags<[DriverOption]>; def m3dnowa : Flag<"-m3dnowa">, Group<m_x86_Features_Group>; def m3dnow : Flag<"-m3dnow">, Group<m_x86_Features_Group>; def m64 : Flag<"-m64">, Group<m_Group>, Flags<[DriverOption]>; -def mabi_EQ : Joined<"-mabi=">, Group<m_Group>, Flags<[DriverOption]>; -def march_EQ : Joined<"-march=">, Group<m_Group>, Flags<[DriverOption]>; -def mcmodel_EQ : Joined<"-mcmodel=">, Group<m_Group>, Flags<[DriverOption]>; +def mabi_EQ : Joined<"-mabi=">, Group<m_Group>; +def march_EQ : Joined<"-march=">, Group<m_Group>; +def mcmodel_EQ : Joined<"-mcmodel=">, Group<m_Group>; def mconstant_cfstrings : Flag<"-mconstant-cfstrings">, Group<clang_ignored_m_Group>; -def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>, Flags<[DriverOption]>; +def mcpu_EQ : Joined<"-mcpu=">, Group<m_Group>; def mdynamic_no_pic : Joined<"-mdynamic-no-pic">, Group<m_Group>, Flags<[NoArgumentUnused]>; def mfix_and_continue : Flag<"-mfix-and-continue">, Group<clang_ignored_m_Group>; def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>; @@ -477,6 +507,7 @@ def mfpu_EQ : Joined<"-mfpu=">, Group<m_Group>; def mhard_float : Flag<"-mhard-float">, Group<m_Group>; def miphoneos_version_min_EQ : Joined<"-miphoneos-version-min=">, Group<m_Group>; def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias<miphoneos_version_min_EQ>; +def mios_simulator_version_min_EQ : Joined<"-mios-simulator-version-min=">, Group<m_Group>; def mkernel : Flag<"-mkernel">, Group<m_Group>; def mlinker_version_EQ : Joined<"-mlinker-version=">, Flags<[NoForward]>; def mllvm : Separate<"-mllvm">; @@ -490,6 +521,7 @@ def mno_mmx : Flag<"-mno-mmx">, Group<m_x86_Features_Group>; def mno_pascal_strings : Flag<"-mno-pascal-strings">, Group<m_Group>; def mno_red_zone : Flag<"-mno-red-zone">, Group<m_Group>; def mno_relax_all : Flag<"-mno-relax-all">, Group<m_Group>; +def mno_rtd: Flag<"-mno-rtd">, Group<m_Group>; def mno_soft_float : Flag<"-mno-soft-float">, Group<m_Group>; def mno_sse2 : Flag<"-mno-sse2">, Group<m_x86_Features_Group>; def mno_sse3 : Flag<"-mno-sse3">, Group<m_x86_Features_Group>; @@ -512,6 +544,7 @@ def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>; def mred_zone : Flag<"-mred-zone">, Group<m_Group>; def mregparm_EQ : Joined<"-mregparm=">, Group<m_Group>; def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>; +def mrtd: Flag<"-mrtd">, Group<m_Group>; def msoft_float : Flag<"-msoft-float">, Group<m_Group>; def msse2 : Flag<"-msse2">, Group<m_x86_Features_Group>; def msse3 : Flag<"-msse3">, Group<m_x86_Features_Group>; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index f0012bd851eb..da6949f9786e 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -88,8 +88,10 @@ public: return 0; } - /// SelectTool - Choose a tool to use to handle the action \arg JA. - virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const = 0; + /// SelectTool - Choose a tool to use to handle the action \arg JA with the + /// given \arg Inputs. + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const = 0; // Helper methods @@ -151,6 +153,9 @@ public: /// particular PIC mode. virtual const char *GetForcedPicModel() const = 0; + /// SupportsProfiling - Does this tool chain support -pg. + virtual bool SupportsProfiling() const { return true; } + /// Does this tool chain support Objective-C garbage collection. virtual bool SupportsObjCGC() const { return false; } diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index c45bd4070600..3c05834ad6a7 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -14,8 +14,6 @@ #ifndef DRIVER_ASTCONSUMERS_H #define DRIVER_ASTCONSUMERS_H -#include <string> - namespace llvm { class raw_ostream; namespace sys { class Path; } @@ -36,12 +34,6 @@ class TargetOptions; // implementation is still incomplete. ASTConsumer *CreateASTPrinter(llvm::raw_ostream *OS); -// AST XML-printer: prints out the AST in a XML format -// The output is intended to be in a format such that -// clang or any other tool could re-parse the output back into the same AST, -// but the implementation is still incomplete. -ASTConsumer *CreateASTPrinterXML(llvm::raw_ostream *OS); - // AST dumper: dumps the raw AST in human-readable form to stderr; this is // intended for debugging. ASTConsumer *CreateASTDumper(); diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index e93563311b85..57c59d951e94 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -71,12 +71,12 @@ public: private: llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; - llvm::OwningPtr<FileManager> FileMgr; - llvm::OwningPtr<SourceManager> SourceMgr; + llvm::IntrusiveRefCntPtr<FileManager> FileMgr; + llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr; llvm::OwningPtr<HeaderSearch> HeaderInfo; - llvm::OwningPtr<TargetInfo> Target; - llvm::OwningPtr<Preprocessor> PP; - llvm::OwningPtr<ASTContext> Ctx; + llvm::IntrusiveRefCntPtr<TargetInfo> Target; + llvm::IntrusiveRefCntPtr<Preprocessor> PP; + llvm::IntrusiveRefCntPtr<ASTContext> Ctx; FileSystemOptions FileSystemOpts; @@ -90,7 +90,7 @@ private: /// Optional owned invocation, just used to make the invocation used in /// LoadFromCommandLine available. - llvm::OwningPtr<CompilerInvocation> Invocation; + llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation; /// \brief The set of target features. /// @@ -115,6 +115,9 @@ private: /// \brief Whether we should time each operation. bool WantTiming; + + /// \brief Whether the ASTUnit should delete the remapped buffers. + bool OwnsRemappedFileBuffers; /// Track the top-level decls which appeared in an ASTUnit which was loaded /// from a source file. @@ -393,11 +396,11 @@ public: const SourceManager &getSourceManager() const { return *SourceMgr; } SourceManager &getSourceManager() { return *SourceMgr; } - const Preprocessor &getPreprocessor() const { return *PP.get(); } - Preprocessor &getPreprocessor() { return *PP.get(); } + const Preprocessor &getPreprocessor() const { return *PP; } + Preprocessor &getPreprocessor() { return *PP; } - const ASTContext &getASTContext() const { return *Ctx.get(); } - ASTContext &getASTContext() { return *Ctx.get(); } + const ASTContext &getASTContext() const { return *Ctx; } + ASTContext &getASTContext() { return *Ctx; } bool hasSema() const { return TheSema; } Sema &getSema() const { @@ -422,6 +425,9 @@ public: bool getOnlyLocalDecls() const { return OnlyLocalDecls; } + bool getOwnsRemappedFileBuffers() const { return OwnsRemappedFileBuffers; } + void setOwnsRemappedFileBuffers(bool val) { OwnsRemappedFileBuffers = val; } + /// \brief Retrieve the maximum PCH level of declarations that a /// traversal of the translation unit should consider. unsigned getMaxPCHLevel() const; @@ -529,10 +535,16 @@ public: /// that might still be used as a precompiled header or preamble. bool isCompleteTranslationUnit() const { return CompleteTranslationUnit; } + typedef llvm::PointerUnion<const char *, const llvm::MemoryBuffer *> + FilenameOrMemBuf; /// \brief A mapping from a file name to the memory buffer that stores the /// remapped contents of that file. - typedef std::pair<std::string, const llvm::MemoryBuffer *> RemappedFile; - + typedef std::pair<std::string, FilenameOrMemBuf> RemappedFile; + + /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. + static ASTUnit *create(CompilerInvocation *CI, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags); + /// \brief Create a ASTUnit from an AST file. /// /// \param Filename - The AST file to load. @@ -603,6 +615,7 @@ public: bool CaptureDiagnostics = false, RemappedFile *RemappedFiles = 0, unsigned NumRemappedFiles = 0, + bool RemappedFilesKeepOriginalName = true, bool PrecompilePreamble = false, bool CompleteTranslationUnit = true, bool CacheCodeCompletionResults = false, @@ -647,6 +660,11 @@ public: /// /// \returns True if an error occurred, false otherwise. bool Save(llvm::StringRef File); + + /// \brief Serialize this translation unit with the given output stream. + /// + /// \returns True if an error occurred, false otherwise. + bool serialize(llvm::raw_ostream &OS); }; } // namespace clang diff --git a/include/clang/Frontend/Analyses.def b/include/clang/Frontend/Analyses.def index 75b52a824c63..f055549b4e24 100644 --- a/include/clang/Frontend/Analyses.def +++ b/include/clang/Frontend/Analyses.def @@ -11,16 +11,6 @@ // //===----------------------------------------------------------------------===// -#ifndef ANALYSIS -#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) -#endif - -ANALYSIS(WarnUninitVals, "warn-uninit-values", - "Warn about uses of uninitialized variables", Code) - -ANALYSIS(ObjCMemChecker, "analyzer-check-objc-mem", - "Run the [Core] Foundation reference count checker", Code) - #ifndef ANALYSIS_STORE #define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) #endif @@ -45,7 +35,6 @@ ANALYSIS_DIAGNOSTICS(PLIST, "plist", "Output analysis results using Plists", cre ANALYSIS_DIAGNOSTICS(PLIST_HTML, "plist-html", "Output analysis results using HTML wrapped with Plists", createPlistHTMLDiagnosticClient, true) ANALYSIS_DIAGNOSTICS(TEXT, "text", "Text output of analysis results", createTextPathDiagnosticClient, true) -#undef ANALYSIS #undef ANALYSIS_STORE #undef ANALYSIS_CONSTRAINTS #undef ANALYSIS_DIAGNOSTICS diff --git a/include/clang/Frontend/AnalyzerOptions.h b/include/clang/Frontend/AnalyzerOptions.h index 64263c1b54e8..ea9f5e38b7b9 100644 --- a/include/clang/Frontend/AnalyzerOptions.h +++ b/include/clang/Frontend/AnalyzerOptions.h @@ -55,7 +55,6 @@ NUM_ANALYSIS_DIAG_CLIENTS class AnalyzerOptions { public: - std::vector<Analyses> AnalysisList; /// \brief Pair of checker name and enable/disable. std::vector<std::pair<std::string, bool> > CheckersControlList; AnalysisStores AnalysisStoreOpt; @@ -68,14 +67,11 @@ public: unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; - unsigned AnalyzerStats : 1; unsigned EagerlyAssume : 1; - unsigned BufferOverflows : 1; unsigned PurgeDead : 1; unsigned TrimGraph : 1; unsigned VisualizeEGDot : 1; unsigned VisualizeEGUbi : 1; - unsigned EnableExperimentalChecks : 1; unsigned InlineCall : 1; unsigned UnoptimizedCFG : 1; unsigned CFGAddImplicitDtors : 1; @@ -91,14 +87,11 @@ public: AnalyzeAll = 0; AnalyzerDisplayProgress = 0; AnalyzeNestedBlocks = 0; - AnalyzerStats = 0; EagerlyAssume = 0; - BufferOverflows = 0; PurgeDead = 1; TrimGraph = 0; VisualizeEGDot = 0; VisualizeEGUbi = 0; - EnableExperimentalChecks = 0; InlineCall = 0; UnoptimizedCFG = 0; CFGAddImplicitDtors = 0; diff --git a/include/clang/Frontend/ChainedDiagnosticClient.h b/include/clang/Frontend/ChainedDiagnosticClient.h index 2d5e128dac37..70f21901db4f 100644 --- a/include/clang/Frontend/ChainedDiagnosticClient.h +++ b/include/clang/Frontend/ChainedDiagnosticClient.h @@ -48,6 +48,9 @@ public: virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, const DiagnosticInfo &Info) { + // Default implementation (Warnings/errors count). + DiagnosticClient::HandleDiagnostic(DiagLevel, Info); + Primary->HandleDiagnostic(DiagLevel, Info); Secondary->HandleDiagnostic(DiagLevel, Info); } diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index ee85b655c23f..8bef6a3e0d43 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H #include <string> +#include <vector> namespace clang { @@ -51,6 +52,10 @@ public: /// Decl* various IR entities came from. Only /// useful when running CodeGen as a /// subroutine. + unsigned EmitGcovArcs : 1; /// Emit coverage data files, aka. GCDA. + unsigned EmitGcovNotes : 1; /// Emit coverage "notes" files, aka GCNO. + unsigned ForbidGuardVariables : 1; /// Issue errors if C++ guard variables + /// are required unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled unsigned HiddenWeakTemplateVTables : 1; /// Emit weak vtables and RTTI for /// template classes with hidden visibility @@ -63,6 +68,7 @@ public: /// generated. unsigned MergeAllConstants : 1; /// Merge identical constants. unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. + unsigned NoDwarf2CFIAsm : 1; /// Set when -fno-dwarf2-cfi-asm is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. unsigned NoInfsFPMath : 1; /// Assume FP arguments, results not +-Inf. unsigned NoNaNsFPMath : 1; /// Assume FP arguments, results not NaN. @@ -71,9 +77,10 @@ public: unsigned OmitLeafFramePointer : 1; /// Set when -momit-leaf-frame-pointer is /// enabled. unsigned OptimizationLevel : 3; /// The -O[0-4] option specified. - unsigned OptimizeSize : 1; /// If -Os is specified. + unsigned OptimizeSize : 2; /// If -Os (==1) or -Oz (==2) is specified. unsigned RelaxAll : 1; /// Relax all machine code instructions. unsigned RelaxedAliasing : 1; /// Set when -fno-strict-aliasing is enabled. + unsigned SaveTempLabels : 1; /// Save temporary labels. unsigned SimplifyLibCalls : 1; /// Set when -fbuiltin is enabled. unsigned SoftFloat : 1; /// -soft-float. unsigned TimePasses : 1; /// Set when -ftime-report is enabled. @@ -112,6 +119,9 @@ public: /// The name of the relocation model to use. std::string RelocationModel; + /// A list of command-line options to forward to the LLVM backend. + std::vector<std::string> BackendOptions; + /// The user specified number of registers to be used for integral arguments, /// or 0 if unspecified. unsigned NumRegisterParameters; @@ -128,6 +138,9 @@ public: DisableLLVMOpts = 0; DisableRedZone = 0; EmitDeclMetadata = 0; + EmitGcovArcs = 0; + EmitGcovNotes = 0; + ForbidGuardVariables = 0; FunctionSections = 0; HiddenWeakTemplateVTables = 0; HiddenWeakVTables = 0; @@ -136,6 +149,7 @@ public: LessPreciseFPMAD = 0; MergeAllConstants = 1; NoCommon = 0; + NoDwarf2CFIAsm = 0; NoImplicitFloat = 0; NoInfsFPMath = 0; NoNaNsFPMath = 0; @@ -147,6 +161,7 @@ public: OptimizeSize = 0; RelaxAll = 0; RelaxedAliasing = 0; + SaveTempLabels = 0; SimplifyLibCalls = 1; SoftFloat = 0; TimePasses = 0; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 7ea79e5599ff..004c8896e232 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -59,25 +59,25 @@ class TargetInfo; /// and a long form that takes explicit instances of any required objects. class CompilerInstance { /// The options used in this compiler instance. - llvm::OwningPtr<CompilerInvocation> Invocation; + llvm::IntrusiveRefCntPtr<CompilerInvocation> Invocation; /// The diagnostics engine instance. llvm::IntrusiveRefCntPtr<Diagnostic> Diagnostics; /// The target being compiled for. - llvm::OwningPtr<TargetInfo> Target; + llvm::IntrusiveRefCntPtr<TargetInfo> Target; /// The file manager. - llvm::OwningPtr<FileManager> FileMgr; + llvm::IntrusiveRefCntPtr<FileManager> FileMgr; /// The source manager. - llvm::OwningPtr<SourceManager> SourceMgr; + llvm::IntrusiveRefCntPtr<SourceManager> SourceMgr; /// The preprocessor. - llvm::OwningPtr<Preprocessor> PP; + llvm::IntrusiveRefCntPtr<Preprocessor> PP; /// The AST context. - llvm::OwningPtr<ASTContext> Context; + llvm::IntrusiveRefCntPtr<ASTContext> Context; /// The AST consumer. llvm::OwningPtr<ASTConsumer> Consumer; @@ -161,10 +161,7 @@ public: return *Invocation; } - CompilerInvocation *takeInvocation() { return Invocation.take(); } - - /// setInvocation - Replace the current invocation; the compiler instance - /// takes ownership of \arg Value. + /// setInvocation - Replace the current invocation. void setInvocation(CompilerInvocation *Value); /// } @@ -251,13 +248,13 @@ public: bool hasDiagnostics() const { return Diagnostics != 0; } + /// Get the current diagnostics engine. Diagnostic &getDiagnostics() const { assert(Diagnostics && "Compiler instance has no diagnostics!"); return *Diagnostics; } - /// setDiagnostics - Replace the current diagnostics engine; the compiler - /// instance takes ownership of \arg Value. + /// setDiagnostics - Replace the current diagnostics engine. void setDiagnostics(Diagnostic *Value); DiagnosticClient &getDiagnosticClient() const { @@ -277,12 +274,7 @@ public: 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. + /// Replace the current diagnostics engine. void setTarget(TargetInfo *Value); /// } @@ -291,17 +283,17 @@ public: bool hasFileManager() const { return FileMgr != 0; } + /// Return the current file manager to the caller. FileManager &getFileManager() const { assert(FileMgr && "Compiler instance has no file manager!"); return *FileMgr; } + + void resetAndLeakFileManager() { + FileMgr.resetWithoutRelease(); + } - /// 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. + /// setFileManager - Replace the current file manager. void setFileManager(FileManager *Value); /// } @@ -310,17 +302,17 @@ public: bool hasSourceManager() const { return SourceMgr != 0; } + /// Return the current source manager. SourceManager &getSourceManager() const { assert(SourceMgr && "Compiler instance has no source manager!"); return *SourceMgr; } + + void resetAndLeakSourceManager() { + SourceMgr.resetWithoutRelease(); + } - /// 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. + /// setSourceManager - Replace the current source manager. void setSourceManager(SourceManager *Value); /// } @@ -329,17 +321,17 @@ public: bool hasPreprocessor() const { return PP != 0; } + /// Return the current preprocessor. 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(); } + void resetAndLeakPreprocessor() { + PP.resetWithoutRelease(); + } - /// setPreprocessor - Replace the current preprocessor; the compiler instance - /// takes ownership of \arg Value. + /// Replace the current preprocessor. void setPreprocessor(Preprocessor *Value); /// } @@ -352,13 +344,12 @@ public: assert(Context && "Compiler instance has no AST context!"); return *Context; } + + void resetAndLeakASTContext() { + Context.resetWithoutRelease(); + } - /// 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. + /// setASTContext - Replace the current AST context. void setASTContext(ASTContext *Value); /// \brief Replace the current Sema; the compiler instance takes ownership @@ -479,11 +470,15 @@ public: /// attached to (and, then, owned by) the returned Diagnostic /// object. /// + /// \param CodeGenOpts If non-NULL, the code gen options in use, which may be + /// used by some diagnostics printers (for logging purposes only). + /// /// \return The new object on success, or null on failure. static llvm::IntrusiveRefCntPtr<Diagnostic> createDiagnostics(const DiagnosticOptions &Opts, int Argc, const char* const *Argv, - DiagnosticClient *Client = 0); + DiagnosticClient *Client = 0, + const CodeGenOptions *CodeGenOpts = 0); /// Create the file manager and replace any existing one with it. void createFileManager(); diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index e0329dbc96ec..e18f3fe63249 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -22,6 +22,7 @@ #include "clang/Frontend/LangStandard.h" #include "clang/Frontend/PreprocessorOptions.h" #include "clang/Frontend/PreprocessorOutputOptions.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringMap.h" #include <string> @@ -41,7 +42,7 @@ class Diagnostic; /// 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 { +class CompilerInvocation : public llvm::RefCountedBase<CompilerInvocation> { /// Options controlling the static analyzer. AnalyzerOptions AnalyzerOpts; diff --git a/include/clang/Frontend/DeclContextXML.def b/include/clang/Frontend/DeclContextXML.def deleted file mode 100644 index 39ed5f9432b6..000000000000 --- a/include/clang/Frontend/DeclContextXML.def +++ /dev/null @@ -1,113 +0,0 @@ -//===-- DeclContextXML.def - Metadata about Context XML nodes ---*- 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 XML context info database as written in the -// <ReferenceSection>/<Contexts> sub-nodes of the XML document. Type nodes -// are referred by "context" reference attributes throughout the document. -// A context node never contains sub-nodes. -// The semantics of the attributes and enums are mostly self-documenting -// by looking at the appropriate internally used functions and values. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// context of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that context -// node and possible sub-nodes follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Context nodes have an "id" attribute containing a -// string, which value uniquely identify that statement. Other nodes may refer -// by "context" attributes to this value. -// -// TYPE_ATTRIBUTE_XML( FN ) - Context nodes may refer to the ids of type -// nodes by a "type" attribute, if they create a type during declaration. -// For instance 'struct S;' creates both a context 'S::' and a type 'S'. -// Contexts and types always have different ids, however declarations and -// contexts may share the same ids. FN is internally used by clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally -// used by clang. A boolean attribute have the values "0" or "1". -// -// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the -// empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is -// internally used by clang. -// -// END_ENUM_XML - Closes the enumeration definition of the current attribute. -// -//===----------------------------------------------------------------------===// - -#ifndef TYPE_ATTRIBUTE_XML -# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#endif - -#ifndef CONTEXT_ATTRIBUTE_XML -# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#endif - -NODE_XML(TranslationUnitDecl, "TranslationUnit") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(FunctionDecl, "Function") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAsFunctionType()) -END_NODE_XML - -NODE_XML(NamespaceDecl, "Namespace") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") -END_NODE_XML - -NODE_XML(RecordDecl, "Record") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getTypeForDecl()) -END_NODE_XML - -NODE_XML(EnumDecl, "Enum") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getTypeForDecl()) -END_NODE_XML - -NODE_XML(LinkageSpecDecl, "LinkageSpec") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang") - ENUM_XML(LinkageSpecDecl::lang_c, "C") - ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX") - END_ENUM_XML -END_NODE_XML - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef TYPE_ATTRIBUTE_XML -#undef ATTRIBUTE_XML -#undef ATTRIBUTE_SPECIAL_XML -#undef ATTRIBUTE_OPT_XML -#undef ATTRIBUTE_ENUM_XML -#undef ATTRIBUTE_ENUM_OPT_XML -#undef ATTRIBUTE_FILE_LOCATION_XML -#undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML -#undef SUB_NODE_XML -#undef SUB_NODE_SEQUENCE_XML -#undef SUB_NODE_OPT_XML diff --git a/include/clang/Frontend/DeclXML.def b/include/clang/Frontend/DeclXML.def deleted file mode 100644 index 58f7e55fbe80..000000000000 --- a/include/clang/Frontend/DeclXML.def +++ /dev/null @@ -1,372 +0,0 @@ -//===-- DeclXML.def - Metadata about Decl XML nodes ------------*- 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 XML statement database structure as written in -// <TranslationUnit> sub-nodes of the XML document. -// The semantics of the attributes and enums are mostly self-documenting -// by looking at the appropriate internally used functions and values. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// statement of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that statement -// node and possible sub-nodes follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a -// string, which value uniquely identify that statement. Other nodes may refer -// by reference attributes to this value (currently used only for Label). -// -// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an -// expression by a "type" attribute. FN is internally used by clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally -// used by clang. A boolean attribute have the values "0" or "1". -// -// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves -// a special handling. See the appropriate documentations. -// -// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of -// a statement in the source file(s). -// -// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. -// Optional attributes are omitted for boolean types, if the value is false, -// for integral types, if the value is null and for strings, -// if the value is the empty string. FN is internally used by clang. -// -// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the -// empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is -// internally used by clang. -// -// END_ENUM_XML - Closes the enumeration definition of the current attribute. -// -// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or -// its sub-classes. -// -//===----------------------------------------------------------------------===// - -#ifndef ATTRIBUTE_FILE_LOCATION_XML -# define ATTRIBUTE_FILE_LOCATION_XML \ - ATTRIBUTE_XML(getFilename(), "file") \ - ATTRIBUTE_XML(getLine(), "line") \ - ATTRIBUTE_XML(getColumn(), "col") \ - ATTRIBUTE_OPT_XML(getFilename(), "endfile") \ - ATTRIBUTE_OPT_XML(getLine(), "endline") \ - ATTRIBUTE_OPT_XML(getColumn(), "endcol") -#endif - -#ifndef TYPE_ATTRIBUTE_XML -# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#endif - -#ifndef CONTEXT_ATTRIBUTE_XML -# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#endif - -//NODE_XML(TranslationUnitDecl, "TranslationUnit") -// SUB_NODE_SEQUENCE_XML(Decl) -//END_NODE_XML - -NODE_XML(Decl, "FIXME_Decl") - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclKindName(), "unhandled_decl_name") -END_NODE_XML - -NODE_XML(FunctionDecl, "Function") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) - ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") - ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") - ENUM_XML(SC_None, "") - ENUM_XML(SC_Extern, "extern") - ENUM_XML(SC_Static, "static") - ENUM_XML(SC_PrivateExtern, "__private_extern__") - END_ENUM_XML - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - //ATTRIBUTE_OPT_XML(isVariadic(), "variadic") // in the type reference - ATTRIBUTE_XML(getNumParams(), "num_args") - ATTRIBUTE_OPT_XML(isMain(), "main") - ATTRIBUTE_OPT_XML(isExternC(), "externc") - ATTRIBUTE_OPT_XML(isGlobal(), "global") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(CXXMethodDecl, "CXXMethod") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) - ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") - ATTRIBUTE_OPT_XML(isPure(), "pure") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_XML(getNumParams(), "num_args") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(CXXConstructorDecl, "CXXConstructor") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) - ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") - ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit") - ATTRIBUTE_OPT_XML(isDefaultConstructor(), "is_default_ctor") - ATTRIBUTE_OPT_XML(isCopyConstructor(), "is_copy_ctor") - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_XML(getNumParams(), "num_args") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(CXXDestructorDecl, "CXXDestructor") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) - ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_XML(getNumParams(), "num_args") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(CXXConversionDecl, "CXXConversion") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()->getAs<FunctionType>()->getResultType()) - ATTRIBUTE_XML(getType()->getAs<FunctionType>(), "function_type") - ATTRIBUTE_OPT_XML(isExplicit(), "is_explicit") - ATTRIBUTE_OPT_XML(isInlineSpecified(), "inline") - ATTRIBUTE_OPT_XML(isStatic(), "static") - ATTRIBUTE_OPT_XML(isVirtual(), "virtual") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_XML(getNumParams(), "num_args") - SUB_NODE_SEQUENCE_XML(ParmVarDecl) - SUB_NODE_FN_BODY_XML -END_NODE_XML - -NODE_XML(NamespaceDecl, "Namespace") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - SUB_NODE_SEQUENCE_XML(DeclContext) -END_NODE_XML - -NODE_XML(UsingDirectiveDecl, "UsingDirective") - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_XML(getNominatedNamespace(), "ref") -END_NODE_XML - -NODE_XML(NamespaceAliasDecl, "NamespaceAlias") - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_XML(getNamespace(), "ref") -END_NODE_XML - -NODE_XML(RecordDecl, "Record") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") - ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates - SUB_NODE_SEQUENCE_XML(FieldDecl) -END_NODE_XML - -NODE_XML(CXXRecordDecl, "CXXRecord") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") - ATTRIBUTE_XML(getTypeForDecl(), "type") // refers to the type this decl creates - SUB_NODE_SEQUENCE_XML(FieldDecl) -END_NODE_XML - -NODE_XML(EnumDecl, "Enum") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - ATTRIBUTE_OPT_XML(isDefinition() == false, "forward") - ATTRIBUTE_SPECIAL_XML(getIntegerType(), "type") // is NULL in pure declarations thus deserves special handling - SUB_NODE_SEQUENCE_XML(EnumConstantDecl) // only present in definition -END_NODE_XML - -NODE_XML(EnumConstantDecl, "EnumConstant") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getInitVal().toString(10, true), "value") // integer - SUB_NODE_OPT_XML(Expr) // init expr of this constant -END_NODE_XML - -NODE_XML(FieldDecl, "Field") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_OPT_XML(isMutable(), "mutable") - ATTRIBUTE_ENUM_OPT_XML(getAccess(), "access") - ENUM_XML(AS_none, "") - ENUM_XML(AS_public, "public") - ENUM_XML(AS_protected, "protected") - ENUM_XML(AS_private, "private") - END_ENUM_XML - ATTRIBUTE_OPT_XML(isBitField(), "bitfield") - SUB_NODE_OPT_XML(Expr) // init expr of a bit field -END_NODE_XML - -NODE_XML(TypedefDecl, "Typedef") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getUnderlyingType()) -END_NODE_XML - -NODE_XML(VarDecl, "Var") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_OPT_XML(getStorageClass(), "storage_class") - ENUM_XML(SC_None, "") - ENUM_XML(SC_Auto, "auto") - ENUM_XML(SC_Register, "register") - ENUM_XML(SC_Extern, "extern") - ENUM_XML(SC_Static, "static") - ENUM_XML(SC_PrivateExtern, "__private_extern__") - END_ENUM_XML - SUB_NODE_OPT_XML(Expr) // init expr -END_NODE_XML - -NODE_XML(ParmVarDecl, "ParmVar") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_OPT_XML(Expr) // default argument expression -END_NODE_XML - -NODE_XML(LinkageSpecDecl, "LinkageSpec") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_ENUM_OPT_XML(getLanguage(), "lang") - ENUM_XML(LinkageSpecDecl::lang_c, "C") - ENUM_XML(LinkageSpecDecl::lang_cxx, "CXX") - END_ENUM_XML - SUB_NODE_XML(DeclContext) -END_NODE_XML - -NODE_XML(TemplateDecl, "Template") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") -END_NODE_XML - -NODE_XML(TemplateTypeParmDecl, "TemplateTypeParm") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getNameAsString(), "name") -END_NODE_XML - -NODE_XML(UsingShadowDecl, "UsingShadow") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getTargetDecl(), "target_decl") - ATTRIBUTE_XML(getUsingDecl(), "using_decl") -END_NODE_XML - -NODE_XML(UsingDecl, "Using") - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getDeclContext(), "context") - ATTRIBUTE_XML(getQualifier(), "target_nested_namespace_decl") - ATTRIBUTE_XML(isTypeName(), "is_typename") -END_NODE_XML - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef TYPE_ATTRIBUTE_XML -#undef ATTRIBUTE_XML -#undef ATTRIBUTE_SPECIAL_XML -#undef ATTRIBUTE_OPT_XML -#undef ATTRIBUTE_ENUM_XML -#undef ATTRIBUTE_ENUM_OPT_XML -#undef ATTRIBUTE_FILE_LOCATION_XML -#undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML -#undef SUB_NODE_XML -#undef SUB_NODE_SEQUENCE_XML -#undef SUB_NODE_OPT_XML -#undef SUB_NODE_FN_BODY_XML diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index f7f498bff024..ff92058f01df 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -31,8 +31,10 @@ public: unsigned ShowFixits : 1; /// Show fixit information. unsigned ShowSourceRanges : 1; /// Show source ranges in numeric form. unsigned ShowParseableFixits : 1; /// Show machine parseable fix-its. - unsigned ShowOptionNames : 1; /// Show the diagnostic name for mappable + unsigned ShowNames : 1; /// Show the diagnostic name + unsigned ShowOptionNames : 1; /// Show the option name for mappable /// diagnostics. + unsigned ShowNoteIncludeStack : 1; /// Show include stacks for notes. unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number, /// 2 -> Full Name. unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. @@ -60,6 +62,9 @@ public: /// testing and analysis. std::string DumpBuildInformation; + /// The file to log diagnostic output to. + std::string DiagnosticLogFile; + /// The list of -W... options used to alter the diagnostic mappings, with the /// prefixes removed. std::vector<std::string> Warnings; @@ -78,6 +83,7 @@ public: ShowColumn = 1; ShowFixits = 1; ShowLocation = 1; + ShowNames = 0; ShowOptionNames = 0; ShowCategories = 0; ShowSourceRanges = 0; diff --git a/include/clang/Frontend/DocumentXML.def b/include/clang/Frontend/DocumentXML.def deleted file mode 100644 index 4c52bd84422f..000000000000 --- a/include/clang/Frontend/DocumentXML.def +++ /dev/null @@ -1,75 +0,0 @@ -//===-- DocumentXML.def - Metadata about Document XML nodes -----*- 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 XML root database structure as written in -// an AST XML document. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// statement of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that statement -// node and possible sub-nodes follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Some nodes have an "id" attribute containing a -// string, which value uniquely identify the entity represented by that node. -// Other nodes may refer by reference attributes to this value. -// -// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves -// a special handling. See the appropriate documentations. -// -// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or -// its sub-classes. -// -//===----------------------------------------------------------------------===// - -ROOT_NODE_XML("CLANG_XML") - ATTRIBUTE_SPECIAL_XML(ignore, "version") // special retrieving needed - SUB_NODE_XML("TranslationUnit") - SUB_NODE_XML("ReferenceSection") -END_NODE_XML - -NODE_XML("TranslationUnit") - SUB_NODE_SEQUENCE_XML(Decl) -END_NODE_XML - -NODE_XML("ReferenceSection") - SUB_NODE_XML("Types") - SUB_NODE_XML("Contexts") - SUB_NODE_XML("Files") -END_NODE_XML - -NODE_XML("Types") - SUB_NODE_SEQUENCE_XML(Type) -END_NODE_XML - -NODE_XML("Contexts") - SUB_NODE_SEQUENCE_XML(DeclContext) -END_NODE_XML - -NODE_XML("Files") - SUB_NODE_SEQUENCE_XML("File") -END_NODE_XML - -NODE_XML("File") - ID_ATTRIBUTE_XML - ATTRIBUTE_SPECIAL_XML(ignore, "name") // special retrieving needed, denotes the source file name -END_NODE_XML - - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef ATTRIBUTE_SPECIAL_XML -#undef END_NODE_XML -#undef SUB_NODE_XML -#undef SUB_NODE_SEQUENCE_XML diff --git a/include/clang/Frontend/DocumentXML.h b/include/clang/Frontend/DocumentXML.h deleted file mode 100644 index 602d84655828..000000000000 --- a/include/clang/Frontend/DocumentXML.h +++ /dev/null @@ -1,185 +0,0 @@ -//===--- DocumentXML.h - XML document for ASTs ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements the XML document class, which provides the means to -// dump out the AST in a XML form that exposes type details and other fields. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_FRONTEND_DOCUMENTXML_H -#define LLVM_CLANG_FRONTEND_DOCUMENTXML_H - -#include <string> -#include <map> -#include <stack> -#include "clang/AST/Type.h" -#include "clang/AST/TypeOrdering.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/ADT/DenseMap.h" - -namespace clang { - -//--------------------------------------------------------- forwards -class DeclContext; -class Decl; -class NamedDecl; -class FunctionDecl; -class ASTContext; -class LabelStmt; - -//--------------------------------------------------------- -namespace XML { - // id maps: - template<class T> - struct IdMap : llvm::DenseMap<T, unsigned> {}; - - template<> - struct IdMap<QualType> : std::map<QualType, unsigned, QualTypeOrdering> {}; - - template<> - struct IdMap<std::string> : std::map<std::string, unsigned> {}; -} - -//--------------------------------------------------------- -class DocumentXML { -public: - DocumentXML(const std::string& rootName, llvm::raw_ostream& out); - - void initialize(ASTContext &Context); - void PrintDecl(Decl *D); - void PrintStmt(const Stmt *S); // defined in StmtXML.cpp - void finalize(); - - - DocumentXML& addSubNode(const std::string& name); // also enters the sub node, returns *this - DocumentXML& toParent(); // returns *this - - void addAttribute(const char* pName, const QualType& pType); - void addAttribute(const char* pName, bool value); - - template<class T> - void addAttribute(const char* pName, const T* value) { - addPtrAttribute(pName, value); - } - - template<class T> - void addAttribute(const char* pName, T* value) { - addPtrAttribute(pName, value); - } - - template<class T> - void addAttribute(const char* pName, const T& value); - - template<class T> - void addAttributeOptional(const char* pName, const T& value); - - void addSourceFileAttribute(const std::string& fileName); - - PresumedLoc addLocation(const SourceLocation& Loc); - void addLocationRange(const SourceRange& R); - - static std::string escapeString(const char* pStr, std::string::size_type len); - -private: - DocumentXML(const DocumentXML&); // not defined - DocumentXML& operator=(const DocumentXML&); // not defined - - std::stack<std::string> NodeStack; - llvm::raw_ostream& Out; - ASTContext *Ctx; - bool HasCurrentNodeSubNodes; - - - XML::IdMap<QualType> Types; - XML::IdMap<const DeclContext*> Contexts; - XML::IdMap<const Type*> BasicTypes; - XML::IdMap<std::string> SourceFiles; - XML::IdMap<const NamedDecl*> Decls; - XML::IdMap<const LabelStmt*> Labels; - - void addContextsRecursively(const DeclContext *DC); - void addTypeRecursively(const Type* pType); - void addTypeRecursively(const QualType& pType); - - void Indent(); - - // forced pointer dispatch: - void addPtrAttribute(const char* pName, const Type* pType); - void addPtrAttribute(const char* pName, const NamedDecl* D); - void addPtrAttribute(const char* pName, const DeclContext* D); - void addPtrAttribute(const char* pName, const NamespaceDecl* D); // disambiguation - void addPtrAttribute(const char* pName, const NestedNameSpecifier* N); - void addPtrAttribute(const char* pName, const LabelStmt* L); - void addPtrAttribute(const char* pName, const char* text); - - // defined in TypeXML.cpp: - void addParentTypes(const Type* pType); - void writeTypeToXML(const Type* pType); - void writeTypeToXML(const QualType& pType); - class TypeAdder; - friend class TypeAdder; - - // defined in DeclXML.cpp: - void writeDeclToXML(Decl *D); - class DeclPrinter; - friend class DeclPrinter; - - // for addAttributeOptional: - static bool isDefault(unsigned value) { return value == 0; } - static bool isDefault(bool value) { return !value; } - static bool isDefault(Qualifiers::GC value) { return value == Qualifiers::GCNone; } - static bool isDefault(const std::string& value) { return value.empty(); } -}; - -//--------------------------------------------------------- inlines - -inline void DocumentXML::initialize(ASTContext &Context) { - Ctx = &Context; -} - -//--------------------------------------------------------- -template<class T> -inline void DocumentXML::addAttribute(const char* pName, const T& value) { - std::string repr; - { - llvm::raw_string_ostream buf(repr); - buf << value; - } - - Out << ' ' << pName << "=\"" - << DocumentXML::escapeString(repr.c_str(), repr.size()) - << "\""; -} - -//--------------------------------------------------------- -inline void DocumentXML::addPtrAttribute(const char* pName, const char* text) { - Out << ' ' << pName << "=\"" - << DocumentXML::escapeString(text, strlen(text)) - << "\""; -} - -//--------------------------------------------------------- -inline void DocumentXML::addAttribute(const char* pName, bool value) { - addPtrAttribute(pName, value ? "1" : "0"); -} - -//--------------------------------------------------------- -template<class T> -inline void DocumentXML::addAttributeOptional(const char* pName, - const T& value) { - if (!isDefault(value)) { - addAttribute(pName, value); - } -} - -//--------------------------------------------------------- - -} //namespace clang - -#endif //LLVM_CLANG_DOCUMENTXML_H diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 4df2e71571f7..4e67449b8549 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -42,12 +42,6 @@ protected: 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, diff --git a/include/clang/Frontend/FrontendDiagnostic.h b/include/clang/Frontend/FrontendDiagnostic.h index 2efbc818de1b..3e9508c009c8 100644 --- a/include/clang/Frontend/FrontendDiagnostic.h +++ b/include/clang/Frontend/FrontendDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define FRONTENDSTART #include "clang/Basic/DiagnosticFrontendKinds.inc" #undef DIAG diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 19d39c3ca1b2..02f6f868fe49 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -23,7 +23,6 @@ namespace frontend { ASTDump, ///< Parse ASTs and dump them. ASTDumpXML, ///< Parse ASTs and dump them in XML. ASTPrint, ///< Parse ASTs and print them. - ASTPrintXML, ///< Parse ASTs and print them in XML. ASTView, ///< Parse ASTs and view them in Graphviz. BoostCon, ///< BoostCon mode. CreateModule, ///< Create module definition diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Frontend/LangStandard.h index 441d34f5a388..74ca5191dd48 100644 --- a/include/clang/Frontend/LangStandard.h +++ b/include/clang/Frontend/LangStandard.h @@ -19,12 +19,13 @@ namespace frontend { enum LangFeatures { BCPLComment = (1 << 0), C99 = (1 << 1), - CPlusPlus = (1 << 2), - CPlusPlus0x = (1 << 3), - Digraphs = (1 << 4), - GNUMode = (1 << 5), - HexFloat = (1 << 6), - ImplicitInt = (1 << 7) + C1X = (1 << 2), + CPlusPlus = (1 << 3), + CPlusPlus0x = (1 << 4), + Digraphs = (1 << 5), + GNUMode = (1 << 6), + HexFloat = (1 << 7), + ImplicitInt = (1 << 8) }; } @@ -56,6 +57,9 @@ public: /// isC99 - Language is a superset of C99. bool isC99() const { return Flags & frontend::C99; } + /// isC1X - Language is a superset of C1X. + bool isC1X() const { return Flags & frontend::C1X; } + /// isCPlusPlus - Language is a C++ variant. bool isCPlusPlus() const { return Flags & frontend::CPlusPlus; } diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def index d4046b3e5668..586e5c8fa2a4 100644 --- a/include/clang/Frontend/LangStandards.def +++ b/include/clang/Frontend/LangStandards.def @@ -54,11 +54,23 @@ LANGSTANDARD(iso9899_199x, LANGSTANDARD(gnu99, "gnu99", "ISO C 1999 with GNU extensions", - BCPLComment | C99 | Digraphs | GNUMode | HexFloat | Digraphs) + BCPLComment | C99 | Digraphs | GNUMode | HexFloat) LANGSTANDARD(gnu9x, "gnu9x", "ISO C 1999 with GNU extensions", BCPLComment | C99 | Digraphs | GNUMode | HexFloat) +// C1X modes +LANGSTANDARD(c1x, "c1x", + "ISO C 201X", + BCPLComment | C99 | C1X | Digraphs | HexFloat) +LANGSTANDARD(iso9899_201x, + "iso9899:201x", "ISO C 201X", + BCPLComment | C99 | C1X | Digraphs | HexFloat) + +LANGSTANDARD(gnu1x, "gnu1x", + "ISO C 201X with GNU extensions", + BCPLComment | C99 | C1X | Digraphs | GNUMode | HexFloat) + // C++ modes LANGSTANDARD(cxx98, "c++98", "ISO C++ 1998 with amendments", diff --git a/include/clang/Frontend/LogDiagnosticPrinter.h b/include/clang/Frontend/LogDiagnosticPrinter.h new file mode 100644 index 000000000000..b6fc23ca1f04 --- /dev/null +++ b/include/clang/Frontend/LogDiagnosticPrinter.h @@ -0,0 +1,77 @@ +//===--- LogDiagnosticPrinter.h - Log 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_LOG_DIAGNOSTIC_PRINTER_H_ +#define LLVM_CLANG_FRONTEND_LOG_DIAGNOSTIC_PRINTER_H_ + +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { +class DiagnosticOptions; +class LangOptions; + +class LogDiagnosticPrinter : public DiagnosticClient { + struct DiagEntry { + /// The primary message line of the diagnostic. + std::string Message; + + /// The source file name, if available. + std::string Filename; + + /// The source file line number, if available. + unsigned Line; + + /// The source file column number, if available. + unsigned Column; + + /// The ID of the diagnostic. + unsigned DiagnosticID; + + /// The level of the diagnostic. + Diagnostic::Level DiagnosticLevel; + }; + + llvm::raw_ostream &OS; + const LangOptions *LangOpts; + const DiagnosticOptions *DiagOpts; + + SourceLocation LastWarningLoc; + FullSourceLoc LastLoc; + unsigned OwnsOutputStream : 1; + + llvm::SmallVector<DiagEntry, 8> Entries; + + std::string MainFilename; + std::string DwarfDebugFlags; + +public: + LogDiagnosticPrinter(llvm::raw_ostream &OS, const DiagnosticOptions &Diags, + bool OwnsOutputStream = false); + virtual ~LogDiagnosticPrinter(); + + void setDwarfDebugFlags(llvm::StringRef Value) { + DwarfDebugFlags = Value; + } + + void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) { + LangOpts = &LO; + } + + void EndSourceFile(); + + virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + const DiagnosticInfo &Info); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h index 560178be9bf8..4242f0117147 100644 --- a/include/clang/Frontend/MultiplexConsumer.h +++ b/include/clang/Frontend/MultiplexConsumer.h @@ -12,6 +12,9 @@ // //===----------------------------------------------------------------------===// +#ifndef CLANG_FRONTEND_MULTIPLEXCONSUMER_H +#define CLANG_FRONTEND_MULTIPLEXCONSUMER_H + #include "clang/Sema/SemaConsumer.h" #include "llvm/ADT/OwningPtr.h" #include <vector> @@ -52,3 +55,5 @@ private: }; } // end namespace clang + +#endif diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h index 0d52e53ea16a..e875ec1fefd2 100644 --- a/include/clang/Frontend/PreprocessorOptions.h +++ b/include/clang/Frontend/PreprocessorOptions.h @@ -44,6 +44,9 @@ public: /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; + /// \brief Headers that will be converted to chained PCHs in memory. + std::vector<std::string> ChainedIncludes; + /// \brief When true, disables most of the normal validation performed on /// precompiled headers. bool DisablePCHValidation; @@ -73,6 +76,10 @@ public: /// If given, a PTH cache file to use for speeding up header parsing. std::string TokenCache; + /// \brief True if the SourceManager should report the original file name for + /// contents of files that were remapped to other files. Defaults to true. + bool RemappedFilesKeepOriginalName; + /// \brief The set of file remappings, which take existing files on /// the system (the first part of each pair) and gives them the /// contents of other files on the system (the second part of each @@ -132,6 +139,7 @@ public: DisablePCHValidation(false), DisableStatCache(false), DumpDeserializedPCHDecls(false), PrecompiledPreambleBytes(0, true), + RemappedFilesKeepOriginalName(true), RetainRemappedFileBuffers(false) { } void addMacroDef(llvm::StringRef Name) { diff --git a/include/clang/Frontend/StmtXML.def b/include/clang/Frontend/StmtXML.def deleted file mode 100644 index 8a859e6898b1..000000000000 --- a/include/clang/Frontend/StmtXML.def +++ /dev/null @@ -1,520 +0,0 @@ -//===-- StmtXML.def - Metadata about Stmt XML nodes ------------*- 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 XML statement database structure as written in -// <TranslationUnit> sub-nodes of the XML document. -// The semantics of the attributes and enums are mostly self-documenting -// by looking at the appropriate internally used functions and values. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// statement of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that statement -// node and possible sub-nodes follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Some statement nodes have an "id" attribute containing a -// string, which value uniquely identify that statement. Other nodes may refer -// by reference attributes to this value (currently used only for Label). -// -// TYPE_ATTRIBUTE_XML( FN ) - Type nodes refer to the result type id of an -// expression by a "type" attribute. FN is internally used by clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally -// used by clang. A boolean attribute have the values "0" or "1". -// -// ATTRIBUTE_SPECIAL_XML( FN, NAME ) - An attribute named NAME which deserves -// a special handling. See the appropriate documentations. -// -// ATTRIBUTE_FILE_LOCATION_XML - A bunch of attributes denoting the location of -// a statement in the source file(s). -// -// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. -// Optional attributes are omitted for boolean types, if the value is false, -// for integral types, if the value is null and for strings, -// if the value is the empty string. FN is internally used by clang. -// -// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the -// empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is -// internally used by clang. -// -// END_ENUM_XML - Closes the enumeration definition of the current attribute. -// -// SUB_NODE_XML( CLASS ) - A mandatory sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_OPT_XML( CLASS ) - An optional sub-node of class CLASS or its sub-classes. -// -// SUB_NODE_SEQUENCE_XML( CLASS ) - Zero or more sub-nodes of class CLASS or -// its sub-classes. -// -//===----------------------------------------------------------------------===// - -#ifndef ATTRIBUTE_FILE_LOCATION_XML -# define ATTRIBUTE_FILE_LOCATION_XML \ - ATTRIBUTE_XML(getFilename(), "file") \ - ATTRIBUTE_XML(getLine(), "line") \ - ATTRIBUTE_XML(getColumn(), "col") \ - ATTRIBUTE_OPT_XML(getFilename(), "endfile") \ - ATTRIBUTE_OPT_XML(getLine(), "endline") \ - ATTRIBUTE_OPT_XML(getColumn(), "endcol") -#endif - -#ifndef TYPE_ATTRIBUTE_XML -# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#endif - -#ifndef CONTEXT_ATTRIBUTE_XML -# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#endif - -NODE_XML(Stmt, "Stmt_Unsupported") // fallback for unsupproted statements - ATTRIBUTE_FILE_LOCATION_XML -END_NODE_XML - -NODE_XML(NullStmt, "NullStmt") - ATTRIBUTE_FILE_LOCATION_XML -END_NODE_XML - -NODE_XML(CompoundStmt, "CompoundStmt") - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(size(), "num_stmts") - SUB_NODE_SEQUENCE_XML(Stmt) -END_NODE_XML - -NODE_XML(CaseStmt, "CaseStmt") // case expr: body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Stmt) // body - SUB_NODE_XML(Expr) // expr - SUB_NODE_XML(Expr) // rhs expr in gc extension: case expr .. expr: body; -END_NODE_XML - -NODE_XML(DefaultStmt, "DefaultStmt") // default: body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(LabelStmt, "LabelStmt") // Label: body; - ID_ATTRIBUTE_XML - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getName(), "name") // string - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(IfStmt, "IfStmt") // if (cond) stmt1; else stmt2; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Stmt) // stmt1 - SUB_NODE_XML(Stmt) // stmt2 -END_NODE_XML - -NODE_XML(SwitchStmt, "SwitchStmt") // switch (cond) body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(WhileStmt, "WhileStmt") // while (cond) body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(DoStmt, "DoStmt") // do body while (cond); - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(ForStmt, "ForStmt") // for (init; cond; inc) body; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Stmt) // init - SUB_NODE_XML(Expr) // cond - SUB_NODE_XML(Expr) // inc - SUB_NODE_XML(Stmt) // body -END_NODE_XML - -NODE_XML(GotoStmt, "GotoStmt") // goto label; - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getLabel()->getName(), "name") // informal string - ATTRIBUTE_XML(getLabel(), "ref") // id string -END_NODE_XML - -NODE_XML(IndirectGotoStmt, "IndirectGotoStmt") // goto expr; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(ContinueStmt, "ContinueStmt") // continue - ATTRIBUTE_FILE_LOCATION_XML -END_NODE_XML - -NODE_XML(BreakStmt, "BreakStmt") // break - ATTRIBUTE_FILE_LOCATION_XML -END_NODE_XML - -NODE_XML(ReturnStmt, "ReturnStmt") // return expr; - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(AsmStmt, "AsmStmt") // GNU inline-assembly statement extension - ATTRIBUTE_FILE_LOCATION_XML - // FIXME -END_NODE_XML - -NODE_XML(DeclStmt, "DeclStmt") // a declaration statement - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_SEQUENCE_XML(Decl) -END_NODE_XML - -// C++ statements -NODE_XML(CXXTryStmt, "CXXTryStmt") // try CompoundStmt CXXCatchStmt1 CXXCatchStmt2 .. - ATTRIBUTE_FILE_LOCATION_XML - ATTRIBUTE_XML(getNumHandlers(), "num_handlers") - SUB_NODE_XML(CompoundStmt) - SUB_NODE_SEQUENCE_XML(CXXCatchStmt) -END_NODE_XML - -NODE_XML(CXXCatchStmt, "CXXCatchStmt") // catch (decl) Stmt - ATTRIBUTE_FILE_LOCATION_XML - SUB_NODE_XML(VarDecl) - SUB_NODE_XML(Stmt) -END_NODE_XML - -// Expressions -NODE_XML(PredefinedExpr, "PredefinedExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_XML(getIdentType(), "kind") - ENUM_XML(PredefinedExpr::Func, "__func__") - ENUM_XML(PredefinedExpr::Function, "__FUNCTION__") - ENUM_XML(PredefinedExpr::PrettyFunction, "__PRETTY_FUNCTION__") - END_ENUM_XML -END_NODE_XML - -NODE_XML(DeclRefExpr, "DeclRefExpr") // an expression referring to a declared entity - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getDecl(), "ref") // id string of the declaration - ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // informal - //ATTRIBUTE_ENUM_XML(getDecl()->getKind(), "kind") // really needed here? -END_NODE_XML - -NODE_XML(IntegerLiteral, "IntegerLiteral") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getValue(), "value") // (signed) integer -END_NODE_XML - -NODE_XML(CharacterLiteral, "CharacterLiteral") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getValue(), "value") // unsigned -END_NODE_XML - -NODE_XML(FloatingLiteral, "FloatingLiteral") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - // FIXME: output float as written in source (no approximation or the like) - //ATTRIBUTE_XML(getValueAsApproximateDouble(), "value") // float -END_NODE_XML - -NODE_XML(StringLiteral, "StringLiteral") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_SPECIAL_XML(getStrData(), "value") // string, special handling for escaping needed - ATTRIBUTE_OPT_XML(isWide(), "is_wide") // boolean -END_NODE_XML - -NODE_XML(UnaryOperator, "UnaryOperator") // op(expr) or (expr)op - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_XML(getOpcode(), "kind") - ENUM_XML(UO_PostInc, "postinc") - ENUM_XML(UO_PostDec, "postdec") - ENUM_XML(UO_PreInc, "preinc") - ENUM_XML(UO_PreDec, "predec") - ENUM_XML(UO_AddrOf, "addrof") - ENUM_XML(UO_Deref, "deref") - ENUM_XML(UO_Plus, "plus") - ENUM_XML(UO_Minus, "minus") - ENUM_XML(UO_Not, "not") // bitwise not - ENUM_XML(UO_LNot, "lnot") // boolean not - ENUM_XML(UO_Real, "__real") - ENUM_XML(UO_Imag, "__imag") - ENUM_XML(UO_Extension, "__extension__") - END_ENUM_XML - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(BinaryOperator, "BinaryOperator") // (expr1) op (expr2) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_XML(getOpcode(), "kind") - ENUM_XML(BO_PtrMemD , "ptrmemd") - ENUM_XML(BO_PtrMemI , "ptrmemi") - ENUM_XML(BO_Mul , "mul") - ENUM_XML(BO_Div , "div") - ENUM_XML(BO_Rem , "rem") - ENUM_XML(BO_Add , "add") - ENUM_XML(BO_Sub , "sub") - ENUM_XML(BO_Shl , "shl") - ENUM_XML(BO_Shr , "shr") - ENUM_XML(BO_LT , "lt") - ENUM_XML(BO_GT , "gt") - ENUM_XML(BO_LE , "le") - ENUM_XML(BO_GE , "ge") - ENUM_XML(BO_EQ , "eq") - ENUM_XML(BO_NE , "ne") - ENUM_XML(BO_And , "and") // bitwise and - ENUM_XML(BO_Xor , "xor") - ENUM_XML(BO_Or , "or") // bitwise or - ENUM_XML(BO_LAnd , "land") // boolean and - ENUM_XML(BO_LOr , "lor") // boolean or - ENUM_XML(BO_Assign , "assign") - ENUM_XML(BO_MulAssign, "mulassign") - ENUM_XML(BO_DivAssign, "divassign") - ENUM_XML(BO_RemAssign, "remassign") - ENUM_XML(BO_AddAssign, "addassign") - ENUM_XML(BO_SubAssign, "subassign") - ENUM_XML(BO_ShlAssign, "shlassign") - ENUM_XML(BO_ShrAssign, "shrassign") - ENUM_XML(BO_AndAssign, "andassign") - ENUM_XML(BO_XorAssign, "xorassign") - ENUM_XML(BO_OrAssign , "orassign") - ENUM_XML(BO_Comma , "comma") - END_ENUM_XML - SUB_NODE_XML(Expr) // expr1 - SUB_NODE_XML(Expr) // expr2 -END_NODE_XML - -// FIXME: is there a special class needed or is BinaryOperator sufficient? -//NODE_XML(CompoundAssignOperator, "CompoundAssignOperator") - -NODE_XML(ConditionalOperator, "ConditionalOperator") // expr1 ? expr2 : expr3 - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr1 - SUB_NODE_XML(Expr) // expr2 - SUB_NODE_XML(Expr) // expr3 -END_NODE_XML - -NODE_XML(OffsetOfExpr, "OffsetOfExpr") // offsetof(basetype, components) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getTypeSourceInfo()->getType()) - ATTRIBUTE_XML(getNumComponents(), "num_components") - SUB_NODE_SEQUENCE_XML(OffsetOfExpr::OffsetOfNode) -END_NODE_XML - -NODE_XML(SizeOfAlignOfExpr, "SizeOfAlignOfExpr") // sizeof(expr) or alignof(expr) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(isSizeOf(), "is_sizeof") - ATTRIBUTE_XML(isArgumentType(), "is_type") // "1" if expr denotes a type - ATTRIBUTE_SPECIAL_XML(getArgumentType(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getArgumentType() could assert - SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" -END_NODE_XML - -NODE_XML(ArraySubscriptExpr, "ArraySubscriptExpr") // expr1[expr2] - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr1 - SUB_NODE_XML(Expr) // expr2 -END_NODE_XML - -NODE_XML(CallExpr, "CallExpr") // fnexpr(arg1, arg2, ...) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned - SUB_NODE_XML(Expr) // fnexpr - SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN -END_NODE_XML - -NODE_XML(MemberExpr, "MemberExpr") // expr->F or expr.F - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(isArrow(), "is_deref") - ATTRIBUTE_XML(getMemberDecl(), "ref") // refers to F - ATTRIBUTE_XML(getMemberDecl()->getNameAsString(), "name") // informal - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(CStyleCastExpr, "CStyleCastExpr") // (type)expr - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(ImplicitCastExpr, "ImplicitCastExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) -END_NODE_XML - -NODE_XML(CompoundLiteralExpr, "CompoundLiteralExpr") // [C99 6.5.2.5] - SUB_NODE_XML(Expr) // init -END_NODE_XML - -NODE_XML(ExtVectorElementExpr, "ExtVectorElementExpr") - SUB_NODE_XML(Expr) // base -END_NODE_XML - -NODE_XML(InitListExpr, "InitListExpr") // struct foo x = { expr1, { expr2, expr3 } }; - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_OPT_XML(getInitializedFieldInUnion(), "field_ref") // if a union is initialized, this refers to the initialized union field id - ATTRIBUTE_XML(getNumInits(), "num_inits") // unsigned - SUB_NODE_SEQUENCE_XML(Expr) // expr1..exprN -END_NODE_XML - -NODE_XML(DesignatedInitExpr, "DesignatedInitExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -NODE_XML(ImplicitValueInitExpr, "ImplicitValueInitExpr") // Implicit value initializations occur within InitListExpr - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -NODE_XML(VAArgExpr, "VAArgExpr") // used for the builtin function __builtin_va_start(expr) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(ParenExpr, "ParenExpr") // this represents a parethesized expression "(expr)". Only formed if full location information is requested. - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -// GNU Extensions -NODE_XML(AddrLabelExpr, "AddrLabelExpr") // the GNU address of label extension, representing &&label. - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getLabel(), "ref") // id string - SUB_NODE_XML(LabelStmt) // expr -END_NODE_XML - -NODE_XML(StmtExpr, "StmtExpr") // StmtExpr contains a single CompoundStmt node, which it evaluates and takes the value of the last subexpression. - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(CompoundStmt) -END_NODE_XML - -NODE_XML(ChooseExpr, "ChooseExpr") // GNU builtin-in function __builtin_choose_expr(expr1, expr2, expr3) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // expr1 - SUB_NODE_XML(Expr) // expr2 - SUB_NODE_XML(Expr) // expr3 -END_NODE_XML - -NODE_XML(GNUNullExpr, "GNUNullExpr") // GNU __null extension - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -// C++ Expressions -NODE_XML(CXXOperatorCallExpr, "CXXOperatorCallExpr") // fnexpr(arg1, arg2, ...) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned - SUB_NODE_XML(Expr) // fnexpr - SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN -END_NODE_XML - -NODE_XML(CXXConstructExpr, "CXXConstructExpr") // ctor(arg1, arg2, ...) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned - SUB_NODE_XML(Expr) // fnexpr - SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN -END_NODE_XML - -NODE_XML(CXXNamedCastExpr, "CXXNamedCastExpr") // xxx_cast<type>(expr) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_ENUM_XML(getStmtClass(), "kind") - ENUM_XML(Stmt::CXXStaticCastExprClass, "static_cast") - ENUM_XML(Stmt::CXXDynamicCastExprClass, "dynamic_cast") - ENUM_XML(Stmt::CXXReinterpretCastExprClass, "reinterpret_cast") - ENUM_XML(Stmt::CXXConstCastExprClass, "const_cast") - END_ENUM_XML - ATTRIBUTE_XML(getTypeAsWritten(), "type_ref") // denotes the type as written in the source code - SUB_NODE_XML(Expr) // expr -END_NODE_XML - -NODE_XML(CXXMemberCallExpr, "CXXMemberCallExpr") // fnexpr(arg1, arg2, ...) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getNumArgs(), "num_args") // unsigned - SUB_NODE_XML(Expr) // fnexpr - SUB_NODE_SEQUENCE_XML(Expr) // arg1..argN -END_NODE_XML - -NODE_XML(CXXBoolLiteralExpr, "CXXBoolLiteralExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getValue(), "value") // boolean -END_NODE_XML - -NODE_XML(CXXNullPtrLiteralExpr, "CXXNullPtrLiteralExpr") // [C++0x 2.14.7] C++ Pointer Literal - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -NODE_XML(CXXTypeidExpr, "CXXTypeidExpr") // typeid(expr) - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(isTypeOperand(), "is_type") // "1" if expr denotes a type - ATTRIBUTE_SPECIAL_XML(getTypeOperand(), "type_ref") // optional, denotes the type of expr, if is_type=="1", special handling needed since getTypeOperand() could assert - SUB_NODE_OPT_XML(Expr) // expr, if is_type=="0" -END_NODE_XML - -NODE_XML(CXXThisExpr, "CXXThisExpr") // this - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) -END_NODE_XML - -NODE_XML(CXXThrowExpr, "CXXThrowExpr") // throw (expr); - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - SUB_NODE_XML(Expr) // NULL in case of "throw;" -END_NODE_XML - -NODE_XML(CXXDefaultArgExpr, "CXXDefaultArgExpr") - ATTRIBUTE_FILE_LOCATION_XML - TYPE_ATTRIBUTE_XML(getType()) - ATTRIBUTE_XML(getParam(), "ref") // id of the parameter declaration (the expression is a subnode of the declaration) -END_NODE_XML - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef TYPE_ATTRIBUTE_XML -#undef ATTRIBUTE_XML -#undef ATTRIBUTE_SPECIAL_XML -#undef ATTRIBUTE_OPT_XML -#undef ATTRIBUTE_ENUM_XML -#undef ATTRIBUTE_ENUM_OPT_XML -#undef ATTRIBUTE_FILE_LOCATION_XML -#undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML -#undef SUB_NODE_XML -#undef SUB_NODE_SEQUENCE_XML -#undef SUB_NODE_OPT_XML diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index f5302947a593..d7d2692cb547 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -53,7 +53,8 @@ public: LangOpts = 0; } - void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM); + void PrintIncludeStack(Diagnostic::Level Level, SourceLocation Loc, + const SourceManager &SM); void HighlightRange(const CharSourceRange &R, const SourceManager &SrcMgr, @@ -61,7 +62,7 @@ public: std::string &CaretLine, const std::string &SourceLine); - void EmitCaretDiagnostic(SourceLocation Loc, + void EmitCaretDiagnostic(Diagnostic::Level Level, SourceLocation Loc, CharSourceRange *Ranges, unsigned NumRanges, const SourceManager &SM, const FixItHint *Hints, @@ -71,7 +72,7 @@ public: unsigned MacroSkipStart, unsigned MacroSkipEnd); - virtual void HandleDiagnostic(Diagnostic::Level DiagLevel, + virtual void HandleDiagnostic(Diagnostic::Level Level, const DiagnosticInfo &Info); }; diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def deleted file mode 100644 index b78e70f5aa86..000000000000 --- a/include/clang/Frontend/TypeXML.def +++ /dev/null @@ -1,304 +0,0 @@ -//===-- TypeXML.def - Metadata about Type XML nodes ------------*- 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 XML type info database as written in the -// <ReferenceSection>/<Types> sub-nodes of the XML document. Type nodes -// are referred by "type" reference attributes throughout the document. -// A type node never contains sub-nodes. -// The semantics of the attributes and enums are mostly self-documenting -// by looking at the appropriate internally used functions and values. -// The following macros are used: -// -// NODE_XML( CLASS, NAME ) - A node of name NAME denotes a concrete -// type of class CLASS where CLASS is a class name used internally by clang. -// After a NODE_XML the definition of all (optional) attributes of that type -// node follows. -// -// END_NODE_XML - Closes the attribute definition of the current node. -// -// ID_ATTRIBUTE_XML - Each type node has an "id" attribute containing a -// string, which value uniquely identify the type. Other nodes may refer -// by "type" reference attributes to this value. -// -// TYPE_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of other type -// nodes by a "type" attribute. FN is internally used by clang. -// -// CONTEXT_ATTRIBUTE_XML( FN ) - Type nodes may refer to the ids of their -// declaration contexts by a "context" attribute. FN is internally used by -// clang. -// -// ATTRIBUTE_XML( FN, NAME ) - An attribute named NAME. FN is internally -// used by clang. A boolean attribute have the values "0" or "1". -// -// ATTRIBUTE_OPT_XML( FN, NAME ) - An optional attribute named NAME. -// Optional attributes are omitted for boolean types, if the value is false, -// for integral types, if the value is null and for strings, -// if the value is the empty string. FN is internally used by clang. -// -// ATTRIBUTE_ENUM[_OPT]_XML( FN, NAME ) - An attribute named NAME. The value -// is an enumeration defined with ENUM_XML macros immediately following after -// that macro. An optional attribute is ommited, if the particular enum is the -// empty string. FN is internally used by clang. -// -// ENUM_XML( VALUE, NAME ) - An enumeration element named NAME. VALUE is -// internally used by clang. -// -// END_ENUM_XML - Closes the enumeration definition of the current attribute. -// -//===----------------------------------------------------------------------===// - -#ifndef TYPE_ATTRIBUTE_XML -# define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type") -#endif - -#ifndef CONTEXT_ATTRIBUTE_XML -# define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context") -#endif - -NODE_XML(Type, "FIXME_Type") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getTypeClassName(), "unhandled_type_name") -END_NODE_XML - -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(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 - -NODE_XML(BuiltinType, "FundamentalType") - ID_ATTRIBUTE_XML - ATTRIBUTE_ENUM_XML(getKind(), "kind") - ENUM_XML(BuiltinType::Void, "void") - ENUM_XML(BuiltinType::Bool, "bool") - ENUM_XML(BuiltinType::Char_U, "char") // not explicitely qualified char, depends on target platform - ENUM_XML(BuiltinType::Char_S, "char") // not explicitely qualified char, depends on target platform - ENUM_XML(BuiltinType::SChar, "signed char") - ENUM_XML(BuiltinType::Short, "short"); - ENUM_XML(BuiltinType::Int, "int"); - ENUM_XML(BuiltinType::Long, "long"); - ENUM_XML(BuiltinType::LongLong, "long long"); - ENUM_XML(BuiltinType::Int128, "__int128_t"); - ENUM_XML(BuiltinType::UChar, "unsigned char"); - ENUM_XML(BuiltinType::UShort, "unsigned short"); - ENUM_XML(BuiltinType::UInt, "unsigned int"); - ENUM_XML(BuiltinType::ULong, "unsigned long"); - ENUM_XML(BuiltinType::ULongLong, "unsigned long long"); - ENUM_XML(BuiltinType::UInt128, "__uint128_t"); - ENUM_XML(BuiltinType::Float, "float"); - ENUM_XML(BuiltinType::Double, "double"); - ENUM_XML(BuiltinType::LongDouble, "long double"); - ENUM_XML(BuiltinType::WChar_U, "wchar_t"); - ENUM_XML(BuiltinType::WChar_S, "wchar_t"); - ENUM_XML(BuiltinType::Char16, "char16_t"); - ENUM_XML(BuiltinType::Char32, "char32_t"); - ENUM_XML(BuiltinType::NullPtr, "nullptr_t"); // This is the type of C++0x 'nullptr'. - ENUM_XML(BuiltinType::Overload, "overloaded"); - ENUM_XML(BuiltinType::Dependent, "dependent"); - END_ENUM_XML -END_NODE_XML - -NODE_XML(PointerType, "PointerType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) -END_NODE_XML - -NODE_XML(LValueReferenceType, "ReferenceType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) -END_NODE_XML - -NODE_XML(RValueReferenceType, "ReferenceType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) -END_NODE_XML - -NODE_XML(FunctionNoProtoType, "FunctionNoProtoType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(FunctionProtoType, "FunctionType") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getResultType(), "result_type") - ATTRIBUTE_OPT_XML(isVariadic(), "variadic") - ATTRIBUTE_ENUM_XML(getCallConv(), "call_conv") - ENUM_XML(CC_Default, "") - ENUM_XML(CC_C, "C") - ENUM_XML(CC_X86StdCall, "X86StdCall") - ENUM_XML(CC_X86FastCall, "X86FastCall") - ENUM_XML(CC_X86ThisCall, "X86ThisCall") - END_ENUM_XML -END_NODE_XML - -NODE_XML(TypedefType, "Typedef") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getDecl()->getUnderlyingType()) - ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string - CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) -END_NODE_XML - -NODE_XML(ComplexType, "ComplexType") // C99 complex types (_Complex float etc) - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) -END_NODE_XML - -NODE_XML(BlockPointerType, "BlockPointerType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) // alway refers to a function type -END_NODE_XML - -NODE_XML(MemberPointerType, "MemberPointerType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getPointeeType()) - ATTRIBUTE_XML(getClass(), "class_type") // refers to the class type id of which the pointee is a member -END_NODE_XML - -NODE_XML(ConstantArrayType, "ArrayType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - ATTRIBUTE_XML(getSize(), "size") // unsigned - ATTRIBUTE_ENUM_OPT_XML(getSizeModifier(), "size_modifier") - ENUM_XML(ArrayType::Normal, "") - ENUM_XML(ArrayType::Static, "static") - ENUM_XML(ArrayType::Star, "star") - END_ENUM_XML - ATTRIBUTE_OPT_XML(getIndexTypeCVRQualifiers(), "index_type_qualifier") // unsigned -END_NODE_XML - -NODE_XML(IncompleteArrayType, "IncompleteArrayType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) -END_NODE_XML - -NODE_XML(VariableArrayType, "VariableArrayType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - // note: the size expression is print at the point of declaration -END_NODE_XML - -NODE_XML(DependentSizedArrayType, "DependentSizedArrayType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - // FIXME: how to deal with size expression? -END_NODE_XML - -NODE_XML(VectorType, "VectorType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - ATTRIBUTE_XML(getNumElements(), "size") // unsigned -END_NODE_XML - -NODE_XML(ExtVectorType, "ExtVectorType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getElementType()) - ATTRIBUTE_XML(getNumElements(), "size") // unsigned -END_NODE_XML - -NODE_XML(TypeOfExprType, "TypeOfExprType") - ID_ATTRIBUTE_XML - // note: the typeof expression is print at the point of use -END_NODE_XML - -NODE_XML(TypeOfType, "TypeOfType") - ID_ATTRIBUTE_XML - TYPE_ATTRIBUTE_XML(getUnderlyingType()) -END_NODE_XML - - -NODE_XML(RecordType, "Record") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string - ATTRIBUTE_ENUM_XML(getDecl()->getTagKind(), "kind") - ENUM_XML(TTK_Struct, "struct") - ENUM_XML(TTK_Union, "union") - ENUM_XML(TTK_Class, "class") - END_ENUM_XML - CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) -END_NODE_XML - -NODE_XML(EnumType, "Enum") - ID_ATTRIBUTE_XML - ATTRIBUTE_XML(getDecl()->getNameAsString(), "name") // string - CONTEXT_ATTRIBUTE_XML(getDecl()->getDeclContext()) -END_NODE_XML - -NODE_XML(TemplateTypeParmType, "TemplateTypeParmType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(TemplateSpecializationType, "TemplateSpecializationType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(ElaboratedType, "ElaboratedType") - ID_ATTRIBUTE_XML - ATTRIBUTE_ENUM_XML(getKeyword(), "keyword") - ENUM_XML(ETK_None, "none") - ENUM_XML(ETK_Typename, "typename") - ENUM_XML(ETK_Struct, "struct") - ENUM_XML(ETK_Union, "union") - ENUM_XML(ETK_Class, "class") - ENUM_XML(ETK_Enum, "enum") - END_ENUM_XML - TYPE_ATTRIBUTE_XML(getNamedType()) -END_NODE_XML - -NODE_XML(InjectedClassNameType, "InjectedClassNameType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(DependentNameType, "DependentNameType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(DependentTemplateSpecializationType, - "DependentTemplateSpecializationType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(ObjCInterfaceType, "ObjCInterfaceType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(ObjCObjectPointerType, "ObjCObjectPointerType") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(SubstTemplateTypeParmType, "SubstTemplateTypeParm") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(DependentSizedExtVectorType, "DependentSizedExtVector") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(UnresolvedUsingType, "UnresolvedUsing") - ID_ATTRIBUTE_XML -END_NODE_XML - -NODE_XML(DecltypeType, "Decltype") - ID_ATTRIBUTE_XML -END_NODE_XML - -//===----------------------------------------------------------------------===// -#undef NODE_XML -#undef ID_ATTRIBUTE_XML -#undef TYPE_ATTRIBUTE_XML -#undef CONTEXT_ATTRIBUTE_XML -#undef ATTRIBUTE_XML -#undef ATTRIBUTE_OPT_XML -#undef ATTRIBUTE_ENUM_XML -#undef ATTRIBUTE_ENUM_OPT_XML -#undef ENUM_XML -#undef END_ENUM_XML -#undef END_NODE_XML diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 02342c1a4710..e4997165cd11 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -14,7 +14,10 @@ #ifndef LLVM_CLANG_FRONTEND_UTILS_H #define LLVM_CLANG_FRONTEND_UTILS_H +#include "clang/Basic/Diagnostic.h" #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/Support/raw_ostream.h" namespace llvm { @@ -24,6 +27,7 @@ class Triple; namespace clang { class ASTConsumer; class CompilerInstance; +class CompilerInvocation; class Decl; class DependencyOutputOptions; class Diagnostic; @@ -85,12 +89,23 @@ void AttachDependencyFileGen(Preprocessor &PP, /// \param OutputPath - If non-empty, a path to write the header include /// information to, instead of writing to stderr. void AttachHeaderIncludeGen(Preprocessor &PP, bool ShowAllHeaders = false, - llvm::StringRef OutputPath = ""); + llvm::StringRef OutputPath = "", + bool ShowDepth = true); /// CacheTokens - Cache tokens for use with PCH. Note that this requires /// a seekable stream. void CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS); +/// createInvocationFromCommandLine - Construct a compiler invocation object for +/// a command line argument vector. +/// +/// \return A CompilerInvocation, or 0 if none was built for the given +/// argument vector. +CompilerInvocation * +createInvocationFromCommandLine(llvm::ArrayRef<const char *> Args, + llvm::IntrusiveRefCntPtr<Diagnostic> Diags = + llvm::IntrusiveRefCntPtr<Diagnostic>()); + } // end namespace clang #endif diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index 64687a18e2b6..1ee6953a12b2 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -18,6 +18,7 @@ namespace llvm { class StringRef; + template <typename T> class SmallVectorImpl; } namespace clang { class HeaderMap; @@ -121,11 +122,26 @@ public: /// LookupFile - Lookup the specified file in this search path, returning it /// if it exists or returning null if not. - const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS) const; + /// + /// \param Filename The file to look up relative to the search paths. + /// + /// \param HS The header search instance to search with. + /// + /// \param SearchPath If not NULL, will be set to the search path relative + /// to which the file was found. + /// + /// \param RelativePath If not NULL, will be set to the path relative to + /// SearchPath at which the file was found. This only differs from the + /// Filename for framework includes. + const FileEntry *LookupFile(llvm::StringRef Filename, HeaderSearch &HS, + llvm::SmallVectorImpl<char> *SearchPath, + llvm::SmallVectorImpl<char> *RelativePath) const; private: - const FileEntry *DoFrameworkLookup(llvm::StringRef Filename, - HeaderSearch &HS) const; + const FileEntry *DoFrameworkLookup( + llvm::StringRef Filename, HeaderSearch &HS, + llvm::SmallVectorImpl<char> *SearchPath, + llvm::SmallVectorImpl<char> *RelativePath) const; }; diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h index 8a5c83ecf495..e333840b6a9d 100644 --- a/include/clang/Lex/HeaderMap.h +++ b/include/clang/Lex/HeaderMap.h @@ -17,6 +17,7 @@ namespace llvm { class MemoryBuffer; class StringRef; + template <typename T> class SmallVectorImpl; } namespace clang { class FileEntry; @@ -47,6 +48,10 @@ public: /// LookupFile - Check to see if the specified relative filename is located in /// this HeaderMap. If so, open it and return its FileEntry. + /// If RawPath is not NULL and the file is found, RawPath will be set to the + /// raw path at which the file was found in the file system. For example, + /// for a search path ".." and a filename "../file.h" this would be + /// "../../file.h". const FileEntry *LookupFile(llvm::StringRef Filename, FileManager &FM) const; /// getFileName - Return the filename of the headermap. diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 30bd4f58549c..fec4dad1e73b 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -104,7 +104,7 @@ class HeaderSearch { /// consequtively. Requests for <x> search the current dir first, then each /// directory in SearchDirs, starting at SystemDirIdx, consequtively. If /// NoCurDirSearch is true, then the check for the file in the current - /// directory is supressed. + /// directory is suppressed. std::vector<DirectoryLookup> SearchDirs; unsigned SystemDirIdx; bool NoCurDirSearch; @@ -182,25 +182,43 @@ public: } /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, - /// return null on failure. isAngled indicates whether the file reference is - /// a <> reference. If successful, this returns 'UsedDir', the - /// DirectoryLookup member the file was found in, or null if not applicable. - /// If CurDir is non-null, the file was found in the specified directory - /// search location. This is used to implement #include_next. CurFileEnt, if - /// non-null, indicates where the #including file is, in case a relative - /// search is needed. + /// return null on failure. + /// + /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member + /// the file was found in, or null if not applicable. + /// + /// \param isAngled indicates whether the file reference is a <> reference. + /// + /// \param CurDir If non-null, the file was found in the specified directory + /// search location. This is used to implement #include_next. + /// + /// \param CurFileEnt If non-null, indicates where the #including file is, in + /// case a relative search is needed. + /// + /// \param SearchPath If non-null, will be set to the search path relative + /// to which the file was found. If the include path is absolute, SearchPath + /// will be set to an empty string. + /// + /// \param RelativePath If non-null, will be set to the path relative to + /// SearchPath at which the file was found. This only differs from the + /// Filename for framework includes. const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, - const FileEntry *CurFileEnt); + const FileEntry *CurFileEnt, + llvm::SmallVectorImpl<char> *SearchPath, + llvm::SmallVectorImpl<char> *RelativePath); /// LookupSubframeworkHeader - Look up a subframework for the specified /// #include file. For example, if #include'ing <HIToolbox/HIToolbox.h> from /// within ".../Carbon.framework/Headers/Carbon.h", check to see if HIToolbox /// is a subframework within Carbon.framework. If so, return the FileEntry /// for the designated file, otherwise return null. - const FileEntry *LookupSubframeworkHeader(llvm::StringRef Filename, - const FileEntry *RelativeFileEnt); + const FileEntry *LookupSubframeworkHeader( + llvm::StringRef Filename, + const FileEntry *RelativeFileEnt, + llvm::SmallVectorImpl<char> *SearchPath, + llvm::SmallVectorImpl<char> *RelativePath); /// LookupFrameworkCache - Look up the specified framework name in our /// framework cache, returning the DirectoryEntry it is in if we know, @@ -261,6 +279,17 @@ public: // Used by ASTReader. void setHeaderFileInfoForUID(HeaderFileInfo HFI, unsigned UID); + // Used by external tools + typedef std::vector<DirectoryLookup>::const_iterator search_dir_iterator; + search_dir_iterator search_dir_begin() const { return SearchDirs.begin(); } + search_dir_iterator search_dir_end() const { return SearchDirs.end(); } + unsigned search_dir_size() const { return SearchDirs.size(); } + + search_dir_iterator system_dir_begin() const { + return SearchDirs.begin() + SystemDirIdx; + } + search_dir_iterator system_dir_end() const { return SearchDirs.end(); } + void PrintStats(); private: diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h index 5fcb8eb2d1a4..7d2eb89c50bc 100644 --- a/include/clang/Lex/LexDiagnostic.h +++ b/include/clang/Lex/LexDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define LEXSTART #include "clang/Basic/DiagnosticLexKinds.inc" #undef DIAG diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index fc9a8de43482..7c3d863bd3d3 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -18,7 +18,6 @@ #include "clang/Basic/LangOptions.h" #include "llvm/ADT/SmallVector.h" #include <string> -#include <vector> #include <cassert> namespace clang { @@ -236,6 +235,20 @@ public: const SourceManager &SourceMgr, const LangOptions &Features, bool *Invalid = 0); + + /// getSpelling - This method is used to get the spelling of the + /// token at the given source location. If, as is usually true, it + /// is not necessary to copy any data, then the returned string may + /// not point into the provided buffer. + /// + /// This method lexes at the instantiation depth of the given + /// location and does not jump to the instantiation or spelling + /// location. + static llvm::StringRef getSpelling(SourceLocation loc, + llvm::SmallVectorImpl<char> &buffer, + const SourceManager &SourceMgr, + const LangOptions &Features, + bool *invalid = 0); /// MeasureTokenLength - Relex the token at the specified location and return /// its length in bytes in the input file. If the token needs cleaning (e.g. diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index bf2c06becdbf..dcaf4457cfa8 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -19,7 +19,6 @@ #include "llvm/ADT/SmallString.h" #include "llvm/Support/DataTypes.h" #include <cctype> -#include <string> namespace clang { diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 717c3008eca9..7c4cfb007233 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -17,7 +17,6 @@ #include "clang/Lex/Token.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" -#include <vector> #include <cassert> namespace clang { diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h index 5d5d67329059..95b00dfcf366 100644 --- a/include/clang/Lex/MultipleIncludeOpt.h +++ b/include/clang/Lex/MultipleIncludeOpt.h @@ -47,7 +47,7 @@ public: TheMacro = 0; } - /// Invalidate - Permenantly mark this file as not being suitable for the + /// Invalidate - Permanently mark this file as not being suitable for the /// include-file optimization. void Invalidate() { // If we have read tokens but have no controlling macro, the state-machine diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index b2a80a62985f..fd07a29f8e9d 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -75,12 +75,26 @@ public: /// /// \param EndLoc The location of the last token within the inclusion /// directive. + /// + /// \param SearchPath Contains the search path which was used to find the file + /// in the file system. If the file was found via an absolute include path, + /// SearchPath will be empty. For framework includes, the SearchPath and + /// RelativePath will be split up. For example, if an include of "Some/Some.h" + /// is found via the framework path + /// "path/to/Frameworks/Some.framework/Headers/Some.h", SearchPath will be + /// "path/to/Frameworks/Some.framework/Headers" and RelativePath will be + /// "Some.h". + /// + /// \param RelativePath The path relative to SearchPath, at which the include + /// file was found. This is equal to FileName except for framework includes. virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, llvm::StringRef FileName, bool IsAngled, const FileEntry *File, - SourceLocation EndLoc) { + SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { } /// EndOfMainFile - This callback is invoked when the end of the main file is @@ -188,11 +202,13 @@ public: llvm::StringRef FileName, bool IsAngled, const FileEntry *File, - SourceLocation EndLoc) { - First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc); - Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, - EndLoc); + SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath) { + First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, + EndLoc, SearchPath, RelativePath); + Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, File, + EndLoc, SearchPath, RelativePath); } virtual void EndOfMainFile() { diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h index 0b5a76ccfd6e..f6a97a0a90a4 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -15,7 +15,6 @@ #define LLVM_CLANG_PTHLEXER_H #include "clang/Lex/PreprocessorLexer.h" -#include <vector> namespace clang { diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index 8bd22369476e..c6ab35c19c1e 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -17,7 +17,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include <cassert> -#include <vector> namespace clang { class Preprocessor; diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index afd7ae1187cc..7be845549d4a 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -341,7 +341,9 @@ namespace clang { llvm::StringRef FileName, bool IsAngled, const FileEntry *File, - SourceLocation EndLoc); + SourceLocation EndLoc, + llvm::StringRef SearchPath, + llvm::StringRef RelativePath); }; } // end namespace clang diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 9005adc6ade6..616507a914a8 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -25,6 +25,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallVector.h" @@ -53,7 +54,7 @@ class PreprocessingRecord; /// single source file, and don't know anything about preprocessor-level issues /// like the #include stack, token expansion, etc. /// -class Preprocessor { +class Preprocessor : public llvm::RefCountedBase<Preprocessor> { Diagnostic *Diags; LangOptions Features; const TargetInfo &Target; @@ -217,6 +218,10 @@ class Preprocessor { /// previous macro value. llvm::DenseMap<IdentifierInfo*, std::vector<MacroInfo*> > PragmaPushMacroInfo; + /// \brief Instantiation source location for the last macro that expanded + /// to no tokens. + SourceLocation LastEmptyMacroInstantiationLoc; + // Various statistics we track for performance analysis. unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma; unsigned NumIf, NumElse, NumEndif; @@ -365,6 +370,12 @@ public: macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; + /// \brief Instantiation source location for the last macro that expanded + /// to no tokens. + SourceLocation getLastEmptyMacroInstantiationLoc() const { + return LastEmptyMacroInstantiationLoc; + } + const std::string &getPredefines() const { return Predefines; } /// setPredefines - Set the predefines for this Preprocessor. These /// predefines are automatically injected when parsing the main file. @@ -644,13 +655,26 @@ public: return Diags->Report(Tok.getLocation(), DiagID); } + /// getSpelling() - Return the 'spelling' of the token at the given + /// location; does not go up to the spelling location or down to the + /// instantiation location. + /// + /// \param buffer A buffer which will be used only if the token requires + /// "cleaning", e.g. if it contains trigraphs or escaped newlines + /// \param invalid If non-null, will be set \c true if an error occurs. + llvm::StringRef getSpelling(SourceLocation loc, + llvm::SmallVectorImpl<char> &buffer, + bool *invalid = 0) const { + return Lexer::getSpelling(loc, buffer, SourceMgr, Features, invalid); + } + /// 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. /// - /// \param Invalid If non-NULL, will be set \c true if an error occurs. + /// \param Invalid If non-null, will be set \c true if an error occurs. std::string getSpelling(const Token &Tok, bool *Invalid = 0) const { return Lexer::getSpelling(Tok, SourceMgr, Features, Invalid); } @@ -759,6 +783,38 @@ public: /// updating the token kind accordingly. IdentifierInfo *LookUpIdentifierInfo(Token &Identifier) const; +private: + llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons; + +public: + + // SetPoisonReason - Call this function to indicate the reason for + // poisoning an identifier. If that identifier is accessed while + // poisoned, then this reason will be used instead of the default + // "poisoned" diagnostic. + void SetPoisonReason(IdentifierInfo *II, unsigned DiagID); + + // HandlePoisonedIdentifier - Display reason for poisoned + // identifier. + void HandlePoisonedIdentifier(Token & Tok); + + void MaybeHandlePoisonedIdentifier(Token & Identifier) { + if(IdentifierInfo * II = Identifier.getIdentifierInfo()) { + if(II->isPoisoned()) { + HandlePoisonedIdentifier(Identifier); + } + } + } + +private: + /// Identifiers used for SEH handling in Borland. These are only + /// allowed in particular circumstances + IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block + IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression + IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally +public: + void PoisonSEHIdentifiers(bool Poison = true); // Borland + /// HandleIdentifier - This callback is invoked when the lexer reads an /// identifier and has filled in the tokens IdentifierInfo member. This /// callback potentially macro expands it or turns it into a named token (like @@ -782,13 +838,13 @@ public: /// read is the correct one. void HandleDirective(Token &Result); - /// CheckEndOfDirective - Ensure that the next token is a tok::eom token. If - /// not, emit a diagnostic and consume up until the eom. If EnableMacros is + /// CheckEndOfDirective - Ensure that the next token is a tok::eod token. If + /// not, emit a diagnostic and consume up until the eod. If EnableMacros is /// true, then we consider macros that expand to zero tokens as being ok. void CheckEndOfDirective(const char *Directive, bool EnableMacros = false); /// DiscardUntilEndOfDirective - Read and discard all tokens remaining on the - /// current line until the tok::eom token is found. + /// current line until the tok::eod token is found. void DiscardUntilEndOfDirective(); /// SawDateOrTime - This returns true if the preprocessor has seen a use of @@ -819,7 +875,9 @@ public: /// for system #include's or not (i.e. using <> instead of ""). const FileEntry *LookupFile(llvm::StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, - const DirectoryLookup *&CurDir); + const DirectoryLookup *&CurDir, + llvm::SmallVectorImpl<char> *SearchPath, + llvm::SmallVectorImpl<char> *RelativePath); /// GetCurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to @@ -839,12 +897,12 @@ public: /// /// This code concatenates and consumes tokens up to the '>' token. It /// returns false if the > was found, otherwise it returns true if it finds - /// and consumes the EOM marker. + /// and consumes the EOD marker. bool ConcatenateIncludeName(llvm::SmallString<128> &FilenameBuffer, SourceLocation &End); /// LexOnOffSwitch - Lex an on-off-switch (C99 6.10.6p2) and verify that it is - /// followed by EOM. Return true if the token is not a valid on-off-switch. + /// followed by EOD. Return true if the token is not a valid on-off-switch. bool LexOnOffSwitch(tok::OnOffSwitch &OOS); private: @@ -875,7 +933,7 @@ private: void ReleaseMacroInfo(MacroInfo* MI); /// ReadMacroName - Lex and validate a macro name, which occurs after a - /// #define or #undef. This emits a diagnostic, sets the token kind to eom, + /// #define or #undef. This emits a diagnostic, sets the token kind to eod, /// and discards the rest of the macro line if the macro name is invalid. void ReadMacroName(Token &MacroNameTok, char isDefineUndef = 0); diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index d8332938a7ed..7bf041df974f 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -17,7 +17,6 @@ #include "clang/Lex/MultipleIncludeOpt.h" #include "clang/Lex/Token.h" #include "llvm/ADT/SmallVector.h" -#include <string> namespace clang { @@ -36,7 +35,7 @@ protected: //===--------------------------------------------------------------------===// /// ParsingPreprocessorDirective - This is true when parsing #XXX. This turns - /// '\n' into a tok::eom token. + /// '\n' into a tok::eod token. bool ParsingPreprocessorDirective; /// ParsingFilename - True after #include: this turns <xx> into a @@ -131,7 +130,7 @@ public: /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and /// (potentially) macro expand the filename. If the sequence parsed is not - /// lexically legal, emit a diagnostic and return a result EOM token. + /// lexically legal, emit a diagnostic and return a result EOD token. void LexIncludeFilename(Token &Result); /// setParsingPreprocessorDirective - Inform the lexer whether or not diff --git a/include/clang/Makefile b/include/clang/Makefile index d6b9844285d2..a7be0319e5fa 100644 --- a/include/clang/Makefile +++ b/include/clang/Makefile @@ -8,9 +8,12 @@ install-local:: $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir) $(Verb) if test -d "$(PROJ_SRC_ROOT)/tools/clang/include/clang" ; then \ cd $(PROJ_SRC_ROOT)/tools/clang/include && \ - for hdr in `find clang -type f '!' '(' -name '*~' \ - -o -name '.#*' -o -name '*.in' -o -name '*.txt' \ - -o -name 'Makefile' -o -name '*.td' -o -name '*.orig' ')' -print \ + for hdr in `find clang -type f \ + '(' -name LICENSE.TXT \ + -o -name '*.def' \ + -o -name '*.h' \ + -o -name '*.inc' \ + ')' -print \ | grep -v CVS | grep -v .svn | grep -v .dir` ; do \ instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \ if test \! -d "$$instdir" ; then \ @@ -23,7 +26,12 @@ install-local:: ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) $(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/clang/include/clang" ; then \ cd $(PROJ_OBJ_ROOT)/tools/clang/include && \ - for hdr in `find clang -type f '!' '(' -name 'Makefile' ')' -print \ + for hdr in `find clang -type f \ + '(' -name LICENSE.TXT \ + -o -name '*.def' \ + -o -name '*.h' \ + -o -name '*.inc' \ + ')' -print \ | grep -v CVS | grep -v .tmp | grep -v .dir` ; do \ $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \ done ; \ diff --git a/include/clang/Parse/ParseDiagnostic.h b/include/clang/Parse/ParseDiagnostic.h index f640b37c1982..c50ac92f6e8d 100644 --- a/include/clang/Parse/ParseDiagnostic.h +++ b/include/clang/Parse/ParseDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define PARSESTART #include "clang/Basic/DiagnosticParseKinds.inc" #undef DIAG diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 758792097639..3fd9844368ee 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -22,7 +22,6 @@ #include "llvm/Support/PrettyStackTrace.h" #include "llvm/ADT/OwningPtr.h" #include <stack> -#include <list> namespace clang { class PragmaHandler; @@ -33,6 +32,8 @@ namespace clang { class PragmaUnusedHandler; class ColonProtectionRAIIObject; class InMessageExpressionRAIIObject; + class PoisonSEHIdentifiersRAIIObject; + class VersionTuple; /// PrettyStackTraceParserEntry - If a crash happens while the parser is active, /// an entry is printed for it. @@ -75,8 +76,8 @@ class Parser : public CodeCompletionHandler { friend class PragmaUnusedHandler; friend class ColonProtectionRAIIObject; friend class InMessageExpressionRAIIObject; + friend class PoisonSEHIdentifiersRAIIObject; friend class ParenBraceBracketBalancer; - PrettyStackTraceParserEntry CrashInfo; Preprocessor &PP; @@ -103,6 +104,12 @@ class Parser : public CodeCompletionHandler { unsigned NumCachedScopes; Scope *ScopeCache[ScopeCacheSize]; + /// Identifiers used for SEH handling in Borland. These are only + /// allowed in particular circumstances + IdentifierInfo *Ident__exception_code, *Ident___exception_code, *Ident_GetExceptionCode; // __except block + IdentifierInfo *Ident__exception_info, *Ident___exception_info, *Ident_GetExceptionInfo; // __except filter expression + IdentifierInfo *Ident__abnormal_termination, *Ident___abnormal_termination, *Ident_AbnormalTermination; // __finally + /// Ident_super - IdentifierInfo for "super", to support fast /// comparison. IdentifierInfo *Ident_super; @@ -112,6 +119,18 @@ class Parser : public CodeCompletionHandler { IdentifierInfo *Ident_vector; IdentifierInfo *Ident_pixel; + /// \brief Identifier for "introduced". + IdentifierInfo *Ident_introduced; + + /// \brief Identifier for "deprecated". + IdentifierInfo *Ident_deprecated; + + /// \brief Identifier for "obsoleted". + IdentifierInfo *Ident_obsoleted; + + /// \brief Identifier for "unavailable". + IdentifierInfo *Ident_unavailable; + /// C++0x contextual keywords. mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; @@ -120,6 +139,7 @@ class Parser : public CodeCompletionHandler { llvm::OwningPtr<PragmaHandler> GCCVisibilityHandler; llvm::OwningPtr<PragmaHandler> OptionsHandler; llvm::OwningPtr<PragmaHandler> PackHandler; + llvm::OwningPtr<PragmaHandler> MSStructHandler; llvm::OwningPtr<PragmaHandler> UnusedHandler; llvm::OwningPtr<PragmaHandler> WeakHandler; llvm::OwningPtr<PragmaHandler> FPContractHandler; @@ -137,7 +157,7 @@ class Parser : public CodeCompletionHandler { /// ColonProtectionRAIIObject RAII object. bool ColonIsSacred; - /// \brief When true, we are directly inside an Ojective-C messsage + /// \brief When true, we are directly inside an Objective-C messsage /// send expression. /// /// This is managed by the \c InMessageExpressionRAIIObject class, and @@ -148,7 +168,7 @@ class Parser : public CodeCompletionHandler { unsigned TemplateParameterDepth; /// Factory object for creating AttributeList objects. - AttributeList::Factory AttrFactory; + AttributeFactory AttrFactory; public: Parser(Preprocessor &PP, Sema &Actions); @@ -380,6 +400,24 @@ private: static void setTypeAnnotation(Token &Tok, ParsedType T) { Tok.setAnnotationValue(T.getAsOpaquePtr()); } + + /// \brief Read an already-translated primary expression out of an annotation + /// token. + static ExprResult getExprAnnotation(Token &Tok) { + if (Tok.getAnnotationValue()) + return ExprResult((Expr *)Tok.getAnnotationValue()); + + return ExprResult(true); + } + + /// \brief Set the primary expression corresponding to the given annotation + /// token. + static void setExprAnnotation(Token &Tok, ExprResult ER) { + if (ER.isInvalid()) + Tok.setAnnotationValue(0); + else + Tok.setAnnotationValue(ER.get()); + } /// TryAnnotateTypeOrScopeToken - If the current token position is on a /// typename (possibly qualified in C++) or a C++ scope specifier not followed @@ -678,7 +716,7 @@ private: /// LateParsedDeclarationsContainer - During parsing of a top (non-nested) /// C++ class, its method declarations that contain parts that won't be - /// parsed until after the definiton is completed (C++ [class.mem]p2), + /// parsed until after the definition is completed (C++ [class.mem]p2), /// the method declarations and possibly attached inline definitions /// will be stored here with the tokens that will be parsed to create those entities. typedef llvm::SmallVector<LateParsedDeclaration*, 2> LateParsedDeclarationsContainer; @@ -792,10 +830,9 @@ private: ParsingDeclRAIIObject ParsingRAII; public: - ParsingDeclSpec(Parser &P) : ParsingRAII(P) {} - ParsingDeclSpec(ParsingDeclRAIIObject &RAII) : ParsingRAII(RAII) {} + ParsingDeclSpec(Parser &P) : DeclSpec(P.AttrFactory), ParsingRAII(P) {} ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) - : ParsingRAII(P, RAII) {} + : DeclSpec(P.AttrFactory), ParsingRAII(P, RAII) {} void complete(Decl *D) { ParsingRAII.complete(D); @@ -908,6 +945,27 @@ private: SourceRange getSourceRange() const; }; + /// \brief Contains a late templated function. + /// Will be parsed at the end of the translation unit. + struct LateParsedTemplatedFunction { + explicit LateParsedTemplatedFunction(Parser* P, Decl *MD) + : D(MD) {} + + CachedTokens Toks; + + /// \brief The template function declaration to be late parsed. + Decl *D; + }; + + void LexTemplateFunctionForLateParsing(CachedTokens &Toks); + void ParseLateTemplatedFuncDef(LateParsedTemplatedFunction &LMT); + typedef llvm::DenseMap<const FunctionDecl*, LateParsedTemplatedFunction*> + LateParsedTemplateMapT; + LateParsedTemplateMapT LateParsedTemplateMap; + + static void LateTemplateParserCallback(void *P, const FunctionDecl *FD); + void LateTemplateParser(const FunctionDecl *FD); + Sema::ParsingClassState PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass); void DeallocateParsedClasses(ParsingClass *Class); @@ -934,6 +992,9 @@ private: //===--------------------------------------------------------------------===// // C99 6.9: External Definitions. struct ParsedAttributesWithRange : ParsedAttributes { + ParsedAttributesWithRange(AttributeFactory &factory) + : ParsedAttributes(factory) {} + SourceRange Range; }; @@ -992,13 +1053,21 @@ private: bool isTokIdentifier_in() const; - ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, bool IsParameter); + /// \brief The context in which we are parsing an Objective-C type name. + enum ObjCTypeNameContext { + OTN_ResultType, + OTN_ParameterType + }; + + ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, ObjCTypeNameContext Context); void ParseObjCMethodRequirement(); Decl *ParseObjCMethodPrototype(Decl *classOrCat, - tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); + tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword, + bool MethodDefinition = true); Decl *ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, Decl *classDecl, - tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); + tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword, + bool MethodDefinition=true); void ParseObjCPropertyAttribute(ObjCDeclSpec &DS, Decl *ClassDecl); Decl *ParseObjCMethodDefinition(); @@ -1016,14 +1085,14 @@ private: ExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); ExprResult ParseRHSOfBinaryExpression(ExprResult LHS, - prec::Level MinPrec); + prec::Level MinPrec); ExprResult ParseCastExpression(bool isUnaryExpression, - bool isAddressOfOperand, - bool &NotCastExpr, - ParsedType TypeOfCast); + bool isAddressOfOperand, + bool &NotCastExpr, + ParsedType TypeOfCast); ExprResult ParseCastExpression(bool isUnaryExpression, - bool isAddressOfOperand = false, - ParsedType TypeOfCast = ParsedType()); + bool isAddressOfOperand = false, + ParsedType TypeOfCast = ParsedType()); /// Returns true if the next token would start a postfix-expression /// suffix. @@ -1035,10 +1104,10 @@ private: } ExprResult ParsePostfixExpressionSuffix(ExprResult LHS); - ExprResult ParseSizeofAlignofExpression(); + ExprResult ParseUnaryExprOrTypeTraitExpression(); ExprResult ParseBuiltinPrimaryExpression(); - ExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, + ExprResult ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, bool &isCastExpr, ParsedType &CastTy, SourceRange &CastRange); @@ -1079,6 +1148,8 @@ private: ExprResult ParseStringLiteralExpression(); + ExprResult ParseGenericSelectionExpression(); + //===--------------------------------------------------------------------===// // C++ Expressions ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); @@ -1086,7 +1157,8 @@ private: bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, ParsedType ObjectType, bool EnteringContext, - bool *MayBePseudoDestructor = 0); + bool *MayBePseudoDestructor = 0, + bool IsTypename = false); //===--------------------------------------------------------------------===// // C++ 5.2p1: C++ Casts @@ -1114,11 +1186,18 @@ private: //===--------------------------------------------------------------------===// // C++ 15: C++ Throw Expression ExprResult ParseThrowExpression(); + + ExceptionSpecificationType MaybeParseExceptionSpecification( + SourceRange &SpecificationRange, + llvm::SmallVectorImpl<ParsedType> &DynamicExceptions, + llvm::SmallVectorImpl<SourceRange> &DynamicExceptionRanges, + ExprResult &NoexceptExpr); + // EndLoc is filled with the location of the last token of the specification. - bool ParseExceptionSpecification(SourceLocation &EndLoc, - llvm::SmallVectorImpl<ParsedType> &Exns, - llvm::SmallVectorImpl<SourceRange> &Ranges, - bool &hasAnyExceptionSpec); + ExceptionSpecificationType ParseDynamicExceptionSpecification( + SourceRange &SpecificationRange, + llvm::SmallVectorImpl<ParsedType> &Exceptions, + llvm::SmallVectorImpl<SourceRange> &Ranges); //===--------------------------------------------------------------------===// // C++0x 8: Function declaration trailing-return-type @@ -1205,11 +1284,14 @@ private: } StmtResult ParseStatementOrDeclaration(StmtVector& Stmts, bool OnlyStatement = false); + StmtResult ParseExprStatement(ParsedAttributes &Attrs); StmtResult ParseLabeledStatement(ParsedAttributes &Attr); - StmtResult ParseCaseStatement(ParsedAttributes &Attr); + StmtResult ParseCaseStatement(ParsedAttributes &Attr, + bool MissingCase = false, + ExprResult Expr = ExprResult()); StmtResult ParseDefaultStatement(ParsedAttributes &Attr); StmtResult ParseCompoundStatement(ParsedAttributes &Attr, - bool isStmtExpr = false); + bool isStmtExpr = false); StmtResult ParseCompoundStatementBody(bool isStmtExpr = false); bool ParseParenExprOrCondition(ExprResult &ExprResult, Decl *&DeclResult, @@ -1238,6 +1320,14 @@ private: StmtResult ParseCXXCatchBlock(); //===--------------------------------------------------------------------===// + // MS: SEH Statements and Blocks + + StmtResult ParseSEHTryBlock(ParsedAttributes &Attr); + StmtResult ParseSEHTryBlockCommon(SourceLocation Loc); + StmtResult ParseSEHExceptBlock(SourceLocation Loc); + StmtResult ParseSEHFinallyBlock(SourceLocation Loc); + + //===--------------------------------------------------------------------===// // Objective-C Statements StmtResult ParseObjCAtStatement(SourceLocation atLoc); @@ -1258,6 +1348,15 @@ private: DSC_top_level // top-level/namespace declaration context }; + /// Information on a C++0x for-range-initializer found while parsing a + /// declaration which turns out to be a for-range-declaration. + struct ForRangeInit { + SourceLocation ColonLoc; + ExprResult RangeExpr; + + bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); } + }; + DeclGroupPtrTy ParseDeclaration(StmtVector &Stmts, unsigned Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs); @@ -1265,14 +1364,19 @@ private: unsigned Context, SourceLocation &DeclEnd, ParsedAttributes &attrs, - bool RequireSemi); + bool RequireSemi, + ForRangeInit *FRI = 0); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, bool AllowFunctionDefinitions, - SourceLocation *DeclEnd = 0); + SourceLocation *DeclEnd = 0, + ForRangeInit *FRI = 0); Decl *ParseDeclarationAfterDeclarator(Declarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); - Decl *ParseFunctionStatementBody(Decl *Decl); - Decl *ParseFunctionTryBlock(Decl *Decl); + bool ParseAttributesAfterDeclarator(Declarator &D); + Decl *ParseDeclarationAfterDeclaratorAndAttributes(Declarator &D, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope); + Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope); /// \brief When in code-completion, skip parsing of the function/method body /// unless the body contains the code-completion point. @@ -1296,7 +1400,8 @@ private: void ParseSpecifierQualifierList(DeclSpec &DS); - void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, bool IsParameter); + void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, + ObjCTypeNameContext Context); void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), @@ -1470,7 +1575,7 @@ private: TypeResult ParseTypeName(SourceRange *Range = 0, Declarator::TheContext Context - = Declarator::TypeNameContext); + = Declarator::TypeNameContext); void ParseBlockId(); void ProhibitAttributes(ParsedAttributesWithRange &attrs) { @@ -1481,10 +1586,10 @@ private: void MaybeParseGNUAttributes(Declarator &D) { if (Tok.is(tok::kw___attribute)) { - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); SourceLocation endLoc; ParseGNUAttributes(attrs, &endLoc); - D.addAttributes(attrs.getList(), endLoc); + D.takeAttributes(attrs, endLoc); } } void MaybeParseGNUAttributes(ParsedAttributes &attrs, @@ -1497,18 +1602,18 @@ private: void MaybeParseCXX0XAttributes(Declarator &D) { if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); SourceLocation endLoc; ParseCXX0XAttributes(attrs, &endLoc); - D.addAttributes(attrs.getList(), endLoc); + D.takeAttributes(attrs, endLoc); } } void MaybeParseCXX0XAttributes(ParsedAttributes &attrs, SourceLocation *endLoc = 0) { if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { - ParsedAttributesWithRange attrsWithRange; + ParsedAttributesWithRange attrsWithRange(AttrFactory); ParseCXX0XAttributes(attrsWithRange, endLoc); - attrs.append(attrsWithRange.getList()); + attrs.takeAllFrom(attrsWithRange); } } void MaybeParseCXX0XAttributes(ParsedAttributesWithRange &attrs, @@ -1530,6 +1635,13 @@ private: void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs); void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLAttributes(ParsedAttributes &attrs); + void ParseOpenCLQualifiers(DeclSpec &DS); + + VersionTuple ParseVersionTuple(SourceRange &Range); + void ParseAvailabilityAttribute(IdentifierInfo &Availability, + SourceLocation AvailabilityLoc, + ParsedAttributes &attrs, + SourceLocation *endLoc); void ParseTypeofSpecifier(DeclSpec &DS); void ParseDecltypeSpecifier(DeclSpec &DS); @@ -1539,8 +1651,7 @@ private: VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const; void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS); - ClassVirtSpecifiers::Specifier isCXX0XClassVirtSpecifier() const; - void ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS); + bool isCXX0XFinalKeyword() const; /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to /// enter a new C++ declarator scope and exit it when the function is @@ -1624,8 +1735,7 @@ private: //===--------------------------------------------------------------------===// // C++ 9: classes [class] and C structs/unions. - TypeResult ParseClassName(SourceLocation &EndLocation, - CXXScopeSpec *SS = 0); + TypeResult ParseClassName(SourceLocation &EndLocation, CXXScopeSpec &SS); void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), @@ -1696,18 +1806,18 @@ private: bool ParseTemplateIdAfterTemplateName(TemplateTy Template, SourceLocation TemplateNameLoc, - const CXXScopeSpec *SS, + const CXXScopeSpec &SS, bool ConsumeLastToken, SourceLocation &LAngleLoc, TemplateArgList &TemplateArgs, SourceLocation &RAngleLoc); bool AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, - const CXXScopeSpec *SS, + CXXScopeSpec &SS, UnqualifiedId &TemplateName, SourceLocation TemplateKWLoc = SourceLocation(), bool AllowTypeAnnotation = true); - void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); + void AnnotateTemplateIdTokenAsType(); bool IsTemplateArgumentList(unsigned Skip = 0); bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); ParsedTemplateArgument ParseTemplateTemplateArgument(); @@ -1722,6 +1832,11 @@ private: ExprResult ParseBinaryTypeTrait(); //===--------------------------------------------------------------------===// + // Embarcadero: Arary and Expression Traits + ExprResult ParseArrayTypeTrait(); + ExprResult ParseExpressionTrait(); + + //===--------------------------------------------------------------------===// // Preprocessor code-completion pass-through virtual void CodeCompleteDirective(bool InConditional); virtual void CodeCompleteInConditionalExclusion(); diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h index 2b5f88ccee9d..6b33183166f8 100644 --- a/include/clang/Rewrite/FrontendActions.h +++ b/include/clang/Rewrite/FrontendActions.h @@ -11,8 +11,6 @@ #define LLVM_CLANG_REWRITE_FRONTENDACTIONS_H #include "clang/Frontend/FrontendAction.h" -#include <string> -#include <vector> namespace clang { class FixItRewriter; diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h index b3d4035628ee..7861e9992891 100644 --- a/include/clang/Rewrite/Rewriter.h +++ b/include/clang/Rewrite/Rewriter.h @@ -22,7 +22,6 @@ #include <cstring> #include <map> #include <string> -#include <vector> namespace llvm { class raw_ostream; } @@ -58,7 +57,8 @@ public: llvm::raw_ostream &write(llvm::raw_ostream &) const; /// RemoveText - Remove the specified text. - void RemoveText(unsigned OrigOffset, unsigned Size); + void RemoveText(unsigned OrigOffset, unsigned Size, + bool removeLineIfEmpty = false); /// InsertText - Insert some text at the specified point, where the offset in /// the buffer is specified relative to the original SourceBuffer. The @@ -129,6 +129,23 @@ class Rewriter { const LangOptions *LangOpts; std::map<FileID, RewriteBuffer> RewriteBuffers; public: + struct RewriteOptions { + /// \brief Given a source range, true to include previous inserts at the + /// beginning of the range as part of the range itself (true by default). + bool IncludeInsertsAtBeginOfRange; + /// \brief Given a source range, true to include previous inserts at the + /// end of the range as part of the range itself (true by default). + bool IncludeInsertsAtEndOfRange; + /// \brief If true and removing some text leaves a blank line + /// also remove the empty line (false by default). + bool RemoveLineIfEmpty; + + RewriteOptions() + : IncludeInsertsAtBeginOfRange(true), + IncludeInsertsAtEndOfRange(true), + RemoveLineIfEmpty(false) { } + }; + typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator; explicit Rewriter(SourceManager &SM, const LangOptions &LO) @@ -150,8 +167,10 @@ public: /// getRangeSize - Return the size in bytes of the specified range if they /// are in the same file. If not, this returns -1. - int getRangeSize(SourceRange Range) const; - int getRangeSize(const CharSourceRange &Range) const; + int getRangeSize(SourceRange Range, + RewriteOptions opts = RewriteOptions()) const; + int getRangeSize(const CharSourceRange &Range, + RewriteOptions opts = RewriteOptions()) const; /// getRewrittenText - Return the rewritten form of the text in the specified /// range. If the start or end of the range was unrewritable or if they are @@ -176,6 +195,10 @@ public: return InsertText(Loc, Str); } + /// \brief Insert the specified string after the token in the + /// specified location. + bool InsertTextAfterToken(SourceLocation Loc, llvm::StringRef Str); + /// InsertText - Insert the specified string at the specified location in the /// original buffer. This method returns true (and does nothing) if the input /// location was not rewritable, false otherwise. Text is @@ -186,7 +209,19 @@ public: } /// RemoveText - Remove the specified text region. - bool RemoveText(SourceLocation Start, unsigned Length); + bool RemoveText(SourceLocation Start, unsigned Length, + RewriteOptions opts = RewriteOptions()); + + /// \brief Remove the specified text region. + bool RemoveText(CharSourceRange range, + RewriteOptions opts = RewriteOptions()) { + return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); + } + + /// \brief Remove the specified text region. + bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) { + return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); + } /// ReplaceText - This method replaces a range of characters in the input /// buffer with a new string. This is effectively a combined "remove/insert" @@ -194,11 +229,37 @@ public: bool ReplaceText(SourceLocation Start, unsigned OrigLength, llvm::StringRef NewStr); + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + bool ReplaceText(SourceRange range, llvm::StringRef NewStr) { + return ReplaceText(range.getBegin(), getRangeSize(range), NewStr); + } + + /// ReplaceText - This method replaces a range of characters in the input + /// buffer with a new string. This is effectively a combined "remove/insert" + /// operation. + bool ReplaceText(SourceRange range, SourceRange replacementRange); + /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty /// printer to generate the replacement code. This returns true if the input /// could not be rewritten, or false if successful. bool ReplaceStmt(Stmt *From, Stmt *To); + /// \brief Increase indentation for the lines between the given source range. + /// To determine what the indentation should be, 'parentIndent' is used + /// that should be at a source location with an indentation one degree + /// lower than the given range. + bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent); + bool IncreaseIndentation(SourceRange range, SourceLocation parentIndent) { + return IncreaseIndentation(CharSourceRange::getTokenRange(range), + parentIndent); + } + + /// ConvertToString converts statement 'From' to a string using the + /// pretty printer. + std::string ConvertToString(Stmt *From); + /// getEditBuffer - This is like getRewriteBufferFor, but always returns a /// buffer, and allows you to write on it directly. This is useful if you /// want efficient low-level access to apis for scribbling on one specific diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 45ee579a02d3..72cd47589f91 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -16,14 +16,33 @@ #define LLVM_CLANG_SEMA_ATTRLIST_H #include "llvm/Support/Allocator.h" -#include "clang/Sema/Ownership.h" +#include "llvm/ADT/SmallVector.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/VersionTuple.h" #include <cassert> namespace clang { + class ASTContext; class IdentifierInfo; class Expr; +/// \brief Represents information about a change in availability for +/// an entity, which is part of the encoding of the 'availability' +/// attribute. +struct AvailabilityChange { + /// \brief The location of the keyword indicating the kind of change. + SourceLocation KeywordLoc; + + /// \brief The version number at which the change occurred. + VersionTuple Version; + + /// \brief The source range covering the version number. + SourceRange VersionRange; + + /// \brief Determine whether this availability change is valid. + bool isValid() const { return !Version.empty(); } +}; + /// AttributeList - Represents GCC's __attribute__ declaration. There are /// 4 forms of this construct...they are: /// @@ -32,52 +51,102 @@ namespace clang { /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. /// -class AttributeList { -public: - class Factory; +class AttributeList { // TODO: This should really be called ParsedAttribute private: IdentifierInfo *AttrName; - SourceLocation AttrLoc; IdentifierInfo *ScopeName; - SourceLocation ScopeLoc; IdentifierInfo *ParmName; + SourceLocation AttrLoc; + SourceLocation ScopeLoc; SourceLocation ParmLoc; - Expr **Args; - unsigned NumArgs; - AttributeList *Next; - bool DeclspecAttribute, CXX0XAttribute; + + /// The number of expression arguments this attribute has. + /// The expressions themselves are stored after the object. + unsigned NumArgs : 16; + + /// True if Microsoft style: declspec(foo). + unsigned DeclspecAttribute : 1; + + /// True if C++0x-style: [[foo]]. + unsigned CXX0XAttribute : 1; /// True if already diagnosed as invalid. - mutable bool Invalid; + mutable unsigned Invalid : 1; + + /// True if this has the extra information associated with an + /// availability attribute. + unsigned IsAvailability : 1; + + /// \brief The location of the 'unavailable' keyword in an + /// availability attribute. + SourceLocation UnavailableLoc; + + /// The next attribute in the current position. + AttributeList *NextInPosition; + + /// The next attribute allocated in the current Pool. + AttributeList *NextInPool; + + Expr **getArgsBuffer() { + return reinterpret_cast<Expr**>(this+1); + } + Expr * const *getArgsBuffer() const { + return reinterpret_cast<Expr* const *>(this+1); + } + + enum AvailabilitySlot { + IntroducedSlot, DeprecatedSlot, ObsoletedSlot + }; + + AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { + return reinterpret_cast<AvailabilityChange*>(this+1)[index]; + } + const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { + return reinterpret_cast<const AvailabilityChange*>(this+1)[index]; + } AttributeList(const AttributeList &); // DO NOT IMPLEMENT void operator=(const AttributeList &); // DO NOT IMPLEMENT void operator delete(void *); // DO NOT IMPLEMENT ~AttributeList(); // DO NOT IMPLEMENT - AttributeList(llvm::BumpPtrAllocator &Alloc, - IdentifierInfo *AttrName, SourceLocation AttrLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - IdentifierInfo *ParmName, SourceLocation ParmLoc, - Expr **args, unsigned numargs, - bool declspec, bool cxx0x); + + size_t allocated_size() const; + + AttributeList(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec, bool cxx0x) + : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), + AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc), + NumArgs(numArgs), + DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false), + IsAvailability(false), NextInPosition(0), NextInPool(0) { + if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); + } + + AttributeList(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, + bool declspec, bool cxx0x) + : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), + AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc), + NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), + Invalid(false), IsAvailability(true), UnavailableLoc(unavailable), + NextInPosition(0), NextInPool(0) { + new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); + new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); + new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); + } + + friend class AttributePool; + friend class AttributeFactory; + public: - class Factory { - llvm::BumpPtrAllocator Alloc; - public: - Factory() {} - ~Factory() {} - AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - IdentifierInfo *ParmName, SourceLocation ParmLoc, - Expr **args, unsigned numargs, bool declspec = false, bool cxx0x = false) { - AttributeList *Mem = Alloc.Allocate<AttributeList>(); - new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc, - ParmName, ParmLoc, args, numargs, - declspec, cxx0x); - return Mem; - } - }; - enum Kind { // Please keep this list alphabetized. AT_IBAction, // Clang-specific. AT_IBOutlet, // Clang-specific. @@ -88,6 +157,7 @@ public: AT_always_inline, AT_analyzer_noreturn, AT_annotate, + AT_availability, // Clang-specific AT_base_check, AT_blocks, AT_carries_dependency, @@ -125,6 +195,7 @@ public: AT_nothrow, AT_nsobject, AT_objc_exception, + AT_objc_method_family, AT_cf_returns_not_retained, // Clang-specific. AT_cf_returns_retained, // Clang-specific. AT_ns_returns_not_retained, // Clang-specific. @@ -134,6 +205,7 @@ public: AT_ns_consumed, // Clang-specific. AT_ns_consumes_self, // Clang-specific. AT_objc_gc, + AT_opencl_image_access, // OpenCL-specific. AT_opencl_kernel_function, // OpenCL-specific. AT_overloadable, // Clang-specific. AT_ownership_holds, // Clang-specific. @@ -141,6 +213,7 @@ public: AT_ownership_takes, // Clang-specific. AT_packed, AT_pascal, + AT_pcs, // ARM specific AT_pure, AT_regparm, AT_section, @@ -162,6 +235,7 @@ public: AT_weak_import, AT_reqd_wg_size, AT_init_priority, + AT_MsStruct, IgnoredAttribute, UnknownAttribute }; @@ -185,23 +259,27 @@ public: Kind getKind() const { return getKind(getName()); } static Kind getKind(const IdentifierInfo *Name); - AttributeList *getNext() const { return Next; } - void setNext(AttributeList *N) { Next = N; } + AttributeList *getNext() const { return NextInPosition; } + void setNext(AttributeList *N) { NextInPosition = N; } /// getNumArgs - Return the number of actual arguments to this attribute. unsigned getNumArgs() const { return NumArgs; } + /// hasParameterOrArguments - Return true if this attribute has a parameter, + /// or has a non empty argument expression list. + bool hasParameterOrArguments() const { return ParmName || NumArgs; } + /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return Args[Arg]; + return getArgsBuffer()[Arg]; } class arg_iterator { - Expr** X; + Expr * const *X; unsigned Idx; public: - arg_iterator(Expr** x, unsigned idx) : X(x), Idx(idx) {} + arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {} arg_iterator& operator++() { ++Idx; @@ -228,14 +306,167 @@ public: }; arg_iterator arg_begin() const { - return arg_iterator(Args, 0); + return arg_iterator(getArgsBuffer(), 0); } arg_iterator arg_end() const { - return arg_iterator(Args, NumArgs); + return arg_iterator(getArgsBuffer(), NumArgs); + } + + const AvailabilityChange &getAvailabilityIntroduced() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return getAvailabilitySlot(IntroducedSlot); + } + + const AvailabilityChange &getAvailabilityDeprecated() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return getAvailabilitySlot(DeprecatedSlot); + } + + const AvailabilityChange &getAvailabilityObsoleted() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return getAvailabilitySlot(ObsoletedSlot); + } + + SourceLocation getUnavailableLoc() const { + assert(getKind() == AT_availability && "Not an availability attribute"); + return UnavailableLoc; } }; +/// A factory, from which one makes pools, from which one creates +/// individual attributes which are deallocated with the pool. +/// +/// Note that it's tolerably cheap to create and destroy one of +/// these as long as you don't actually allocate anything in it. +class AttributeFactory { +public: + enum { + /// The required allocation size of an availability attribute, + /// which we want to ensure is a multiple of sizeof(void*). + AvailabilityAllocSize = + sizeof(AttributeList) + + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1) + / sizeof(void*) * sizeof(void*)) + }; + +private: + enum { + /// The number of free lists we want to be sure to support + /// inline. This is just enough that availability attributes + /// don't surpass it. It's actually very unlikely we'll see an + /// attribute that needs more than that; on x86-64 you'd need 10 + /// expression arguments, and on i386 you'd need 19. + InlineFreeListsCapacity = + 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) + }; + + llvm::BumpPtrAllocator Alloc; + + /// Free lists. The index is determined by the following formula: + /// (size - sizeof(AttributeList)) / sizeof(void*) + llvm::SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; + + // The following are the private interface used by AttributePool. + friend class AttributePool; + + /// Allocate an attribute of the given size. + void *allocate(size_t size); + + /// Reclaim all the attributes in the given pool chain, which is + /// non-empty. Note that the current implementation is safe + /// against reclaiming things which were not actually allocated + /// with the allocator, although of course it's important to make + /// sure that their allocator lives at least as long as this one. + void reclaimPool(AttributeList *head); + +public: + AttributeFactory(); + ~AttributeFactory(); +}; + +class AttributePool { + AttributeFactory &Factory; + AttributeList *Head; + + void *allocate(size_t size) { + return Factory.allocate(size); + } + + AttributeList *add(AttributeList *attr) { + // We don't care about the order of the pool. + attr->NextInPool = Head; + Head = attr; + return attr; + } + + void takePool(AttributeList *pool); + +public: + /// Create a new pool for a factory. + AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {} + + /// Move the given pool's allocations to this pool. + AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { + pool.Head = 0; + } + + AttributeFactory &getFactory() const { return Factory; } + + void clear() { + if (Head) { + Factory.reclaimPool(Head); + Head = 0; + } + } + + /// Take the given pool's allocations and add them to this pool. + void takeAllFrom(AttributePool &pool) { + if (pool.Head) { + takePool(pool.Head); + pool.Head = 0; + } + } + + ~AttributePool() { + if (Head) Factory.reclaimPool(Head); + } + + AttributeList *create(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec = false, bool cxx0x = false) { + void *memory = allocate(sizeof(AttributeList) + + numArgs * sizeof(Expr*)); + return add(new (memory) AttributeList(attrName, attrLoc, + scopeName, scopeLoc, + parmName, parmLoc, + args, numArgs, + declspec, cxx0x)); + } + + AttributeList *create(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, + bool declspec = false, bool cxx0x = false) { + void *memory = allocate(AttributeFactory::AvailabilityAllocSize); + return add(new (memory) AttributeList(attrName, attrLoc, + scopeName, scopeLoc, + parmName, parmLoc, + introduced, deprecated, obsoleted, + unavailable, + declspec, cxx0x)); + } + + AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, + SourceLocation TokLoc, int Arg); +}; + /// addAttributeLists - Add two AttributeLists together /// The right-hand list is appended to the left-hand list, if any /// A pointer to the joined list is returned. @@ -278,7 +509,16 @@ struct CXX0XAttributeList { /// is that this will become significantly more serious. class ParsedAttributes { public: - ParsedAttributes() : list(0) {} + ParsedAttributes(AttributeFactory &factory) + : pool(factory), list(0) { + } + + ParsedAttributes(ParsedAttributes &attrs) + : pool(attrs.pool), list(attrs.list) { + attrs.list = 0; + } + + AttributePool &getPool() const { return pool; } bool empty() const { return list == 0; } @@ -289,7 +529,7 @@ public: list = newAttr; } - void append(AttributeList *newList) { + void addAll(AttributeList *newList) { if (!newList) return; AttributeList *lastInNewList = newList; @@ -304,14 +544,59 @@ public: list = newList; } - void clear() { list = 0; } + void takeAllFrom(ParsedAttributes &attrs) { + addAll(attrs.list); + attrs.list = 0; + pool.takeAllFrom(attrs.pool); + } + + void clear() { list = 0; pool.clear(); } AttributeList *getList() const { return list; } /// Returns a reference to the attribute list. Try not to introduce /// dependencies on this method, it may not be long-lived. AttributeList *&getListRef() { return list; } + + AttributeList *addNew(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec = false, bool cxx0x = false) { + AttributeList *attr = + pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc, + args, numArgs, declspec, cxx0x); + add(attr); + return attr; + } + + AttributeList *addNew(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, + bool declspec = false, bool cxx0x = false) { + AttributeList *attr = + pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc, + introduced, deprecated, obsoleted, unavailable, + declspec, cxx0x); + add(attr); + return attr; + } + + AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, + SourceLocation loc, int arg) { + AttributeList *attr = + pool.createIntegerAttribute(C, name, loc, arg); + add(attr); + return attr; + } + + private: + mutable AttributePool pool; AttributeList *list; }; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 64126bd4d80a..708c9b2084b0 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -22,7 +22,9 @@ #include "clang/Sema/AttributeList.h" #include "clang/Sema/Ownership.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/Lex/Token.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/SmallVector.h" @@ -54,32 +56,10 @@ namespace clang { /// /// The actual scope is described by getScopeRep(). class CXXScopeSpec { - SourceRange Range; - NestedNameSpecifier *ScopeRep; - - /// \brief Buffer used to store source-location information for the - /// nested-name-specifier. - /// - /// Note that we explicitly manage the buffer (rather than using a - /// SmallVector) because \c Declarator expects it to be possible to memcpy() - /// a \c CXXScopeSpec. - char *Buffer; - - /// \brief The size of the buffer used to store source-location information - /// for the nested-name-specifier. - unsigned BufferSize; - - /// \brief The capacity of the buffer used to store source-location - /// information for the nested-name-specifier. - unsigned BufferCapacity; + SourceRange Range; + NestedNameSpecifierLocBuilder Builder; public: - CXXScopeSpec() : Range(), ScopeRep(), Buffer(0), BufferSize(0), - BufferCapacity(0) { } - CXXScopeSpec(const CXXScopeSpec &Other); - CXXScopeSpec &operator=(const CXXScopeSpec &Other); - ~CXXScopeSpec(); - const SourceRange &getRange() const { return Range; } void setRange(const SourceRange &R) { Range = R; } void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } @@ -87,7 +67,10 @@ public: SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } - NestedNameSpecifier *getScopeRep() const { return ScopeRep; } + /// \brief Retrieve the representation of the nested-name-specifier. + NestedNameSpecifier *getScopeRep() const { + return Builder.getRepresentation(); + } /// \brief Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'type::'. @@ -175,10 +158,10 @@ public: /// A scope specifier is present, but may be valid or invalid. bool isNotEmpty() const { return !isEmpty(); } - /// An error occured during parsing of the scope specifier. - bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; } + /// An error occurred during parsing of the scope specifier. + bool isInvalid() const { return isNotEmpty() && getScopeRep() == 0; } /// A scope specifier is present, and it refers to a real scope. - bool isValid() const { return isNotEmpty() && ScopeRep != 0; } + bool isValid() const { return isNotEmpty() && getScopeRep() != 0; } /// \brief Indicate that this nested-name-specifier is invalid. void SetInvalid(SourceRange R) { @@ -186,24 +169,24 @@ public: if (Range.getBegin().isInvalid()) Range.setBegin(R.getBegin()); Range.setEnd(R.getEnd()); - ScopeRep = 0; + Builder.Clear(); } /// Deprecated. Some call sites intend isNotEmpty() while others intend /// isValid(). - bool isSet() const { return ScopeRep != 0; } + bool isSet() const { return getScopeRep() != 0; } void clear() { Range = SourceRange(); - ScopeRep = 0; + Builder.Clear(); } /// \brief Retrieve the data associated with the source-location information. - char *location_data() const { return Buffer; } + char *location_data() const { return Builder.getBuffer().first; } /// \brief Retrieve the size of the data associated with source-location /// information. - unsigned location_size() const { return BufferSize; } + unsigned location_size() const { return Builder.getBuffer().second; } }; /// DeclSpec - This class captures information about "declaration specifiers", @@ -267,6 +250,7 @@ public: static const TST TST_typeofExpr = clang::TST_typeofExpr; static const TST TST_decltype = clang::TST_decltype; static const TST TST_auto = clang::TST_auto; + static const TST TST_unknown_anytype = clang::TST_unknown_anytype; static const TST TST_error = clang::TST_error; // type-qualifiers @@ -288,7 +272,6 @@ public: }; private: - // storage-class-specifier /*SCS*/unsigned StorageClassSpec : 3; unsigned SCS_thread_specified : 1; @@ -346,6 +329,11 @@ private: SourceLocation StorageClassSpecLoc, SCS_threadLoc; SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc, AltiVecLoc; + /// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union, + /// typename, then this is the location of the named type (if present); + /// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and + /// TSTNameLoc provides source range info for tag types. + SourceLocation TSTNameLoc; SourceRange TypeofParensRange; SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; @@ -370,7 +358,7 @@ private: void operator=(const DeclSpec&); // DO NOT IMPLEMENT public: - DeclSpec() + DeclSpec(AttributeFactory &attrFactory) : StorageClassSpec(SCS_unspecified), SCS_thread_specified(false), SCS_extern_in_linkage_spec(false), @@ -389,6 +377,7 @@ public: Friend_specified(false), Constexpr_specified(false), StorageClassSpecAsWritten(SCS_unspecified), + Attrs(attrFactory), ProtocolQualifiers(0), NumProtocolQualifiers(0), ProtocolLocs(0), @@ -448,6 +437,11 @@ public: SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } SourceLocation getAltiVecLoc() const { return AltiVecLoc; } + SourceLocation getTypeSpecTypeNameLoc() const { + assert(isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename); + return TSTNameLoc; + } + SourceRange getTypeofParensRange() const { return TypeofParensRange; } void setTypeofParensRange(SourceRange range) { TypeofParensRange = range; } @@ -539,6 +533,13 @@ public: unsigned &DiagID, ParsedType Rep); bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, Decl *Rep, bool Owned); + bool SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, const char *&PrevSpec, + unsigned &DiagID, ParsedType Rep); + bool SetTypeSpecType(TST T, SourceLocation TagKwLoc, + SourceLocation TagNameLoc, const char *&PrevSpec, + unsigned &DiagID, Decl *Rep, bool Owned); + bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, Expr *Rep); bool SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc, @@ -581,6 +582,10 @@ public: bool isConstexprSpecified() const { return Constexpr_specified; } SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } + AttributePool &getAttributePool() const { + return Attrs.getPool(); + } + /// AddAttributes - contatenates two attribute lists. /// The GCC attribute syntax allows for the following: /// @@ -594,9 +599,9 @@ public: /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; /// void addAttributes(AttributeList *AL) { - Attrs.append(AL); + Attrs.addAll(AL); } - void aetAttributes(AttributeList *AL) { + void setAttributes(AttributeList *AL) { Attrs.set(AL); } @@ -608,14 +613,12 @@ public: /// TakeAttributes - Return the current attribute list and remove them from /// the DeclSpec so that it doesn't own them. ParsedAttributes takeAttributes() { - ParsedAttributes saved = Attrs; - Attrs.clear(); - return saved; + // The non-const "copy" constructor clears the operand automatically. + return Attrs; } void takeAttributesFrom(ParsedAttributes &attrs) { - Attrs.append(attrs.getList()); - attrs.clear(); + Attrs.takeAllFrom(attrs); } typedef Decl * const *ProtocolQualifierListTy; @@ -649,7 +652,12 @@ public: /// "declaration specifiers" specific to objective-c class ObjCDeclSpec { public: - /// ObjCDeclQualifier - Qualifier used on types in method declarations + /// ObjCDeclQualifier - Qualifier used on types in method + /// declarations. Not all combinations are sensible. Parameters + /// can be one of { in, out, inout } with one of { bycopy, byref }. + /// Returns can either be { oneway } or not. + /// + /// This should be kept in sync with Decl::ObjCDeclQualifier. enum ObjCDeclQualifier { DQ_None = 0x0, DQ_In = 0x1, @@ -661,7 +669,8 @@ public: }; /// PropertyAttributeKind - list of property attributes. - enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0, + enum ObjCPropertyAttributeKind { + DQ_PR_noattr = 0x0, DQ_PR_readonly = 0x01, DQ_PR_getter = 0x02, DQ_PR_assign = 0x04, @@ -1037,11 +1046,8 @@ struct DeclaratorChunk { /// The qualifier bitmask values are the same as in QualType. unsigned TypeQuals : 3; - /// hasExceptionSpec - True if the function has an exception specification. - unsigned hasExceptionSpec : 1; - - /// hasAnyExceptionSpec - True if the function has a throw(...) specifier. - unsigned hasAnyExceptionSpec : 1; + /// ExceptionSpecType - An ExceptionSpecificationType value. + unsigned ExceptionSpecType : 3; /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. unsigned DeleteArgInfo : 1; @@ -1053,28 +1059,34 @@ struct DeclaratorChunk { /// declarator. unsigned NumArgs; - /// NumExceptions - This is the number of types in the exception-decl, if - /// the function has one. + /// NumExceptions - This is the number of types in the dynamic-exception- + /// decl, if the function has one. unsigned NumExceptions; /// \brief The location of the ref-qualifier, if any. /// /// If this is an invalid location, there is no ref-qualifier. unsigned RefQualifierLoc; - - /// ThrowLoc - When hasExceptionSpec is true, the location of the throw + + /// \brief When ExceptionSpecType isn't EST_None, the location of the /// keyword introducing the spec. - unsigned ThrowLoc; + unsigned ExceptionSpecLoc; /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that /// describe the arguments for this function declarator. This is null if /// there are no arguments specified. ParamInfo *ArgInfo; - /// Exceptions - This is a pointer to a new[]'d array of TypeAndRange - /// objects that contain the types in the function's exception - /// specification and their locations. - TypeAndRange *Exceptions; + union { + /// \brief Pointer to a new[]'d array of TypeAndRange objects that + /// contain the types in the function's dynamic exception specification + /// and their locations, if there is one. + TypeAndRange *Exceptions; + + /// \brief Pointer to the expression in the noexcept-specifier of this + /// function, if it has one. + Expr *NoexceptExpr; + }; /// TrailingReturnType - If this isn't null, it's the trailing return type /// specified. This is actually a ParsedType, but stored as void* to @@ -1094,7 +1106,8 @@ struct DeclaratorChunk { void destroy() { if (DeleteArgInfo) delete[] ArgInfo; - delete[] Exceptions; + if (getExceptionSpecType() == EST_Dynamic) + delete[] Exceptions; } /// isKNRPrototype - Return true if this is a K&R style identifier list, @@ -1107,18 +1120,23 @@ struct DeclaratorChunk { SourceLocation getEllipsisLoc() const { return SourceLocation::getFromRawEncoding(EllipsisLoc); } - SourceLocation getThrowLoc() const { - return SourceLocation::getFromRawEncoding(ThrowLoc); + SourceLocation getExceptionSpecLoc() const { + return SourceLocation::getFromRawEncoding(ExceptionSpecLoc); } - + /// \brief Retrieve the location of the ref-qualifier, if any. SourceLocation getRefQualifierLoc() const { return SourceLocation::getFromRawEncoding(RefQualifierLoc); } - + /// \brief Determine whether this function declaration contains a /// ref-qualifier. bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); } + + /// \brief Get the type of exception specification this function has. + ExceptionSpecificationType getExceptionSpecType() const { + return static_cast<ExceptionSpecificationType>(ExceptionSpecType); + } }; struct BlockPointerTypeInfo : TypeInfoCommon { @@ -1188,8 +1206,7 @@ struct DeclaratorChunk { static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, SourceLocation ConstQualLoc, SourceLocation VolatileQualLoc, - SourceLocation RestrictQualLoc, - const ParsedAttributes &attrs) { + SourceLocation RestrictQualLoc) { DeclaratorChunk I; I.Kind = Pointer; I.Loc = Loc; @@ -1197,35 +1214,33 @@ struct DeclaratorChunk { I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding(); I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding(); I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); - I.Ptr.AttrList = attrs.getList(); + I.Ptr.AttrList = 0; return I; } /// getReference - Return a DeclaratorChunk for a reference. /// static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, - const ParsedAttributes &attrs, bool lvalue) { DeclaratorChunk I; I.Kind = Reference; I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.LValueRef = lvalue; - I.Ref.AttrList = attrs.getList(); + I.Ref.AttrList = 0; return I; } /// getArray - Return a DeclaratorChunk for an array. /// static DeclaratorChunk getArray(unsigned TypeQuals, - const ParsedAttributes &attrs, bool isStatic, bool isStar, Expr *NumElts, SourceLocation LBLoc, SourceLocation RBLoc) { DeclaratorChunk I; I.Kind = Array; I.Loc = LBLoc; I.EndLoc = RBLoc; - I.Arr.AttrList = attrs.getList(); + I.Arr.AttrList = 0; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; @@ -1235,44 +1250,44 @@ struct DeclaratorChunk { /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. - static DeclaratorChunk getFunction(const ParsedAttributes &attrs, - bool hasProto, bool isVariadic, + static DeclaratorChunk getFunction(bool hasProto, bool isVariadic, SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, bool RefQualifierIsLvalueRef, SourceLocation RefQualifierLoc, - bool hasExceptionSpec, - SourceLocation ThrowLoc, - bool hasAnyExceptionSpec, + ExceptionSpecificationType ESpecType, + SourceLocation ESpecLoc, ParsedType *Exceptions, SourceRange *ExceptionRanges, unsigned NumExceptions, - SourceLocation LPLoc, SourceLocation RPLoc, + Expr *NoexceptExpr, + SourceLocation LocalRangeBegin, + SourceLocation LocalRangeEnd, Declarator &TheDeclarator, - ParsedType TrailingReturnType = ParsedType()); + ParsedType TrailingReturnType = + ParsedType()); /// getBlockPointer - Return a DeclaratorChunk for a block. /// - static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc, - const ParsedAttributes &attrs) { + static DeclaratorChunk getBlockPointer(unsigned TypeQuals, + SourceLocation Loc) { DeclaratorChunk I; I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = attrs.getList(); + I.Cls.AttrList = 0; return I; } static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS, unsigned TypeQuals, - SourceLocation Loc, - const ParsedAttributes &attrs) { + SourceLocation Loc) { DeclaratorChunk I; I.Kind = MemberPointer; I.Loc = Loc; I.Mem.TypeQuals = TypeQuals; - I.Mem.AttrList = attrs.getList(); + I.Mem.AttrList = 0; new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS); return I; } @@ -1306,6 +1321,7 @@ public: enum TheContext { FileContext, // File scope declaration. PrototypeContext, // Within a function prototype. + ObjCPrototypeContext,// Within a method prototype. KNRTypeListContext, // K&R type definition list for formals. TypeNameContext, // Abstract declarator for types. MemberContext, // Struct/Union field. @@ -1315,7 +1331,8 @@ public: TemplateParamContext,// Within a template parameter list. CXXCatchContext, // C++ catch exception-declaration BlockLiteralContext, // Block literal declarator. - TemplateTypeArgContext // Template type argument. + TemplateTypeArgContext, // Template type argument. + AliasDeclContext // C++0x alias-declaration. }; private: @@ -1340,8 +1357,8 @@ private: /// GroupingParens - Set by Parser::ParseParenDeclarator(). bool GroupingParens : 1; - /// AttrList - Attributes. - AttributeList *AttrList; + /// Attrs - Attributes. + ParsedAttributes Attrs; /// AsmLabel - The asm label, if specified. Expr *AsmLabel; @@ -1365,8 +1382,8 @@ public: Declarator(const DeclSpec &ds, TheContext C) : DS(ds), Range(ds.getSourceRange()), Context(C), InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), - GroupingParens(false), AttrList(0), AsmLabel(0), - InlineParamsUsed(false), Extension(false) { + GroupingParens(false), Attrs(ds.getAttributePool().getFactory()), + AsmLabel(0), InlineParamsUsed(false), Extension(false) { } ~Declarator() { @@ -1384,6 +1401,10 @@ public: /// be shared or when in error recovery etc. DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); } + AttributePool &getAttributePool() const { + return Attrs.getPool(); + } + /// getCXXScopeSpec - Return the C++ scope specifier (global scope or /// nested-name-specifier) that is part of the declarator-id. const CXXScopeSpec &getCXXScopeSpec() const { return SS; } @@ -1394,6 +1415,10 @@ public: TheContext getContext() const { return Context; } + bool isPrototypeContext() const { + return (Context == PrototypeContext || Context == ObjCPrototypeContext); + } + /// getSourceRange - Get the source range that spans this declarator. const SourceRange &getSourceRange() const { return Range; } @@ -1429,7 +1454,7 @@ public: for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) DeclTypeInfo[i].destroy(); DeclTypeInfo.clear(); - AttrList = 0; + Attrs.clear(); AsmLabel = 0; InlineParamsUsed = false; } @@ -1438,26 +1463,79 @@ public: /// not allowed. This is true for typenames, prototypes, and template /// parameter lists. bool mayOmitIdentifier() const { - return Context == TypeNameContext || Context == PrototypeContext || - Context == TemplateParamContext || Context == CXXCatchContext || - Context == BlockLiteralContext || Context == TemplateTypeArgContext; + switch (Context) { + case FileContext: + case KNRTypeListContext: + case MemberContext: + case BlockContext: + case ForContext: + case ConditionContext: + return false; + + case TypeNameContext: + case AliasDeclContext: + case PrototypeContext: + case ObjCPrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return true; + } + llvm_unreachable("unknown context kind!"); } /// mayHaveIdentifier - Return true if the identifier is either optional or /// required. This is true for normal declarators and prototypes, but not /// typenames. bool mayHaveIdentifier() const { - return Context != TypeNameContext && Context != BlockLiteralContext && - Context != TemplateTypeArgContext; + switch (Context) { + case FileContext: + case KNRTypeListContext: + case MemberContext: + case BlockContext: + case ForContext: + case ConditionContext: + case PrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + return true; + + case TypeNameContext: + case AliasDeclContext: + case ObjCPrototypeContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return false; + } + llvm_unreachable("unknown context kind!"); } /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be /// followed by a C++ direct initializer, e.g. "int x(1);". bool mayBeFollowedByCXXDirectInit() const { - return !hasGroupingParens() && - (Context == FileContext || - Context == BlockContext || - Context == ForContext); + if (hasGroupingParens()) return false; + + switch (Context) { + case FileContext: + case BlockContext: + case ForContext: + return true; + + case KNRTypeListContext: + case MemberContext: + case ConditionContext: + case PrototypeContext: + case ObjCPrototypeContext: + case TemplateParamContext: + case CXXCatchContext: + case TypeNameContext: + case AliasDeclContext: + case BlockLiteralContext: + case TemplateTypeArgContext: + return false; + } + llvm_unreachable("unknown context kind!"); } /// isPastIdentifier - Return true if we have parsed beyond the point where @@ -1486,8 +1564,13 @@ public: /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to /// EndLoc, which should be the last token of the chunk. - void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { + void AddTypeInfo(const DeclaratorChunk &TI, + ParsedAttributes &attrs, + SourceLocation EndLoc) { DeclTypeInfo.push_back(TI); + DeclTypeInfo.back().getAttrListRef() = attrs.getList(); + getAttributePool().takeAllFrom(attrs.getPool()); + if (!EndLoc.isInvalid()) SetRangeEnd(EndLoc); } @@ -1567,28 +1650,26 @@ public: return const_cast<Declarator*>(this)->getFunctionTypeInfo(); } - /// AddAttributes - simply adds the attribute list to the Declarator. + /// takeAttributes - Takes attributes from the given parsed-attributes + /// set and add them to this declarator. + /// /// These examples both add 3 attributes to "var": /// short int var __attribute__((aligned(16),common,deprecated)); /// short int x, __attribute__((aligned(16)) var /// __attribute__((common,deprecated)); /// /// Also extends the range of the declarator. - void addAttributes(AttributeList *alist, SourceLocation LastLoc) { - AttrList = addAttributeLists(AttrList, alist); + void takeAttributes(ParsedAttributes &attrs, SourceLocation lastLoc) { + Attrs.takeAllFrom(attrs); - if (!LastLoc.isInvalid()) - SetRangeEnd(LastLoc); + if (!lastLoc.isInvalid()) + SetRangeEnd(lastLoc); } - void addAttributes(const ParsedAttributes &attrs) { - addAttributes(attrs.getList(), SourceLocation()); - } - - const AttributeList *getAttributes() const { return AttrList; } - AttributeList *getAttributes() { return AttrList; } + const AttributeList *getAttributes() const { return Attrs.getList(); } + AttributeList *getAttributes() { return Attrs.getList(); } - AttributeList *&getAttrListRef() { return AttrList; } + AttributeList *&getAttrListRef() { return Attrs.getListRef(); } /// hasAttributes - do we contain any attributes? bool hasAttributes() const { @@ -1634,8 +1715,7 @@ public: enum Specifier { VS_None = 0, VS_Override = 1, - VS_Final = 2, - VS_New = 4 + VS_Final = 2 }; VirtSpecifiers() : Specifiers(0) { } @@ -1649,45 +1729,17 @@ public: bool isFinalSpecified() const { return Specifiers & VS_Final; } SourceLocation getFinalLoc() const { return VS_finalLoc; } - bool isNewSpecified() const { return Specifiers & VS_New; } - SourceLocation getNewLoc() const { return VS_newLoc; } - void clear() { Specifiers = 0; } static const char *getSpecifierName(Specifier VS); + SourceLocation getLastLocation() const { return LastLocation; } + private: unsigned Specifiers; - SourceLocation VS_overrideLoc, VS_finalLoc, VS_newLoc; -}; - -/// ClassVirtSpecifiers - Represents a C++0x class-virt-specifier-seq. -class ClassVirtSpecifiers { -public: - enum Specifier { - CVS_None = 0, - CVS_Final = 1, - CVS_Explicit = 2 - }; - - ClassVirtSpecifiers() : Specifiers(0) { } - - bool SetSpecifier(Specifier CVS, SourceLocation Loc, - const char *&PrevSpec); - - bool isFinalSpecified() const { return Specifiers & CVS_Final; } - SourceLocation getFinalLoc() const { return CVS_finalLoc; } - - bool isExplicitSpecified() const { return Specifiers & CVS_Explicit; } - SourceLocation getExplicitLoc() const { return CVS_explicitLoc; } - - static const char *getSpecifierName(Specifier CVS); - -private: - unsigned Specifiers; - - SourceLocation CVS_finalLoc, CVS_explicitLoc; + SourceLocation VS_overrideLoc, VS_finalLoc; + SourceLocation LastLocation; }; } // end namespace clang diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h index 6e808de9a147..8395138ab612 100644 --- a/include/clang/Sema/DelayedDiagnostic.h +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -119,25 +119,11 @@ public: SourceLocation Loc; - void destroy() { - switch (Kind) { - case Access: getAccessData().~AccessedEntity(); break; - case Deprecation: break; - } - } + void Destroy(); static DelayedDiagnostic makeDeprecation(SourceLocation Loc, const NamedDecl *D, - llvm::StringRef Msg) { - DelayedDiagnostic DD; - DD.Kind = Deprecation; - DD.Triggered = false; - DD.Loc = Loc; - DD.DeprecationData.Decl = D; - DD.DeprecationData.Message = Msg.data(); - DD.DeprecationData.MessageLen = Msg.size(); - return DD; - } + llvm::StringRef Msg); static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h index 7e9d338293ee..8d79fc09f292 100644 --- a/include/clang/Sema/IdentifierResolver.h +++ b/include/clang/Sema/IdentifierResolver.h @@ -28,7 +28,7 @@ class Scope; /// IdentifierResolver - Keeps track of shadowed decls on enclosing /// scopes. It manages the shadowing chains of declaration names and -/// implements efficent decl lookup based on a declaration name. +/// implements efficient decl lookup based on a declaration name. class IdentifierResolver { /// IdDeclInfo - Keeps track of information about decls associated @@ -53,6 +53,11 @@ class IdentifierResolver { /// declaration was not found, returns false. bool ReplaceDecl(NamedDecl *Old, NamedDecl *New); + /// \brief Insert the given declaration at the given position in the list. + void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) { + Decls.insert(Pos, D); + } + private: DeclsTy Decls; }; @@ -146,8 +151,13 @@ public: /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns /// true if 'D' belongs to the given declaration context. + /// + /// \param ExplicitInstantiationOrSpecialization When true, we are checking + /// whether the declaration is in scope for the purposes of explicit template + /// instantiation or specialization. The default is false. bool isDeclInScope(Decl *D, DeclContext *Ctx, ASTContext &Context, - Scope *S = 0) const; + Scope *S = 0, + bool ExplicitInstantiationOrSpecialization = false) const; /// AddDecl - Link the decl to its shadowed decl chain. void AddDecl(NamedDecl *D); @@ -161,6 +171,10 @@ public: /// (and, therefore, replaced). bool ReplaceDecl(NamedDecl *Old, NamedDecl *New); + /// \brief Insert the given declaration after the given iterator + /// position. + void InsertDeclAfter(iterator Pos, NamedDecl *D); + /// \brief Link the declaration into the chain of declarations for /// the given identifier. /// diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index bdf0d8e7b602..e83e5c0ccfda 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -64,6 +64,8 @@ public: EK_Temporary, /// \brief The entity being initialized is a base member subobject. EK_Base, + /// \brief The initialization is being done by a delegating constructor. + EK_Delegating, /// \brief The entity being initialized is an element of a vector. /// or vector. EK_VectorElement, @@ -210,6 +212,11 @@ public: static InitializedEntity InitializeBase(ASTContext &Context, CXXBaseSpecifier *Base, bool IsInheritedVirtualBase); + + /// \brief Create the initialization entity for a delegated constructor. + static InitializedEntity InitializeDelegation(QualType Type) { + return InitializedEntity(EK_Delegating, SourceLocation(), Type); + } /// \brief Create the initialization entity for a member subobject. static InitializedEntity InitializeMember(FieldDecl *Member, @@ -234,7 +241,7 @@ public: EntityKind getKind() const { return Kind; } /// \brief Retrieve the parent of the entity being initialized, when - /// the initialization itself is occuring within the context of a + /// the initialization itself is occurring within the context of a /// larger initialization. const InitializedEntity *getParent() const { return Parent; } @@ -590,6 +597,8 @@ public: FK_ReferenceInitFailed, /// \brief Implicit conversion failed. FK_ConversionFailed, + /// \brief Implicit conversion failed. + FK_ConversionFromPropertyFailed, /// \brief Too many initializers for scalar FK_TooManyInitsForScalar, /// \brief Reference initialization from an initializer list @@ -655,7 +664,7 @@ public: /// \param Kind the kind of initialization being performed. /// /// \param Args the argument(s) provided for initialization, ownership of - /// which is transfered into the routine. + /// which is transferred into the routine. /// /// \param ResultType if non-NULL, will be set to the type of the /// initialized object, which is the type of the declaration in most diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index aa58d14fac73..400a7cc9194d 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -439,6 +439,7 @@ public: Decls.clear(); if (Paths) deletePaths(Paths); Paths = NULL; + NamingClass = 0; } /// \brief Clears out any current state and re-initializes for a diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 3ce3513c21ae..e196e83a0e26 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -76,6 +76,7 @@ namespace clang { ICK_Vector_Splat, ///< A vector splat from an arithmetic type ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7) ICK_Block_Pointer_Conversion, ///< Block Pointer conversions + ICK_TransparentUnionConversion, /// Transparent Union Conversions ICK_Num_Conversion_Kinds ///< The number of conversion kinds }; @@ -647,8 +648,6 @@ namespace clang { /// \brief Clear out all of the candidates. void clear(); - - ~OverloadCandidateSet() { clear(); } /// Find the best viable function on this overload set, if it exists. OverloadingResult BestViableFunction(Sema &S, SourceLocation Loc, diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h index 5f2f0eba7124..cef93fe5832f 100644 --- a/include/clang/Sema/Ownership.h +++ b/include/clang/Sema/Ownership.h @@ -383,11 +383,18 @@ namespace clang { template<typename T> T **takeAs() { return reinterpret_cast<T**>(take()); } }; + /// An opaque type for threading parsed type information through the + /// parser. + typedef OpaquePtr<QualType> ParsedType; + typedef UnionOpaquePtr<QualType> UnionParsedType; + /// A SmallVector of statements, with stack size 32 (as that is the only one /// used.) typedef ASTOwningVector<Stmt*, 32> StmtVector; /// A SmallVector of expressions, with stack size 12 (the maximum used.) typedef ASTOwningVector<Expr*, 12> ExprVector; + /// A SmallVector of types. + typedef ASTOwningVector<ParsedType, 12> TypeVector; template <class T, unsigned N> inline ASTMultiPtr<T> move_arg(ASTOwningVector<T, N> &vec) { @@ -421,11 +428,6 @@ namespace clang { static const bool value = true; }; - /// An opaque type for threading parsed type information through the - /// parser. - typedef OpaquePtr<QualType> ParsedType; - typedef UnionOpaquePtr<QualType> UnionParsedType; - typedef ActionResult<Expr*> ExprResult; typedef ActionResult<Stmt*> StmtResult; typedef ActionResult<ParsedType> TypeResult; @@ -440,6 +442,7 @@ namespace clang { typedef ASTMultiPtr<Expr*> MultiExprArg; typedef ASTMultiPtr<Stmt*> MultiStmtArg; + typedef ASTMultiPtr<ParsedType> MultiTypeArg; typedef ASTMultiPtr<TemplateParameterList*> MultiTemplateParamsArg; inline ExprResult ExprError() { return ExprResult(true); } diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h index 9e1a6165b194..1f572e5df4f3 100644 --- a/include/clang/Sema/ParsedTemplate.h +++ b/include/clang/Sema/ParsedTemplate.h @@ -139,6 +139,9 @@ namespace clang { /// tokens. All of the information about template arguments is allocated /// directly after this structure. struct TemplateIdAnnotation { + /// \brief The nested-name-specifier that precedes the template name. + CXXScopeSpec SS; + /// TemplateNameLoc - The location of the template name within the /// source. SourceLocation TemplateNameLoc; @@ -174,10 +177,13 @@ namespace clang { static TemplateIdAnnotation* Allocate(unsigned NumArgs) { TemplateIdAnnotation *TemplateId - = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + + = (TemplateIdAnnotation *)std::malloc(sizeof(TemplateIdAnnotation) + sizeof(ParsedTemplateArgument) * NumArgs); TemplateId->NumArgs = NumArgs; + // Default-construct nested-name-specifier. + new (&TemplateId->SS) CXXScopeSpec(); + // Default-construct parsed template arguments. ParsedTemplateArgument *TemplateArgs = TemplateId->getTemplateArgs(); for (unsigned I = 0; I != NumArgs; ++I) @@ -186,7 +192,10 @@ namespace clang { return TemplateId; } - void Destroy() { free(this); } + void Destroy() { + SS.~CXXScopeSpec(); + free(this); + } }; /// Retrieves the range of the given template parameter lists. diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index d7fda35cdb87..6588a1d92dfa 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -16,6 +16,7 @@ #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" namespace clang { @@ -75,7 +76,10 @@ public: /// ObjCMethodScope - This scope corresponds to an Objective-C method body. /// It always has FnScope and DeclScope set as well. - ObjCMethodScope = 0x400 + ObjCMethodScope = 0x400, + + /// SwitchScope - This is a scope that corresponds to a switch statement. + SwitchScope = 0x800 }; private: /// The parent scope for this scope. This is null for the translation-unit @@ -90,17 +94,25 @@ private: /// interrelates with other control flow statements. unsigned short Flags; + /// PrototypeDepth - This is the number of function prototype scopes + /// enclosing this scope, including this scope. + unsigned short PrototypeDepth; + + /// PrototypeIndex - This is the number of parameters currently + /// declared in this scope. + unsigned short PrototypeIndex; + /// FnParent - If this scope has a parent scope that is a function body, this /// pointer is non-null and points to it. This is used for label processing. Scope *FnParent; /// BreakParent/ContinueParent - This is a direct link to the immediately - /// preceeding BreakParent/ContinueParent if this scope is not one, or null if + /// preceding BreakParent/ContinueParent if this scope is not one, or null if /// there is no containing break/continue scope. Scope *BreakParent, *ContinueParent; /// ControlParent - This is a direct link to the immediately - /// preceeding ControlParent if this scope is not one, or null if + /// preceding ControlParent if this scope is not one, or null if /// there is no containing control scope. Scope *ControlParent; @@ -193,6 +205,19 @@ public: Scope *getTemplateParamParent() { return TemplateParamParent; } const Scope *getTemplateParamParent() const { return TemplateParamParent; } + /// Returns the number of function prototype scopes in this scope + /// chain. + unsigned getFunctionPrototypeDepth() const { + return PrototypeDepth; + } + + /// Return the number of parameters declared in this function + /// prototype, increasing it by one for the next call. + unsigned getNextFunctionPrototypeIndex() { + assert(isFunctionPrototypeScope()); + return PrototypeIndex++; + } + typedef DeclSetTy::iterator decl_iterator; decl_iterator decl_begin() const { return DeclsInScope.begin(); } decl_iterator decl_end() const { return DeclsInScope.end(); } @@ -260,6 +285,20 @@ public: return getFlags() & Scope::AtCatchScope; } + /// isSwitchScope - Return true if this scope is a switch scope. + bool isSwitchScope() const { + for (const Scope *S = this; S; S = S->getParent()) { + if (S->getFlags() & Scope::SwitchScope) + return true; + else if (S->getFlags() & (Scope::FnScope | Scope::ClassScope | + Scope::BlockScope | Scope::TemplateParamScope | + Scope::FunctionPrototypeScope | + Scope::AtCatchScope | Scope::ObjCMethodScope)) + return false; + } + return false; + } + typedef UsingDirectivesTy::iterator udir_iterator; typedef UsingDirectivesTy::const_iterator const_udir_iterator; @@ -285,36 +324,7 @@ public: /// Init - This is used by the parser to implement scope caching. /// - void Init(Scope *Parent, unsigned ScopeFlags) { - AnyParent = Parent; - Depth = AnyParent ? AnyParent->Depth+1 : 0; - Flags = ScopeFlags; - - if (AnyParent) { - FnParent = AnyParent->FnParent; - BreakParent = AnyParent->BreakParent; - ContinueParent = AnyParent->ContinueParent; - ControlParent = AnyParent->ControlParent; - BlockParent = AnyParent->BlockParent; - TemplateParamParent = AnyParent->TemplateParamParent; - } else { - FnParent = BreakParent = ContinueParent = BlockParent = 0; - ControlParent = 0; - TemplateParamParent = 0; - } - - // If this scope is a function or contains breaks/continues, remember it. - if (Flags & FnScope) FnParent = this; - if (Flags & BreakScope) BreakParent = this; - if (Flags & ContinueScope) ContinueParent = this; - if (Flags & ControlScope) ControlParent = this; - if (Flags & BlockScope) BlockParent = this; - if (Flags & TemplateParamScope) TemplateParamParent = this; - DeclsInScope.clear(); - UsingDirectives.clear(); - Entity = 0; - ErrorTrap.reset(); - } + void Init(Scope *parent, unsigned flags); }; } // end namespace clang diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index a93739892cfe..07a14d2dca3b 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -27,6 +27,7 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TemplateKinds.h" #include "clang/Basic/TypeTraits.h" +#include "clang/Basic/ExpressionTraits.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -43,6 +44,7 @@ namespace clang { class ADLResult; class ASTConsumer; class ASTContext; + class ASTMutationListener; class ArrayType; class AttributeList; class BlockDecl; @@ -110,6 +112,7 @@ namespace clang { class ObjCPropertyDecl; class ObjCProtocolDecl; class OverloadCandidateSet; + class OverloadExpr; class ParenListExpr; class ParmVarDecl; class Preprocessor; @@ -128,7 +131,9 @@ namespace clang { class TemplatePartialOrderingContext; class TemplateTemplateParmDecl; class Token; + class TypeAliasDecl; class TypedefDecl; + class TypedefNameDecl; class TypeLoc; class UnqualifiedId; class UnresolvedLookupExpr; @@ -236,6 +241,8 @@ public: /// PackContext - Manages the stack for #pragma pack. An alignment /// of 0 indicates default alignment. void *PackContext; // Really a "PragmaPackStack*" + + bool MSStructPragmaOn; // True when #pragma ms_struct on /// VisContext - Manages the stack for #pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" @@ -255,7 +262,7 @@ public: /// ExtVectorDecls - This is a list all the extended vector types. This allows /// us to associate a raw vector type with one of the ext_vector type names. /// This is only necessary for issuing pretty diagnostics. - llvm::SmallVector<TypedefDecl*, 24> ExtVectorDecls; + llvm::SmallVector<TypedefNameDecl*, 24> ExtVectorDecls; /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. llvm::OwningPtr<CXXFieldCollector> FieldCollector; @@ -305,6 +312,16 @@ public: /// and must warn if not used. Only contains the first declaration. llvm::SmallVector<const DeclaratorDecl*, 4> UnusedFileScopedDecls; + /// \brief Callback to the parser to parse templated functions when needed. + typedef void LateTemplateParserCB(void *P, const FunctionDecl *FD); + LateTemplateParserCB *LateTemplateParser; + void *OpaqueParser; + + void SetLateTemplateParser(LateTemplateParserCB *LTP, void *P) { + LateTemplateParser = LTP; + OpaqueParser = P; + } + class DelayedDiagnostics; class ParsingDeclState { @@ -645,6 +662,7 @@ public: Preprocessor &getPreprocessor() const { return PP; } ASTContext &getASTContext() const { return Context; } ASTConsumer &getASTConsumer() const { return Consumer; } + ASTMutationListener *getASTMutationListener() const; /// \brief Helper class that creates diagnostics with optional /// template instantiation stacks. @@ -678,6 +696,8 @@ public: /// \brief Build a partial diagnostic. PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h + bool findMacroSpelling(SourceLocation &loc, llvm::StringRef name); + ExprResult Owned(Expr* E) { return E; } ExprResult Owned(ExprResult R) { return R; } StmtResult Owned(Stmt* S) { return S; } @@ -755,7 +775,9 @@ public: const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc, bool *MissingExceptionSpecification = 0, - bool *MissingEmptyExceptionSpecification = 0); + bool *MissingEmptyExceptionSpecification = 0, + bool AllowNoexceptAllMatchWithNoSpec = false, + bool IsOperatorNew = false); bool CheckExceptionSpecSubset( const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Superset, SourceLocation SuperLoc, @@ -792,14 +814,117 @@ public: Scope *S, CXXScopeSpec *SS = 0, bool isClassName = false, bool HasTrailingDot = false, - ParsedType ObjectType = ParsedType()); + ParsedType ObjectType = ParsedType(), + bool WantNontrivialTypeSourceInfo = false); TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S); + bool isMicrosoftMissingTypename(const CXXScopeSpec *SS); bool DiagnoseUnknownTypeName(const IdentifierInfo &II, SourceLocation IILoc, Scope *S, CXXScopeSpec *SS, ParsedType &SuggestedType); + /// \brief Describes the result of the name lookup and resolution performed + /// by \c ClassifyName(). + enum NameClassificationKind { + NC_Unknown, + NC_Error, + NC_Keyword, + NC_Type, + NC_Expression, + NC_NestedNameSpecifier, + NC_TypeTemplate, + NC_FunctionTemplate + }; + + class NameClassification { + NameClassificationKind Kind; + ExprResult Expr; + TemplateName Template; + ParsedType Type; + const IdentifierInfo *Keyword; + + explicit NameClassification(NameClassificationKind Kind) : Kind(Kind) {} + + public: + NameClassification(ExprResult Expr) : Kind(NC_Expression), Expr(Expr) {} + + NameClassification(ParsedType Type) : Kind(NC_Type), Type(Type) {} + + NameClassification(const IdentifierInfo *Keyword) + : Kind(NC_Keyword), Keyword(Keyword) { } + + static NameClassification Error() { + return NameClassification(NC_Error); + } + + static NameClassification Unknown() { + return NameClassification(NC_Unknown); + } + + static NameClassification NestedNameSpecifier() { + return NameClassification(NC_NestedNameSpecifier); + } + + static NameClassification TypeTemplate(TemplateName Name) { + NameClassification Result(NC_TypeTemplate); + Result.Template = Name; + return Result; + } + + static NameClassification FunctionTemplate(TemplateName Name) { + NameClassification Result(NC_FunctionTemplate); + Result.Template = Name; + return Result; + } + + NameClassificationKind getKind() const { return Kind; } + + ParsedType getType() const { + assert(Kind == NC_Type); + return Type; + } + + ExprResult getExpression() const { + assert(Kind == NC_Expression); + return Expr; + } + + TemplateName getTemplateName() const { + assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate); + return Template; + } + + TemplateNameKind getTemplateNameKind() const { + assert(Kind == NC_TypeTemplate || Kind == NC_FunctionTemplate); + return Kind == NC_TypeTemplate? TNK_Type_template : TNK_Function_template; + } +}; + + /// \brief Perform name lookup on the given name, classifying it based on + /// the results of name lookup and the following token. + /// + /// This routine is used by the parser to resolve identifiers and help direct + /// parsing. When the identifier cannot be found, this routine will attempt + /// to correct the typo and classify based on the resulting name. + /// + /// \param S The scope in which we're performing name lookup. + /// + /// \param SS The nested-name-specifier that precedes the name. + /// + /// \param Name The identifier. If typo correction finds an alternative name, + /// this pointer parameter will be updated accordingly. + /// + /// \param NameLoc The location of the identifier. + /// + /// \param NextToken The token following the identifier. Used to help + /// disambiguate the name. + NameClassification ClassifyName(Scope *S, + CXXScopeSpec &SS, + IdentifierInfo *&Name, + SourceLocation NameLoc, + const Token &NextToken); + Decl *ActOnDeclarator(Scope *S, Declarator &D); Decl *HandleDeclarator(Scope *S, Declarator &D, @@ -808,6 +933,7 @@ public: void RegisterLocallyScopedExternCDecl(NamedDecl *ND, const LookupResult &Previous, Scope *S); + bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); void DiagnoseFunctionSpecifiers(Declarator& D); void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); @@ -815,6 +941,8 @@ public: NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, bool &Redeclaration); + NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D, + LookupResult &Previous, bool &Redeclaration); NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -840,12 +968,10 @@ public: ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, QualType T); - ParmVarDecl *CheckParameter(DeclContext *DC, - TypeSourceInfo *TSInfo, QualType T, - IdentifierInfo *Name, - SourceLocation NameLoc, - StorageClass SC, - StorageClass SCAsWritten); + ParmVarDecl *CheckParameter(DeclContext *DC, SourceLocation StartLoc, + SourceLocation NameLoc, IdentifierInfo *Name, + QualType T, TypeSourceInfo *TSInfo, + StorageClass SC, StorageClass SCAsWritten); void ActOnParamDefaultArgument(Decl *param, SourceLocation EqualLoc, Expr *defarg); @@ -860,6 +986,7 @@ public: bool TypeMayContainAuto); void ActOnUninitializedDecl(Decl *dcl, bool TypeMayContainAuto); void ActOnInitializerError(Decl *Dcl); + void ActOnCXXForRangeDecl(Decl *D); void SetDeclDeleted(Decl *dcl, SourceLocation DelLoc); void FinalizeDeclaration(Decl *D); DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS, @@ -869,6 +996,7 @@ public: bool TypeMayContainAuto = true); void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, SourceLocation LocAfterDecls); + void CheckForFunctionRedefinition(FunctionDecl *FD); Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D); Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D); void ActOnStartOfObjCMethodDef(Scope *S, Decl *D); @@ -890,7 +1018,9 @@ public: NamedDecl *D); void DiagnoseInvalidJumps(Stmt *Body); - Decl *ActOnFileScopeAsmDecl(SourceLocation Loc, Expr *expr); + Decl *ActOnFileScopeAsmDecl(Expr *expr, + SourceLocation AsmLoc, + SourceLocation RParenLoc); /// Scope actions. void ActOnPopScope(SourceLocation Loc, Scope *S); @@ -994,7 +1124,7 @@ public: /// C++ record definition's base-specifiers clause and are starting its /// member declarations. void ActOnStartCXXMemberDeclarations(Scope *S, Decl *TagDecl, - ClassVirtSpecifiers &CVS, + SourceLocation FinalLoc, SourceLocation LBraceLoc); /// ActOnTagFinishDefinition - Invoked once we have finished parsing @@ -1055,7 +1185,12 @@ public: /// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true /// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns /// true if 'D' belongs to the given declaration context. - bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0); + /// + /// \param ExplicitInstantiationOrSpecialization When true, we are checking + /// whether the declaration is in scope for the purposes of explicit template + /// instantiation or specialization. The default is false. + bool isDeclInScope(NamedDecl *&D, DeclContext *Ctx, Scope *S = 0, + bool ExplicitInstantiationOrSpecialization = false); /// Finds the scope corresponding to the given decl context, if it /// happens to be an enclosing scope. Otherwise return NULL. @@ -1064,11 +1199,13 @@ public: /// Subroutines of ActOnDeclarator(). TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, TypeSourceInfo *TInfo); - void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls); + void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls); bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old); - void MergeVarDeclTypes(VarDecl *New, VarDecl *Old); + void mergeObjCMethodDecls(ObjCMethodDecl *New, const ObjCMethodDecl *Old); void MergeVarDecl(VarDecl *New, LookupResult &OldDecls); + void MergeVarDeclTypes(VarDecl *New, VarDecl *Old); + void MergeVarDeclExceptionSpecs(VarDecl *New, VarDecl *Old); bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old); // AssignmentAction - This is used by all the assignment diagnostic functions @@ -1149,13 +1286,13 @@ public: ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init); - bool PerformObjectArgumentInitialization(Expr *&From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - CXXMethodDecl *Method); + ExprResult PerformObjectArgumentInitialization(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + CXXMethodDecl *Method); - bool PerformContextuallyConvertToBool(Expr *&From); - bool PerformContextuallyConvertToObjCId(Expr *&From); + ExprResult PerformContextuallyConvertToBool(Expr *From); + ExprResult PerformContextuallyConvertToObjCId(Expr *From); ExprResult ConvertToIntegralOrEnumerationType(SourceLocation Loc, Expr *FromE, @@ -1167,10 +1304,10 @@ public: const PartialDiagnostic &AmbigNote, const PartialDiagnostic &ConvDiag); - bool PerformObjectMemberConversion(Expr *&From, - NestedNameSpecifier *Qualifier, - NamedDecl *FoundDecl, - NamedDecl *Member); + ExprResult PerformObjectMemberConversion(Expr *From, + NestedNameSpecifier *Qualifier, + NamedDecl *FoundDecl, + NamedDecl *Member); // Members have to be NamespaceDecl* or TranslationUnitDecl*. // TODO: make this is a typesafe union. @@ -1208,7 +1345,7 @@ public: void AddMethodTemplateCandidate(FunctionTemplateDecl *MethodTmpl, DeclAccessPair FoundDecl, CXXRecordDecl *ActingContext, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ObjectType, Expr::Classification ObjectClassification, Expr **Args, unsigned NumArgs, @@ -1216,7 +1353,7 @@ public: bool SuppressUserConversions = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, DeclAccessPair FoundDecl, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false); @@ -1253,9 +1390,10 @@ public: void AddArgumentDependentLookupCandidates(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, OverloadCandidateSet& CandidateSet, - bool PartialOverloading = false); + bool PartialOverloading = false, + bool StdNamespaceIsAssociated = false); // Emit as a 'note' the specific overload candidate void NoteOverloadCandidate(FunctionDecl *Fn); @@ -1276,10 +1414,18 @@ public: bool Complain, DeclAccessPair &Found); - FunctionDecl *ResolveSingleFunctionTemplateSpecialization(Expr *From, + FunctionDecl *ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, bool Complain = false, DeclAccessPair* Found = 0); + ExprResult ResolveAndFixSingleFunctionTemplateSpecialization( + Expr *SrcExpr, bool DoFunctionPointerConverion = false, + bool Complain = false, + const SourceRange& OpRangeForComplaining = SourceRange(), + QualType DestTypeForComplaining = QualType(), + unsigned DiagIDForComplaining = 0); + + Expr *FixOverloadedFunctionReference(Expr *E, DeclAccessPair FoundDecl, FunctionDecl *Fn); @@ -1444,15 +1590,16 @@ public: QualType T1, QualType T2, UnresolvedSetImpl &Functions); - LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation Loc, - bool isLocalLabel = false); - + LabelDecl *LookupOrCreateLabel(IdentifierInfo *II, SourceLocation IdentLoc, + SourceLocation GnuLabelLoc = SourceLocation()); + DeclContextLookupResult LookupConstructors(CXXRecordDecl *Class); CXXDestructorDecl *LookupDestructor(CXXRecordDecl *Class); void ArgumentDependentLookup(DeclarationName Name, bool Operator, Expr **Args, unsigned NumArgs, - ADLResult &Functions); + ADLResult &Functions, + bool StdNamespaceIsAssociated = false); void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, @@ -1695,6 +1842,7 @@ public: /// initialization. void CollectIvarsToConstructOrDestruct(ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); + //===--------------------------------------------------------------------===// // Statement Parsing Callbacks: SemaStmt.cpp. public: @@ -1734,7 +1882,7 @@ public: StmtResult ActOnExprStmt(FullExprArg Expr); StmtResult ActOnNullStmt(SourceLocation SemiLoc, - bool LeadingEmptyMacro = false); + SourceLocation LeadingEmptyMacroLoc = SourceLocation()); StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, MultiStmtArg Elts, bool isStmtExpr); @@ -1782,6 +1930,17 @@ public: SourceLocation LParenLoc, Stmt *First, Expr *Second, SourceLocation RParenLoc, Stmt *Body); + StmtResult ActOnCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, Stmt *LoopVar, + SourceLocation ColonLoc, Expr *Collection, + SourceLocation RParenLoc); + StmtResult BuildCXXForRangeStmt(SourceLocation ForLoc, + SourceLocation ColonLoc, + Stmt *RangeDecl, Stmt *BeginEndDecl, + Expr *Cond, Expr *Inc, + Stmt *LoopVarDecl, + SourceLocation RParenLoc); + StmtResult FinishCXXForRangeStmt(Stmt *ForRange, Stmt *Body); StmtResult ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, @@ -1811,7 +1970,8 @@ public: VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, - IdentifierInfo *Name, SourceLocation NameLoc, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, bool Invalid = false); Decl *ActOnObjCExceptionDecl(Scope *S, Declarator &D); @@ -1831,16 +1991,29 @@ public: Expr *SynchExpr, Stmt *SynchBody); - VarDecl *BuildExceptionDeclaration(Scope *S, - TypeSourceInfo *TInfo, - IdentifierInfo *Name, - SourceLocation Loc); + VarDecl *BuildExceptionDeclaration(Scope *S, TypeSourceInfo *TInfo, + SourceLocation StartLoc, + SourceLocation IdLoc, + IdentifierInfo *Id); Decl *ActOnExceptionDeclarator(Scope *S, Declarator &D); StmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, Decl *ExDecl, Stmt *HandlerBlock); StmtResult ActOnCXXTryBlock(SourceLocation TryLoc, Stmt *TryBlock, MultiStmtArg Handlers); + + StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ? + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); + + StmtResult ActOnSEHExceptBlock(SourceLocation Loc, + Expr *FilterExpr, + Stmt *Block); + + StmtResult ActOnSEHFinallyBlock(SourceLocation Loc, + Stmt *Block); + void DiagnoseReturnInConstructorExceptionHandler(CXXTryStmt *TryBlock); bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const; @@ -1870,7 +2043,8 @@ public: } void EmitDeprecationWarning(NamedDecl *D, llvm::StringRef Message, - SourceLocation Loc, bool UnknownObjCClass=false); + SourceLocation Loc, + const ObjCInterfaceDecl *UnknownObjCClass=0); void HandleDelayedDeprecationCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); @@ -1878,7 +2052,8 @@ public: // Expression Parsing Callbacks: SemaExpr.cpp. bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, - bool UnknownObjCClass=false); + const ObjCInterfaceDecl *UnknownObjCClass=0); + std::string getDeletedOrUnavailableSuffix(const FunctionDecl *FD); bool DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *PD, ObjCMethodDecl *Getter, SourceLocation Loc); @@ -1906,6 +2081,10 @@ public: // Primary Expressions. SourceRange getExprRange(Expr *E) const; + ObjCIvarDecl *SynthesizeProvisionalIvar(LookupResult &Lookup, + IdentifierInfo *II, + SourceLocation NameLoc); + ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, UnqualifiedId &Name, bool HasTrailingLParen, bool IsAddressOfOperand); @@ -1971,6 +2150,20 @@ public: /// fragments (e.g. "foo" "bar" L"baz"). ExprResult ActOnStringLiteral(const Token *Toks, unsigned NumToks); + ExprResult ActOnGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + MultiTypeArg Types, + MultiExprArg Exprs); + ExprResult CreateGenericSelectionExpr(SourceLocation KeyLoc, + SourceLocation DefaultLoc, + SourceLocation RParenLoc, + Expr *ControllingExpr, + TypeSourceInfo **Types, + Expr **Exprs, + unsigned NumAssocs); + // Binary/Unary Operators. 'Tok' is the token for the operator. ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputArg); @@ -1979,19 +2172,25 @@ public: ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input); - ExprResult CreateSizeOfAlignOfExpr(TypeSourceInfo *T, - SourceLocation OpLoc, - bool isSizeOf, SourceRange R); - ExprResult CreateSizeOfAlignOfExpr(Expr *E, SourceLocation OpLoc, - bool isSizeOf, SourceRange R); + ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *T, + SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R); + ExprResult CreateUnaryExprOrTypeTraitExpr(Expr *E, SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + SourceRange R); ExprResult - ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, - void *TyOrEx, const SourceRange &ArgRange); + ActOnUnaryExprOrTypeTraitExpr(SourceLocation OpLoc, + UnaryExprOrTypeTrait ExprKind, + bool isType, void *TyOrEx, + const SourceRange &ArgRange); - ExprResult CheckPlaceholderExpr(Expr *E, SourceLocation Loc); + ExprResult CheckPlaceholderExpr(Expr *E); + bool CheckVecStepExpr(Expr *E, SourceLocation OpLoc, SourceRange R); - bool CheckSizeOfAlignOfOperand(QualType type, SourceLocation OpLoc, - SourceRange R, bool isSizeof); + bool CheckUnaryExprOrTypeTraitOperand(QualType type, SourceLocation OpLoc, + SourceRange R, + UnaryExprOrTypeTrait ExprKind); ExprResult ActOnSizeofParameterPackExpr(Scope *S, SourceLocation OpLoc, IdentifierInfo &Name, @@ -2020,7 +2219,7 @@ public: const TemplateArgumentListInfo *TemplateArgs, bool SuppressQualifierCheck = false); - ExprResult LookupMemberExpr(LookupResult &R, Expr *&Base, + ExprResult LookupMemberExpr(LookupResult &R, ExprResult &Base, bool &IsArrow, SourceLocation OpLoc, CXXScopeSpec &SS, Decl *ObjCImpDecl, @@ -2163,6 +2362,8 @@ public: // __null ExprResult ActOnGNUNullExpr(SourceLocation TokenLoc); + bool CheckCaseExpression(Expr *expr); + //===------------------------- "Block" Extension ------------------------===// /// ActOnBlockStart - This callback is invoked when a block literal is @@ -2186,6 +2387,7 @@ public: // Act on C++ namespaces Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc, + SourceLocation NamespaceLoc, SourceLocation IdentLoc, IdentifierInfo *Ident, SourceLocation LBrace, @@ -2250,6 +2452,11 @@ public: AttributeList *AttrList, bool IsTypeName, SourceLocation TypenameLoc); + Decl *ActOnAliasDeclaration(Scope *CurScope, + AccessSpecifier AS, + SourceLocation UsingLoc, + UnqualifiedId &Name, + TypeResult Type); /// AddCXXDirectInitializerToDecl - This action is called immediately after /// ActOnDeclarator, when a C++ direct initializer is present. @@ -2444,7 +2651,7 @@ public: //// ActOnCXXThrow - Parse throw expressions. ExprResult ActOnCXXThrow(SourceLocation OpLoc, Expr *expr); - bool CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *&E); + ExprResult CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E); /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. /// Can be interpreted either as function-style casting ("int(x)") @@ -2542,6 +2749,32 @@ public: TypeSourceInfo *RhsT, SourceLocation RParen); + /// ActOnArrayTypeTrait - Parsed one of the bianry type trait support + /// pseudo-functions. + ExprResult ActOnArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + ParsedType LhsTy, + Expr *DimExpr, + SourceLocation RParen); + + ExprResult BuildArrayTypeTrait(ArrayTypeTrait ATT, + SourceLocation KWLoc, + TypeSourceInfo *TSInfo, + Expr *DimExpr, + SourceLocation RParen); + + /// ActOnExpressionTrait - Parsed one of the unary type trait support + /// pseudo-functions. + ExprResult ActOnExpressionTrait(ExpressionTrait OET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen); + + ExprResult BuildExpressionTrait(ExpressionTrait OET, + SourceLocation KWLoc, + Expr *Queried, + SourceLocation RParen); + ExprResult ActOnStartCXXMemberReference(Scope *S, Expr *Base, SourceLocation OpLoc, @@ -2659,25 +2892,41 @@ public: ParsedType ObjectType, bool EnteringContext); - /// \brief The parser has parsed a nested-name-specifier 'type::'. + /// \brief The parser has parsed a nested-name-specifier + /// 'template[opt] template-name < template-args >::'. /// /// \param S The scope in which this nested-name-specifier occurs. /// - /// \param Type The type, which will be a template specialization - /// type, preceding the '::'. - /// - /// \param CCLoc The location of the '::'. + /// \param TemplateLoc The location of the 'template' keyword, if any. /// /// \param SS The nested-name-specifier, which is both an input /// parameter (the nested-name-specifier before this type) and an /// output parameter (containing the full nested-name-specifier, /// including this new type). + /// + /// \param TemplateLoc the location of the 'template' keyword, if any. + /// \param TemplateName The template name. + /// \param TemplateNameLoc The location of the template name. + /// \param LAngleLoc The location of the opening angle bracket ('<'). + /// \param TemplateArgs The template arguments. + /// \param RAngleLoc The location of the closing angle bracket ('>'). + /// \param CCLoc The location of the '::'. + + /// \param EnteringContext Whether we're entering the context of the + /// nested-name-specifier. + /// /// /// \returns true if an error occurred, false otherwise. bool ActOnCXXNestedNameSpecifier(Scope *S, - ParsedType Type, + SourceLocation TemplateLoc, + CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, SourceLocation CCLoc, - CXXScopeSpec &SS); + bool EnteringContext); /// \brief Given a C++ nested-name-specifier, produce an annotation value /// that the parser can use later to reconstruct the given @@ -2818,10 +3067,13 @@ public: MemInitResult BuildDelegatingInitializer(TypeSourceInfo *TInfo, Expr **Args, unsigned NumArgs, + SourceLocation BaseLoc, SourceLocation RParenLoc, SourceLocation LParenLoc, - CXXRecordDecl *ClassDecl, - SourceLocation EllipsisLoc); + CXXRecordDecl *ClassDecl); + + bool SetDelegatingInitializer(CXXConstructorDecl *Constructor, + CXXCtorInitializer *Initializer); bool SetCtorInitializers(CXXConstructorDecl *Constructor, CXXCtorInitializer **Initializers, @@ -2887,15 +3139,19 @@ public: AttributeList *AttrList); void ActOnReenterTemplateScope(Scope *S, Decl *Template); + void ActOnReenterDeclaratorTemplateScope(Scope *S, DeclaratorDecl *D); void ActOnStartDelayedMemberDeclarations(Scope *S, Decl *Record); void ActOnStartDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnDelayedCXXMethodParameter(Scope *S, Decl *Param); void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *Method); void ActOnFinishDelayedMemberDeclarations(Scope *S, Decl *Record); + void MarkAsLateParsedTemplate(FunctionDecl *FD, bool Flag = true); + bool IsInsideALocalClassWithinATemplateFunction(); - Decl *ActOnStaticAssertDeclaration(SourceLocation AssertLoc, + Decl *ActOnStaticAssertDeclaration(SourceLocation StaticAssertLoc, Expr *AssertExpr, - Expr *AssertMessageExpr); + Expr *AssertMessageExpr, + SourceLocation RParenLoc); FriendDecl *CheckFriendTypeDecl(SourceLocation FriendLoc, TypeSourceInfo *TSInfo); @@ -3071,18 +3327,21 @@ public: //===--------------------------------------------------------------------===// // C++ Templates [C++ 14] // + void FilterAcceptableTemplateNames(LookupResult &R); + bool hasAnyAcceptableTemplateNames(LookupResult &R); + void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType, bool EnteringContext, bool &MemberOfUnknownSpecialization); TemplateNameKind isTemplateName(Scope *S, - CXXScopeSpec &SS, - bool hasTemplateKeyword, - UnqualifiedId &Name, - ParsedType ObjectType, - bool EnteringContext, - TemplateTy &Template, - bool &MemberOfUnknownSpecialization); + CXXScopeSpec &SS, + bool hasTemplateKeyword, + UnqualifiedId &Name, + ParsedType ObjectType, + bool EnteringContext, + TemplateTy &Template, + bool &MemberOfUnknownSpecialization); bool DiagnoseUnknownTemplateName(const IdentifierInfo &II, SourceLocation IILoc, @@ -3155,27 +3414,41 @@ public: IdentifierInfo *Name, SourceLocation NameLoc, AttributeList *Attr, TemplateParameterList *TemplateParams, - AccessSpecifier AS); + AccessSpecifier AS, + unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists); void translateTemplateArguments(const ASTTemplateArgsPtr &In, TemplateArgumentListInfo &Out); + void NoteAllFoundTemplates(TemplateName Name); + QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &TemplateArgs); + TemplateArgumentListInfo &TemplateArgs); TypeResult - ActOnTemplateIdType(TemplateTy Template, SourceLocation TemplateLoc, + ActOnTemplateIdType(CXXScopeSpec &SS, + TemplateTy Template, SourceLocation TemplateLoc, SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, SourceLocation RAngleLoc); - TypeResult ActOnTagTemplateIdType(CXXScopeSpec &SS, - TypeResult Type, - TagUseKind TUK, + /// \brief Parsed an elaborated-type-specifier that refers to a template-id, + /// such as \c class T::template apply<U>. + /// + /// \param TUK + TypeResult ActOnTagTemplateIdType(TagUseKind TUK, TypeSpecifierType TagSpec, - SourceLocation TagLoc); + SourceLocation TagLoc, + CXXScopeSpec &SS, + TemplateTy TemplateD, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc); + ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, LookupResult &R, bool RequiresADL, @@ -3225,7 +3498,7 @@ public: LookupResult &Previous); bool CheckFunctionTemplateSpecialization(FunctionDecl *FD, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, LookupResult &Previous); bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); @@ -3291,9 +3564,30 @@ public: llvm::SmallVectorImpl<TemplateArgument> &Converted, CheckTemplateArgumentKind CTAK = CTAK_Specified); + /// \brief Check that the given template arguments can be be provided to + /// the given template, converting the arguments along the way. + /// + /// \param Template The template to which the template arguments are being + /// provided. + /// + /// \param TemplateLoc The location of the template name in the source. + /// + /// \param TemplateArgs The list of template arguments. If the template is + /// a template template parameter, this function may extend the set of + /// template arguments to also include substituted, defaulted template + /// arguments. + /// + /// \param PartialTemplateArgs True if the list of template arguments is + /// intentionally partial, e.g., because we're checking just the initial + /// set of template arguments. + /// + /// \param Converted Will receive the converted, canonicalized template + /// arguments. + /// + /// \returns True if an error occurred, false otherwise. bool CheckTemplateArgumentList(TemplateDecl *Template, SourceLocation TemplateLoc, - const TemplateArgumentListInfo &TemplateArgs, + TemplateArgumentListInfo &TemplateArgs, bool PartialTemplateArgs, llvm::SmallVectorImpl<TemplateArgument> &Converted); @@ -3305,10 +3599,10 @@ public: TypeSourceInfo *Arg); bool CheckTemplateArgumentPointerToMember(Expr *Arg, TemplateArgument &Converted); - bool CheckTemplateArgument(NonTypeTemplateParmDecl *Param, - QualType InstantiatedParamType, Expr *&Arg, - TemplateArgument &Converted, - CheckTemplateArgumentKind CTAK = CTAK_Specified); + ExprResult CheckTemplateArgument(NonTypeTemplateParmDecl *Param, + QualType InstantiatedParamType, Expr *Arg, + TemplateArgument &Converted, + CheckTemplateArgumentKind CTAK = CTAK_Specified); bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, const TemplateArgumentLoc &Arg); @@ -3384,17 +3678,25 @@ public: /// \param TypenameLoc the location of the 'typename' keyword /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). /// \param TemplateLoc the location of the 'template' keyword, if any. - /// \param Ty the type that the typename specifier refers to. + /// \param TemplateName The template name. + /// \param TemplateNameLoc The location of the template name. + /// \param LAngleLoc The location of the opening angle bracket ('<'). + /// \param TemplateArgs The template arguments. + /// \param RAngleLoc The location of the closing angle bracket ('>'). TypeResult ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, - const CXXScopeSpec &SS, SourceLocation TemplateLoc, - ParsedType Ty); + const CXXScopeSpec &SS, + SourceLocation TemplateLoc, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc); QualType CheckTypenameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo &II, SourceLocation KeywordLoc, - SourceRange NNSRange, + NestedNameSpecifierLoc QualifierLoc, + const IdentifierInfo &II, SourceLocation IILoc); TypeSourceInfo *RebuildTypeInCurrentInstantiation(TypeSourceInfo *T, @@ -3480,7 +3782,7 @@ public: /// \param T The type that is being checked for unexpanded parameter /// packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, UnexpandedParameterPackContext UPPC); @@ -3490,7 +3792,7 @@ public: /// \param E The expression that is being checked for unexpanded /// parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(Expr *E, UnexpandedParameterPackContext UPPC = UPPC_Expression); @@ -3500,7 +3802,7 @@ public: /// \param SS The nested-name-specifier that is being checked for /// unexpanded parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, UnexpandedParameterPackContext UPPC); @@ -3510,7 +3812,7 @@ public: /// \param NameInfo The name (with source location information) that /// is being checked for unexpanded parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, UnexpandedParameterPackContext UPPC); @@ -3522,7 +3824,7 @@ public: /// \param Template The template name that is being checked for unexpanded /// parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TemplateName Template, UnexpandedParameterPackContext UPPC); @@ -3533,7 +3835,7 @@ public: /// \param Arg The template argument that is being checked for unexpanded /// parameter packs. /// - /// \returns true if an error ocurred, false otherwise. + /// \returns true if an error occurred, false otherwise. bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, UnexpandedParameterPackContext UPPC); @@ -3751,7 +4053,7 @@ public: TemplateDeductionResult SubstituteExplicitTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo &ExplicitTemplateArgs, + TemplateArgumentListInfo &ExplicitTemplateArgs, llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced, llvm::SmallVectorImpl<QualType> &ParamTypes, QualType *FunctionType, @@ -3766,14 +4068,14 @@ public: TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, QualType ArgFunctionType, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); @@ -3786,11 +4088,12 @@ public: TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, - const TemplateArgumentListInfo *ExplicitTemplateArgs, + TemplateArgumentListInfo *ExplicitTemplateArgs, FunctionDecl *&Specialization, sema::TemplateDeductionInfo &Info); - bool DeduceAutoType(QualType AutoType, Expr *Initializer, QualType &Result); + bool DeduceAutoType(TypeSourceInfo *AutoType, Expr *Initializer, + TypeSourceInfo *&Result); FunctionTemplateDecl *getMoreSpecializedTemplate(FunctionTemplateDecl *FT1, FunctionTemplateDecl *FT2, @@ -4204,7 +4507,7 @@ public: /// types, static variables, enumerators, etc. std::deque<PendingImplicitInstantiation> PendingLocalImplicitInstantiations; - void PerformPendingInstantiations(bool LocalOnly = false); + bool PerformPendingInstantiations(bool LocalOnly = false); TypeSourceInfo *SubstType(TypeSourceInfo *T, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -4224,6 +4527,7 @@ public: DeclarationName Entity); ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, + int indexAdjustment, llvm::Optional<unsigned> NumExpansions); bool SubstParmTypes(SourceLocation Loc, ParmVarDecl **Params, unsigned NumParams, @@ -4289,11 +4593,6 @@ public: ClassTemplateSpecializationDecl *ClassTemplateSpec, TemplateSpecializationKind TSK); - NestedNameSpecifier * - SubstNestedNameSpecifier(NestedNameSpecifier *NNS, - SourceRange Range, - const MultiLevelTemplateArgumentList &TemplateArgs); - NestedNameSpecifierLoc SubstNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -4302,7 +4601,8 @@ public: SubstDeclarationNameInfo(const DeclarationNameInfo &NameInfo, const MultiLevelTemplateArgumentList &TemplateArgs); TemplateName - SubstTemplateName(TemplateName Name, SourceLocation Loc, + SubstTemplateName(NestedNameSpecifierLoc QualifierLoc, TemplateName Name, + SourceLocation Loc, const MultiLevelTemplateArgumentList &TemplateArgs); bool Subst(const TemplateArgumentLoc *Args, unsigned NumArgs, TemplateArgumentListInfo &Result, @@ -4475,7 +4775,7 @@ public: ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, - bool isVariadic = false); + bool isVariadic, bool MethodDefinition); // Helper method for ActOnClassMethod/ActOnInstanceMethod. // Will search "local" class/category implementations for a method decl. @@ -4485,6 +4785,9 @@ public: ObjCInterfaceDecl *CDecl); ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel, ObjCInterfaceDecl *ClassDecl); + ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool IsInstance); ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, @@ -4586,6 +4889,11 @@ public: PPK_Pop // #pragma pack(pop, [identifier], [n]) }; + enum PragmaMSStructKind { + PMSST_OFF, // #pragms ms_struct off + PMSST_ON // #pragms ms_struct on + }; + /// ActOnPragmaPack - Called on well formed #pragma pack(...). void ActOnPragmaPack(PragmaPackKind Kind, IdentifierInfo *Name, @@ -4593,6 +4901,9 @@ public: SourceLocation PragmaLoc, SourceLocation LParenLoc, SourceLocation RParenLoc); + + /// ActOnPragmaMSStruct - Called on well formed #pragms ms_struct [on|off]. + void ActOnPragmaMSStruct(PragmaMSStructKind Kind); /// ActOnPragmaUnused - Called on well-formed '#pragma unused'. void ActOnPragmaUnused(const Token &Identifier, @@ -4626,6 +4937,9 @@ public: /// a the record decl, to handle '#pragma pack' and '#pragma options align'. void AddAlignmentAttributesForRecord(RecordDecl *RD); + /// AddMsStructLayoutForRecord - Adds ms_struct layout attribute to record. + void AddMsStructLayoutForRecord(RecordDecl *RD); + /// FreePackedContext - Deallocate and null out PackContext. void FreePackedContext(); @@ -4655,38 +4969,42 @@ public: /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit /// cast. If there is already an implicit cast, merge into the existing one. /// If isLvalue, the result of the cast is an lvalue. - void ImpCastExprToType(Expr *&Expr, QualType Type, CastKind CK, - ExprValueKind VK = VK_RValue, - const CXXCastPath *BasePath = 0); + ExprResult ImpCastExprToType(Expr *E, QualType Type, CastKind CK, + ExprValueKind VK = VK_RValue, + const CXXCastPath *BasePath = 0); + + /// ScalarTypeToBooleanCastKind - Returns the cast kind corresponding + /// to the conversion from scalar type ScalarTy to the Boolean type. + static CastKind ScalarTypeToBooleanCastKind(QualType ScalarTy); /// IgnoredValueConversions - Given that an expression's result is /// syntactically ignored, perform any conversions that are /// required. - void IgnoredValueConversions(Expr *&expr); + ExprResult IgnoredValueConversions(Expr *E); // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts // functions and arrays to their respective pointers (C99 6.3.2.1). - Expr *UsualUnaryConversions(Expr *&expr); + ExprResult UsualUnaryConversions(Expr *E); // DefaultFunctionArrayConversion - converts functions and arrays // to their respective pointers (C99 6.3.2.1). - void DefaultFunctionArrayConversion(Expr *&expr); + ExprResult DefaultFunctionArrayConversion(Expr *E); // DefaultFunctionArrayLvalueConversion - converts functions and // arrays to their respective pointers and performs the // lvalue-to-rvalue conversion. - void DefaultFunctionArrayLvalueConversion(Expr *&expr); + ExprResult DefaultFunctionArrayLvalueConversion(Expr *E); // DefaultLvalueConversion - performs lvalue-to-rvalue conversion on // the operand. This is DefaultFunctionArrayLvalueConversion, // except that it assumes the operand isn't of function or array // type. - void DefaultLvalueConversion(Expr *&expr); + ExprResult DefaultLvalueConversion(Expr *E); // DefaultArgumentPromotion (C99 6.5.2.2p6). Used for function calls that // do not have a prototype. Integer promotions are performed on each // argument, and arguments that have type float are promoted to double. - void DefaultArgumentPromotion(Expr *&Expr); + ExprResult DefaultArgumentPromotion(Expr *E); // Used for emitting the right warning by DefaultVariadicArgumentPromotion enum VariadicCallType { @@ -4709,15 +5027,15 @@ public: // DefaultVariadicArgumentPromotion - Like DefaultArgumentPromotion, but // will warn if the resulting type is not a POD type. - bool DefaultVariadicArgumentPromotion(Expr *&Expr, VariadicCallType CT, - FunctionDecl *FDecl); + ExprResult DefaultVariadicArgumentPromotion(Expr *E, VariadicCallType CT, + FunctionDecl *FDecl); // UsualArithmeticConversions - performs the UsualUnaryConversions on it's // operands and then handles various conversions that are common to binary // operators (C99 6.3.1.8). If both operands aren't arithmetic, this // routine returns the first non-arithmetic type found. The client is // responsible for emitting appropriate error diagnostics. - QualType UsualArithmeticConversions(Expr *&lExpr, Expr *&rExpr, + QualType UsualArithmeticConversions(ExprResult &lExpr, ExprResult &rExpr, bool isCompAssign = false); /// AssignConvertType - All of the 'assignment' semantic checks return this @@ -4805,94 +5123,102 @@ public: /// Check assignment constraints and prepare for a conversion of the /// RHS to the LHS type. - AssignConvertType CheckAssignmentConstraints(QualType lhs, Expr *&rhs, + AssignConvertType CheckAssignmentConstraints(QualType lhs, ExprResult &rhs, CastKind &Kind); // CheckSingleAssignmentConstraints - Currently used by // CheckAssignmentOperands, and ActOnReturnStmt. Prior to type checking, // this routine performs the default function/array converions. AssignConvertType CheckSingleAssignmentConstraints(QualType lhs, - Expr *&rExpr); + ExprResult &rExprRes); // \brief If the lhs type is a transparent union, check whether we // can initialize the transparent union with the given expression. AssignConvertType CheckTransparentUnionArgumentConstraints(QualType lhs, - Expr *&rExpr); + ExprResult &rExpr); bool IsStringLiteralToNonConstPointerConversion(Expr *From, QualType ToType); bool CheckExceptionSpecCompatibility(Expr *From, QualType ToType); - bool PerformImplicitConversion(Expr *&From, QualType ToType, - AssignmentAction Action, - bool AllowExplicit = false); - bool PerformImplicitConversion(Expr *&From, QualType ToType, - AssignmentAction Action, - bool AllowExplicit, - ImplicitConversionSequence& ICS); - bool PerformImplicitConversion(Expr *&From, QualType ToType, - const ImplicitConversionSequence& ICS, - AssignmentAction Action, - bool CStyle = false); - bool PerformImplicitConversion(Expr *&From, QualType ToType, - const StandardConversionSequence& SCS, - AssignmentAction Action, - bool CStyle); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, + bool AllowExplicit = false); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + AssignmentAction Action, + bool AllowExplicit, + ImplicitConversionSequence& ICS); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + const ImplicitConversionSequence& ICS, + AssignmentAction Action, + bool CStyle = false); + ExprResult PerformImplicitConversion(Expr *From, QualType ToType, + const StandardConversionSequence& SCS, + AssignmentAction Action, + bool CStyle); /// the following "Check" methods will return a valid/converted QualType /// or a null QualType (indicating an error diagnostic was issued). /// type checking binary operators (subroutines of CreateBuiltinBinOp). - QualType InvalidOperands(SourceLocation l, Expr *&lex, Expr *&rex); + QualType InvalidOperands(SourceLocation l, ExprResult &lex, ExprResult &rex); QualType CheckPointerToMemberOperands( // C++ 5.5 - Expr *&lex, Expr *&rex, ExprValueKind &VK, + ExprResult &lex, ExprResult &rex, ExprValueKind &VK, SourceLocation OpLoc, bool isIndirect); QualType CheckMultiplyDivideOperands( // C99 6.5.5 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign, + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, bool isCompAssign, bool isDivide); QualType CheckRemainderOperands( // C99 6.5.5 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, bool isCompAssign = false); QualType CheckAdditionOperands( // C99 6.5.6 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); QualType CheckSubtractionOperands( // C99 6.5.6 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, QualType* CompLHSTy = 0); QualType CheckShiftOperands( // C99 6.5.7 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, unsigned Opc, bool isCompAssign = false); QualType CheckCompareOperands( // C99 6.5.8/9 - Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc, + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, unsigned Opc, bool isRelational); QualType CheckBitwiseOperands( // C99 6.5.[10...12] - Expr *&lex, Expr *&rex, SourceLocation OpLoc, bool isCompAssign = false); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, bool isCompAssign = false); QualType CheckLogicalOperands( // C99 6.5.[13,14] - Expr *&lex, Expr *&rex, SourceLocation OpLoc, unsigned Opc); + ExprResult &lex, ExprResult &rex, SourceLocation OpLoc, unsigned Opc); // CheckAssignmentOperands is used for both simple and compound assignment. // For simple assignment, pass both expressions and a null converted type. // For compound assignment, pass both expressions and the converted type. QualType CheckAssignmentOperands( // C99 6.5.16.[1,2] - Expr *lex, Expr *&rex, SourceLocation OpLoc, QualType convertedType); + Expr *lex, ExprResult &rex, SourceLocation OpLoc, QualType convertedType); - void ConvertPropertyForRValue(Expr *&E); - void ConvertPropertyForLValue(Expr *&LHS, Expr *&RHS, QualType& LHSTy); + void ConvertPropertyForLValue(ExprResult &LHS, ExprResult &RHS, QualType& LHSTy); + ExprResult ConvertPropertyForRValue(Expr *E); QualType CheckConditionalOperands( // C99 6.5.15 - Expr *&cond, Expr *&lhs, Expr *&rhs, + ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType CXXCheckConditionalOperands( // C++ 5.16 - Expr *&cond, Expr *&lhs, Expr *&rhs, + ExprResult &cond, ExprResult &lhs, ExprResult &rhs, ExprValueKind &VK, ExprObjectKind &OK, SourceLocation questionLoc); QualType FindCompositePointerType(SourceLocation Loc, Expr *&E1, Expr *&E2, bool *NonStandardCompositeType = 0); + QualType FindCompositePointerType(SourceLocation Loc, ExprResult &E1, ExprResult &E2, + bool *NonStandardCompositeType = 0) { + Expr *E1Tmp = E1.take(), *E2Tmp = E2.take(); + QualType Composite = FindCompositePointerType(Loc, E1Tmp, E2Tmp, NonStandardCompositeType); + E1 = Owned(E1Tmp); + E2 = Owned(E2Tmp); + return Composite; + } - QualType FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, + QualType FindCompositeObjCPointerType(ExprResult &LHS, ExprResult &RHS, SourceLocation questionLoc); bool DiagnoseConditionalForNull(Expr *LHS, Expr *RHS, SourceLocation QuestionLoc); /// type checking for vector binary operators. - QualType CheckVectorOperands(SourceLocation l, Expr *&lex, Expr *&rex); - QualType CheckVectorCompareOperands(Expr *&lex, Expr *&rx, + QualType CheckVectorOperands(SourceLocation l, ExprResult &lex, ExprResult &rex); + QualType CheckVectorCompareOperands(ExprResult &lex, ExprResult &rx, SourceLocation l, bool isRel); /// type checking declaration initializers (C99 6.7.8) @@ -4930,9 +5256,13 @@ public: /// CheckCastTypes - Check type constraints for casting between types under /// C semantics, or forward to CXXCheckCStyleCast in C++. - bool CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *&CastExpr, - CastKind &Kind, ExprValueKind &VK, CXXCastPath &BasePath, - bool FunctionalStyle = false); + ExprResult CheckCastTypes(SourceRange TyRange, QualType CastTy, Expr *CastExpr, + CastKind &Kind, ExprValueKind &VK, CXXCastPath &BasePath, + bool FunctionalStyle = false); + + ExprResult checkUnknownAnyCast(SourceRange TyRange, QualType castType, + Expr *castExpr, CastKind &castKind, + ExprValueKind &valueKind, CXXCastPath &BasePath); // CheckVectorCast - check type constraints for vectors. // Since vectors are an extension, there are no C standard reference for this. @@ -4945,15 +5275,15 @@ public: // Since vectors are an extension, there are no C standard reference for this. // We allow casting between vectors and integer datatypes of the same size, // or vectors and the element type of that vector. - // returns true if the cast is invalid - bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr, - CastKind &Kind); + // returns the cast expr + ExprResult CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *CastExpr, + CastKind &Kind); /// CXXCheckCStyleCast - Check constraints of a C-style or function-style /// cast under C++ semantics. - bool CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, - Expr *&CastExpr, CastKind &Kind, - CXXCastPath &BasePath, bool FunctionalStyle); + ExprResult CXXCheckCStyleCast(SourceRange R, QualType CastTy, ExprValueKind &VK, + Expr *CastExpr, CastKind &Kind, + CXXCastPath &BasePath, bool FunctionalStyle); /// CheckMessageArgumentTypes - Check types in an Obj-C message send. /// \param Method - May be null. @@ -4972,7 +5302,7 @@ public: /// \param Loc - A location associated with the condition, e.g. the /// 'if' keyword. /// \return true iff there were any errors - bool CheckBooleanCondition(Expr *&CondExpr, SourceLocation Loc); + ExprResult CheckBooleanCondition(Expr *CondExpr, SourceLocation Loc); ExprResult ActOnBooleanCondition(Scope *S, SourceLocation Loc, Expr *SubExpr); @@ -4986,7 +5316,7 @@ public: void DiagnoseEqualityWithExtraParens(ParenExpr *parenE); /// CheckCXXBooleanCondition - Returns true if conversion to bool is invalid. - bool CheckCXXBooleanCondition(Expr *&CondExpr); + ExprResult CheckCXXBooleanCondition(Expr *CondExpr); /// ConvertIntegerToTypeWarnOnOverflow - Convert the specified APInt to have /// the specified width and sign. If an overflow occurs, detect it and emit @@ -5174,7 +5504,7 @@ public: unsigned ByteNo) const; private: - void CheckArrayAccess(const ArraySubscriptExpr *E); + void CheckArrayAccess(const Expr *E); bool CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall); bool CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall); @@ -5210,12 +5540,15 @@ private: bool isPrintf); void CheckNonNullArguments(const NonNullAttr *NonNull, - const CallExpr *TheCall); + const Expr * const *ExprArgs, + SourceLocation CallSiteLoc); void CheckPrintfScanfArguments(const CallExpr *TheCall, bool HasVAListArg, unsigned format_idx, unsigned firstDataArg, bool isPrintf); + void CheckMemsetArguments(const CallExpr *Call); + void CheckReturnStackAddr(Expr *RetValExp, QualType lhsType, SourceLocation ReturnLoc); void CheckFloatComparison(SourceLocation loc, Expr* lex, Expr* rex); diff --git a/include/clang/Sema/SemaDiagnostic.h b/include/clang/Sema/SemaDiagnostic.h index ae5aa33db766..83c0999ad49c 100644 --- a/include/clang/Sema/SemaDiagnostic.h +++ b/include/clang/Sema/SemaDiagnostic.h @@ -15,7 +15,8 @@ namespace clang { namespace diag { enum { -#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,SFINAE,ACCESS,CATEGORY) ENUM, +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ + SFINAE,ACCESS,CATEGORY,BRIEF,FULL) ENUM, #define SEMASTART #include "clang/Basic/DiagnosticSemaKinds.inc" #undef DIAG diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index 53f4a9d8c8fa..4d97f9bef802 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -335,7 +335,9 @@ namespace clang { Decl *VisitLabelDecl(LabelDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); + Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); Decl *VisitTypedefDecl(TypedefDecl *D); + Decl *VisitTypeAliasDecl(TypeAliasDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitFieldDecl(FieldDecl *D); diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index 7cc35713aace..c66697963e0d 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -56,7 +56,7 @@ public: } /// \brief Returns the location at which template argument is - /// occuring. + /// occurring. SourceLocation getLocation() const { return Loc; } diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 68fd91d4c069..1cfd458a3864 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -490,7 +490,11 @@ namespace clang { /// \brief The ObjC 'Class' type. PREDEF_TYPE_OBJC_CLASS = 27, /// \brief The ObjC 'SEL' type. - PREDEF_TYPE_OBJC_SEL = 28 + PREDEF_TYPE_OBJC_SEL = 28, + /// \brief The 'unknown any' placeholder type. + PREDEF_TYPE_UNKNOWN_ANY = 29, + /// \brief The placeholder type for bound member functions. + PREDEF_TYPE_BOUND_MEMBER = 30 }; /// \brief The number of predefined type IDs that are reserved for @@ -622,7 +626,11 @@ namespace clang { /// \brief NSConstantString type SPECIAL_TYPE_NS_CONSTANT_STRING = 15, /// \brief Whether __[u]int128_t identifier is installed. - SPECIAL_TYPE_INT128_INSTALLED = 16 + SPECIAL_TYPE_INT128_INSTALLED = 16, + /// \brief Cached "auto" deduction type. + SPECIAL_TYPE_AUTO_DEDUCT = 17, + /// \brief Cached "auto &&" deduction type. + SPECIAL_TYPE_AUTO_RREF_DEDUCT = 18 }; /// \brief Record codes for each kind of declaration. @@ -636,6 +644,8 @@ namespace clang { DECL_TRANSLATION_UNIT = 50, /// \brief A TypedefDecl record. DECL_TYPEDEF, + /// \brief A TypeAliasDecl record. + DECL_TYPEALIAS, /// \brief An EnumDecl record. DECL_ENUM, /// \brief A RecordDecl record. @@ -872,6 +882,8 @@ namespace clang { EXPR_BLOCK, /// \brief A BlockDeclRef record. EXPR_BLOCK_DECL_REF, + /// \brief A GenericSelectionExpr record. + EXPR_GENERIC_SELECTION, // Objective-C @@ -913,6 +925,8 @@ namespace clang { STMT_CXX_CATCH, /// \brief A CXXTryStmt record. STMT_CXX_TRY, + /// \brief A CXXForRangeStmt record. + STMT_CXX_FOR_RANGE, /// \brief A CXXOperatorCallExpr record. EXPR_CXX_OPERATOR_CALL, @@ -958,11 +972,13 @@ namespace clang { EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr EXPR_CXX_UNARY_TYPE_TRAIT, // UnaryTypeTraitExpr + EXPR_CXX_EXPRESSION_TRAIT, // ExpressionTraitExpr EXPR_CXX_NOEXCEPT, // CXXNoexceptExpr EXPR_OPAQUE_VALUE, // OpaqueValueExpr EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator EXPR_BINARY_TYPE_TRAIT, // BinaryTypeTraitExpr + EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr EXPR_PACK_EXPANSION, // PackExpansionExpr EXPR_SIZEOF_PACK, // SizeOfPackExpr diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 424e78c391bc..da018ab99e65 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -69,6 +69,7 @@ class ASTStmtReader; class ASTIdentifierLookupTrait; class TypeLocReader; struct HeaderFileInfo; +class VersionTuple; struct PCHPredefinesBlock { /// \brief The file ID for this predefines buffer in a PCH file. @@ -213,6 +214,10 @@ private: /// \brief The AST consumer. ASTConsumer *Consumer; + /// \brief AST buffers for chained PCHs created and stored in memory. + /// First (not depending on another) PCH in chain is in front. + std::vector<llvm::MemoryBuffer *> ASTBuffers; + /// \brief Information that is needed for every module. struct PerFileData { PerFileData(ASTFileType Ty); @@ -806,7 +811,9 @@ private: /// /// This routine should only be used for fatal errors that have to /// do with non-routine failures (e.g., corrupted AST file). - void Error(const char *Msg); + void Error(llvm::StringRef Msg); + void Error(unsigned DiagID, llvm::StringRef Arg1 = llvm::StringRef(), + llvm::StringRef Arg2 = llvm::StringRef()); ASTReader(const ASTReader&); // do not implement ASTReader &operator=(const ASTReader &); // do not implement @@ -886,6 +893,13 @@ public: /// \brief Sets and initializes the given Context. void InitializeContext(ASTContext &Context); + /// \brief Set AST buffers for chained PCHs created and stored in memory. + /// First (not depending on another) PCH in chain is first in array. + void setASTMemoryBuffers(llvm::MemoryBuffer **bufs, unsigned numBufs) { + ASTBuffers.clear(); + ASTBuffers.insert(ASTBuffers.begin(), bufs, bufs + numBufs); + } + /// \brief Retrieve the name of the named (primary) AST file const std::string &getFileName() const { return Chain[0]->FileName; } @@ -1052,6 +1066,10 @@ public: /// \brief Print some statistics about AST usage. virtual void PrintStats(); + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; + /// \brief Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. @@ -1108,7 +1126,7 @@ public: } /// \brief Read the source location entry with index ID. - virtual void ReadSLocEntry(unsigned ID); + virtual bool ReadSLocEntry(unsigned ID); Selector DecodeSelector(unsigned Idx); @@ -1197,6 +1215,9 @@ public: // \brief Read a string std::string ReadString(const RecordData &Record, unsigned &Idx); + /// \brief Read a version tuple. + VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); + CXXTemporary *ReadCXXTemporary(const RecordData &Record, unsigned &Idx); /// \brief Reads attributes from the current stream position. diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 04ad93fa7c1a..1a79b31d26b4 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -56,6 +56,7 @@ class Sema; class SourceManager; class SwitchCase; class TargetInfo; +class VersionTuple; /// \brief Writes an AST file containing the contents of a translation unit. /// @@ -322,6 +323,7 @@ private: void WriteHeaderSearch(HeaderSearch &HS, const char* isysroot); void WritePreprocessorDetail(PreprocessingRecord &PPRec); void WritePragmaDiagnosticMappings(const Diagnostic &Diag); + void WriteCXXBaseSpecifiersOffsets(); void WriteType(QualType T); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); @@ -513,6 +515,9 @@ public: /// \brief Add a string to the given record. void AddString(llvm::StringRef Str, RecordDataImpl &Record); + /// \brief Add a version tuple to the given record + void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record); + /// \brief Mark a declaration context as needing an update. void AddUpdatedDeclContext(const DeclContext *DC) { UpdatedDeclContexts.insert(DC); @@ -581,6 +586,10 @@ public: virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D); virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D); + virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, + const FunctionDecl *D); + virtual void CompletedImplicitDefinition(const FunctionDecl *D); + virtual void StaticDataMemberInstantiated(const VarDecl *D); }; /// \brief AST and semantic-analysis consumer that generates a diff --git a/include/clang/Serialization/ChainedIncludesSource.h b/include/clang/Serialization/ChainedIncludesSource.h new file mode 100644 index 000000000000..0c3e86faf414 --- /dev/null +++ b/include/clang/Serialization/ChainedIncludesSource.h @@ -0,0 +1,76 @@ +//===- ChainedIncludesSource.h - Chained PCHs in Memory ---------*- 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 ChainedIncludesSource class, which converts headers +// to chained PCHs in memory, mainly used for testing. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SERIALIZATION_CHAINEDINCLUDESSOURCE_H +#define LLVM_CLANG_SERIALIZATION_CHAINEDINCLUDESSOURCE_H + +#include "clang/Sema/ExternalSemaSource.h" +#include <vector> + +namespace clang { + class CompilerInstance; + +class ChainedIncludesSource : public ExternalSemaSource { +public: + virtual ~ChainedIncludesSource(); + + static ChainedIncludesSource *create(CompilerInstance &CI); + +private: + ExternalSemaSource &getFinalReader() const { return *FinalReader; } + + std::vector<CompilerInstance *> CIs; + llvm::OwningPtr<ExternalSemaSource> FinalReader; + + +protected: + +//===----------------------------------------------------------------------===// +// ExternalASTSource interface. +//===----------------------------------------------------------------------===// + + virtual Decl *GetExternalDecl(uint32_t ID); + virtual Selector GetExternalSelector(uint32_t ID); + virtual uint32_t GetNumExternalSelectors(); + virtual Stmt *GetExternalDeclStmt(uint64_t Offset); + virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); + virtual DeclContextLookupResult + FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); + virtual void MaterializeVisibleDecls(const DeclContext *DC); + virtual bool FindExternalLexicalDecls(const DeclContext *DC, + bool (*isKindWeWant)(Decl::Kind), + llvm::SmallVectorImpl<Decl*> &Result); + virtual void CompleteType(TagDecl *Tag); + virtual void CompleteType(ObjCInterfaceDecl *Class); + virtual void StartedDeserializing(); + virtual void FinishedDeserializing(); + virtual void StartTranslationUnit(ASTConsumer *Consumer); + virtual void PrintStats(); + + /// Return the amount of memory used by memory buffers, breaking down + /// by heap-backed versus mmap'ed memory. + virtual void getMemoryBufferSizes(MemoryBufferSizes &sizes) const; + +//===----------------------------------------------------------------------===// +// ExternalSemaSource interface. +//===----------------------------------------------------------------------===// + + virtual void InitializeSema(Sema &S); + virtual void ForgetSema(); + virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel); + virtual bool LookupUnqualified(LookupResult &R, Scope *S); +}; + +} + +#endif diff --git a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td index e452ccfb6ceb..11f1e5d4bd51 100644 --- a/include/clang/StaticAnalyzer/Checkers/CheckerBase.td +++ b/include/clang/StaticAnalyzer/Checkers/CheckerBase.td @@ -11,18 +11,19 @@ // //===----------------------------------------------------------------------===// +class CheckerGroup<string name> { + string GroupName = name; +} +class InGroup<CheckerGroup G> { CheckerGroup Group = G; } + class Package<string name> { string PackageName = name; bit Hidden = 0; Package ParentPackage; + CheckerGroup Group; } class InPackage<Package P> { Package ParentPackage = P; } -class CheckerGroup<string name> { - string GroupName = name; -} -class InGroup<CheckerGroup G> { CheckerGroup Group = G; } - // All checkers are an indirect subclass of this. class Checker<string name = ""> { string CheckerName = name; diff --git a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h index afba12dc0620..2a3d43e22325 100644 --- a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h +++ b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h @@ -39,8 +39,6 @@ class ExprEngine; TransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled, const LangOptions& lopts); -void RegisterExperimentalChecks(ExprEngine &Eng); - void RegisterCallInliner(ExprEngine &Eng); } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 93d795831d3c..3acbcd685bc0 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -126,7 +126,7 @@ public: /// getLocation - Return the "definitive" location of the reported bug. /// While a bug can span an entire path, usually there is a specific - /// location that can be used to identify where the key issue occured. + /// location that can be used to identify where the key issue occurred. /// This location is used by clients rendering diagnostics. virtual SourceLocation getLocation() const; @@ -219,6 +219,18 @@ public: virtual std::pair<ranges_iterator, ranges_iterator> getRanges() const { return std::make_pair(Ranges.begin(), Ranges.end()); } + + virtual void Profile(llvm::FoldingSetNodeID& hash) const { + BugReport::Profile(hash); + for (llvm::SmallVectorImpl<SourceRange>::const_iterator I = + Ranges.begin(), E = Ranges.end(); I != E; ++I) { + const SourceRange range = *I; + if (!range.isValid()) + continue; + hash.AddInteger(range.getBegin().getRawEncoding()); + hash.AddInteger(range.getEnd().getRawEncoding()); + } + } }; class EnhancedBugReport : public RangedBugReport { diff --git a/include/clang/StaticAnalyzer/Core/CheckerV2.h b/include/clang/StaticAnalyzer/Core/Checker.h index e080d190ab75..8c2ffc690887 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerV2.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -1,4 +1,4 @@ -//== CheckerV2.h - Registration mechanism for checkers -----------*- C++ -*--=// +//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,15 @@ // //===----------------------------------------------------------------------===// // -// This file defines CheckerV2, used to create and register checkers. +// This file defines Checker, used to create and register checkers. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SA_CORE_CHECKERV2 -#define LLVM_CLANG_SA_CORE_CHECKERV2 +#ifndef LLVM_CLANG_SA_CORE_CHECKER +#define LLVM_CLANG_SA_CORE_CHECKER #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/Support/Casting.h" namespace clang { @@ -145,6 +146,21 @@ public: } }; +class Bind { + template <typename CHECKER> + static void _checkBind(void *checker, const SVal &location, const SVal &val, + CheckerContext &C) { + ((const CHECKER *)checker)->checkBind(location, val, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForBind( + CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); + } +}; + class EndAnalysis { template <typename CHECKER> static void _checkEndAnalysis(void *checker, ExplodedGraph &G, @@ -175,6 +191,22 @@ public: } }; +class BranchCondition { + template <typename CHECKER> + static void _checkBranchCondition(void *checker, const Stmt *condition, + BranchNodeBuilder &B, ExprEngine &Eng) { + ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForBranchCondition( + CheckerManager::CheckBranchConditionFunc(checker, + _checkBranchCondition<CHECKER>)); + } +}; + class LiveSymbols { template <typename CHECKER> static void _checkLiveSymbols(void *checker, const GRState *state, @@ -228,10 +260,39 @@ public: } }; +template <typename EVENT> +class Event { + template <typename CHECKER> + static void _checkEvent(void *checker, const void *event) { + ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); + } +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerListenerForEvent<EVENT>( + CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); + } +}; + } // end check namespace namespace eval { +class Assume { + template <typename CHECKER> + static const GRState *_evalAssume(void *checker, const GRState *state, + const SVal &cond, bool assumption) { + return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEvalAssume( + CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); + } +}; + class Call { template <typename CHECKER> static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { @@ -254,25 +315,58 @@ template <typename CHECK1, typename CHECK2=check::_VoidCheck, typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck> -class CheckerV2 { +class Checker; + +template <> +class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, + check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, + check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, + check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> { +public: + static void _register(void *checker, CheckerManager &mgr) { } +}; + +template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, + typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, + typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12> +class Checker + : public CHECK1, + public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, + CHECK9, CHECK10, CHECK11, CHECK12> { public: template <typename CHECKER> static void _register(CHECKER *checker, CheckerManager &mgr) { CHECK1::_register(checker, mgr); - CHECK2::_register(checker, mgr); - CHECK3::_register(checker, mgr); - CHECK4::_register(checker, mgr); - CHECK5::_register(checker, mgr); - CHECK6::_register(checker, mgr); - CHECK7::_register(checker, mgr); - CHECK8::_register(checker, mgr); - CHECK9::_register(checker, mgr); - CHECK10::_register(checker, mgr); - CHECK11::_register(checker, mgr); - CHECK12::_register(checker, mgr); + Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9, + CHECK10, CHECK11,CHECK12>::_register(checker, mgr); + } +}; + +template <typename EVENT> +class EventDispatcher { + CheckerManager *Mgr; +public: + EventDispatcher() : Mgr(0) { } + + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerDispatcherForEvent<EVENT>(); + static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; + } + + void dispatchEvent(const EVENT &event) const { + Mgr->_dispatchEvent(event); } }; +/// \brief We dereferenced a location that may be null. +struct ImplicitNullDerefEvent { + SVal Location; + bool IsLoad; + ExplodedNode *SinkNode; + BugReporter *BR; +}; + } // end ento namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 276819549d1a..92ec0388e500 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -37,6 +37,7 @@ namespace ento { class ExplodedGraph; class GRState; class EndOfFunctionNodeBuilder; + class BranchNodeBuilder; class MemRegion; class SymbolReaper; @@ -46,47 +47,46 @@ public: virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0; }; -struct VoidCheckerFnParm {}; -template <typename P1=VoidCheckerFnParm, typename P2=VoidCheckerFnParm, - typename P3=VoidCheckerFnParm, typename P4=VoidCheckerFnParm> -class CheckerFn { - typedef void (*Func)(void *, P1, P2, P3, P4); +template <typename T> class CheckerFn; + +template <typename RET, typename P1, typename P2, typename P3> +class CheckerFn<RET(P1, P2, P3)> { + typedef RET (*Func)(void *, P1, P2, P3); Func Fn; public: void *Checker; CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } - void operator()(P1 p1, P2 p2, P3 p3, P4 p4) { Fn(Checker, p1, p2, p3, p4); } + RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); } }; -template <typename P1, typename P2, typename P3> -class CheckerFn<P1, P2, P3, VoidCheckerFnParm> { - typedef void (*Func)(void *, P1, P2, P3); +template <typename RET, typename P1, typename P2> +class CheckerFn<RET(P1, P2)> { + typedef RET (*Func)(void *, P1, P2); Func Fn; public: void *Checker; CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } - void operator()(P1 p1, P2 p2, P3 p3) { Fn(Checker, p1, p2, p3); } + RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); } }; -template <typename P1, typename P2> -class CheckerFn<P1, P2, VoidCheckerFnParm, VoidCheckerFnParm> { - typedef void (*Func)(void *, P1, P2); +template <typename RET, typename P1> +class CheckerFn<RET(P1)> { + typedef RET (*Func)(void *, P1); Func Fn; public: void *Checker; CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } - void operator()(P1 p1, P2 p2) { Fn(Checker, p1, p2); } + RET operator()(P1 p1) const { return Fn(Checker, p1); } }; -template <> -class CheckerFn<VoidCheckerFnParm, VoidCheckerFnParm, VoidCheckerFnParm, - VoidCheckerFnParm> { - typedef void (*Func)(void *); +template <typename RET> +class CheckerFn<RET()> { + typedef RET (*Func)(void *); Func Fn; public: void *Checker; CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { } - void operator()() { Fn(Checker); } + RET operator()() const { return Fn(Checker); } }; class CheckerManager { @@ -96,21 +96,35 @@ public: CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { } ~CheckerManager(); + bool hasPathSensitiveCheckers() const; + + void finishedCheckerRegistration(); + const LangOptions &getLangOptions() const { return LangOpts; } typedef void *CheckerRef; - typedef CheckerFn<> CheckerDtor; + typedef void *CheckerTag; + typedef CheckerFn<void ()> CheckerDtor; //===----------------------------------------------------------------------===// // registerChecker //===----------------------------------------------------------------------===// /// \brief Used to register checkers. + /// + /// \returns a pointer to the checker object. template <typename CHECKER> - void registerChecker() { + CHECKER *registerChecker() { + CheckerTag tag = getTag<CHECKER>(); + CheckerRef &ref = CheckerTags[tag]; + if (ref) + return static_cast<CHECKER *>(ref); // already registered. + CHECKER *checker = new CHECKER(); CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); CHECKER::_register(checker, *this); + ref = checker; + return checker; } //===----------------------------------------------------------------------===// @@ -179,6 +193,12 @@ public: const Stmt *S, ExprEngine &Eng); + /// \brief Run checkers for binding of a value to a location. + void runCheckersForBind(ExplodedNodeSet &Dst, + const ExplodedNodeSet &Src, + SVal location, SVal val, + const Stmt *S, ExprEngine &Eng); + /// \brief Run checkers for end of analysis. void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng); @@ -186,6 +206,10 @@ public: /// \brief Run checkers for end of path. void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng); + /// \brief Run checkers for branch condition. + void runCheckersForBranchCondition(const Stmt *condition, + BranchNodeBuilder &B, ExprEngine &Eng); + /// \brief Run checkers for live symbols. void runCheckersForLiveSymbols(const GRState *state, SymbolReaper &SymReaper); @@ -204,6 +228,10 @@ public: const MemRegion * const *Begin, const MemRegion * const *End); + /// \brief Run checkers for handling assumptions on symbolic values. + const GRState *runCheckersForEvalAssume(const GRState *state, + SVal Cond, bool Assumption); + /// \brief Run checkers for evaluating a call. void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, @@ -217,9 +245,8 @@ public: // Functions used by the registration mechanism, checkers should not touch // these directly. - typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &> + typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)> CheckDeclFunc; - typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc; typedef bool (*HandlesDeclFunc)(const Decl *D); void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); @@ -230,14 +257,44 @@ public: // Internal registration functions for path-sensitive checking. //===----------------------------------------------------------------------===// - typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc; - typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &> + typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc; + + typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)> + CheckObjCMessageFunc; + + typedef CheckerFn<void (const SVal &location, bool isLoad, CheckerContext &)> CheckLocationFunc; - typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &> + + typedef CheckerFn<void (const SVal &location, const SVal &val, + CheckerContext &)> CheckBindFunc; + + typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)> CheckEndAnalysisFunc; - typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc; - typedef CheckerFn<SymbolReaper &, CheckerContext &> CheckDeadSymbolsFunc; - typedef CheckerFn<const GRState *, SymbolReaper &> CheckLiveSymbolsFunc; + + typedef CheckerFn<void (EndOfFunctionNodeBuilder &, ExprEngine &)> + CheckEndPathFunc; + + typedef CheckerFn<void (const Stmt *, BranchNodeBuilder &, ExprEngine &)> + CheckBranchConditionFunc; + + typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> + CheckDeadSymbolsFunc; + + typedef CheckerFn<void (const GRState *,SymbolReaper &)> CheckLiveSymbolsFunc; + + typedef CheckerFn<const GRState * (const GRState *, + const MemRegion * const *begin, + const MemRegion * const *end)> + CheckRegionChangesFunc; + + typedef CheckerFn<bool (const GRState *)> WantsRegionChangeUpdateFunc; + + typedef CheckerFn<const GRState * (const GRState *, + const SVal &cond, bool assumption)> + EvalAssumeFunc; + + typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> + EvalCallFunc; typedef bool (*HandlesStmtFunc)(const Stmt *D); void _registerForPreStmt(CheckStmtFunc checkfn, @@ -250,58 +307,55 @@ public: void _registerForLocation(CheckLocationFunc checkfn); + void _registerForBind(CheckBindFunc checkfn); + void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); void _registerForEndPath(CheckEndPathFunc checkfn); + void _registerForBranchCondition(CheckBranchConditionFunc checkfn); + void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); - class CheckRegionChangesFunc { - typedef const GRState * (*Func)(void *, const GRState *, - const MemRegion * const *, - const MemRegion * const *); - Func Fn; - public: - void *Checker; - CheckRegionChangesFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {} - const GRState *operator()(const GRState *state, - const MemRegion * const *begin, - const MemRegion * const *end) { - return Fn(Checker, state, begin, end); - } - }; - - class WantsRegionChangeUpdateFunc { - typedef bool (*Func)(void *, const GRState *); - Func Fn; - public: - void *Checker; - WantsRegionChangeUpdateFunc(void *checker, Func fn) - : Fn(fn), Checker(checker) { } - bool operator()(const GRState *state) { - return Fn(Checker, state); - } - }; - void _registerForRegionChanges(CheckRegionChangesFunc checkfn, WantsRegionChangeUpdateFunc wantUpdateFn); - class EvalCallFunc { - typedef bool (*Func)(void *, const CallExpr *, CheckerContext &); - Func Fn; - public: - void *Checker; - EvalCallFunc(void *checker, Func fn) : Fn(fn), Checker(checker) { } - bool operator()(const CallExpr *CE, CheckerContext &C) { - return Fn(Checker, CE, C); - } - }; + void _registerForEvalAssume(EvalAssumeFunc checkfn); void _registerForEvalCall(EvalCallFunc checkfn); //===----------------------------------------------------------------------===// +// Internal registration functions for events. +//===----------------------------------------------------------------------===// + + typedef void *EventTag; + typedef CheckerFn<void (const void *event)> CheckEventFunc; + + template <typename EVENT> + void _registerListenerForEvent(CheckEventFunc checkfn) { + EventInfo &info = Events[getTag<EVENT>()]; + info.Checkers.push_back(checkfn); + } + + template <typename EVENT> + void _registerDispatcherForEvent() { + EventInfo &info = Events[getTag<EVENT>()]; + info.HasDispatcher = true; + } + + template <typename EVENT> + void _dispatchEvent(const EVENT &event) const { + EventsTy::const_iterator I = Events.find(getTag<EVENT>()); + if (I == Events.end()) + return; + const EventInfo &info = I->second; + for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i) + info.Checkers[i](&event); + } + +//===----------------------------------------------------------------------===// // Implementation details. //===----------------------------------------------------------------------===// @@ -309,6 +363,11 @@ private: template <typename CHECKER> static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); } + template <typename T> + static void *getTag() { static int tag; return &tag; } + + llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags; + std::vector<CheckerDtor> CheckerDtors; struct DeclCheckerInfo { @@ -365,10 +424,14 @@ private: std::vector<CheckLocationFunc> LocationCheckers; + std::vector<CheckBindFunc> BindCheckers; + std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers; std::vector<CheckEndPathFunc> EndPathCheckers; + std::vector<CheckBranchConditionFunc> BranchConditionCheckers; + std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; @@ -379,7 +442,18 @@ private: }; std::vector<RegionChangesCheckerInfo> RegionChangesCheckers; + std::vector<EvalAssumeFunc> EvalAssumeCheckers; + std::vector<EvalCallFunc> EvalCallCheckers; + + struct EventInfo { + llvm::SmallVector<CheckEventFunc, 4> Checkers; + bool HasDispatcher; + EventInfo() : HasDispatcher(false) { } + }; + + typedef llvm::DenseMap<EventTag, EventInfo> EventsTy; + EventsTy Events; }; } // end ento namespace diff --git a/include/clang/StaticAnalyzer/Core/CheckerProvider.h b/include/clang/StaticAnalyzer/Core/CheckerProvider.h index 40b838e75886..b8aaaa1a04c0 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerProvider.h +++ b/include/clang/StaticAnalyzer/Core/CheckerProvider.h @@ -15,7 +15,6 @@ #define LLVM_CLANG_SA_CORE_CHECKERPROVIDER_H #include "llvm/ADT/StringRef.h" -#include <vector> namespace llvm { class raw_ostream; diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h index 2713e31fc0d1..d02228fa30dd 100644 --- a/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h +++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticClients.h @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H -#define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLiENTS_H +#define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H #include <string> diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index a4327e127f5f..65fbfcc912f9 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -16,6 +16,7 @@ #ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H #define LLVM_CLANG_GR_BASICVALUEFACTORY_H +#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/AST/ASTContext.h" #include "llvm/ADT/FoldingSet.h" @@ -47,16 +48,17 @@ public: }; class LazyCompoundValData : public llvm::FoldingSetNode { - const void *store; + StoreRef store; const TypedRegion *region; public: - LazyCompoundValData(const void *st, const TypedRegion *r) + LazyCompoundValData(const StoreRef &st, const TypedRegion *r) : store(st), region(r) {} - const void *getStore() const { return store; } + const void *getStore() const { return store.getStore(); } const TypedRegion *getRegion() const { return region; } - static void Profile(llvm::FoldingSetNodeID& ID, const void *store, + static void Profile(llvm::FoldingSetNodeID& ID, + const StoreRef &store, const TypedRegion *region); void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); } @@ -170,7 +172,7 @@ public: const CompoundValData *getCompoundValData(QualType T, llvm::ImmutableList<SVal> Vals); - const LazyCompoundValData *getLazyCompoundValData(const void *store, + const LazyCompoundValData *getLazyCompoundValData(const StoreRef &store, const TypedRegion *region); llvm::ImmutableList<SVal> getEmptySValList() { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h deleted file mode 100644 index 627bc0ab3516..000000000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Checker.h +++ /dev/null @@ -1,166 +0,0 @@ -//== Checker.h - Abstract interface for checkers -----------------*- 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 Checker and CheckerVisitor, classes used for creating -// domain-specific checks. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_CHECKER -#define LLVM_CLANG_GR_CHECKER - -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" - -//===----------------------------------------------------------------------===// -// Checker interface. -//===----------------------------------------------------------------------===// - -namespace clang { - -namespace ento { - -class Checker { -private: - friend class ExprEngine; - - // FIXME: Remove the 'tag' option. - void GR_Visit(ExplodedNodeSet &Dst, - StmtNodeBuilder &Builder, - ExprEngine &Eng, - const Stmt *S, - ExplodedNode *Pred, void *tag, bool isPrevisit, - bool& respondsToCallback) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind, &respondsToCallback, S); - if (isPrevisit) - _PreVisit(C, S); - else - _PostVisit(C, S); - } - - void GR_visitObjCMessage(ExplodedNodeSet &Dst, - StmtNodeBuilder &Builder, - ExprEngine &Eng, - const ObjCMessage &msg, - ExplodedNode *Pred, void *tag, bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind, 0, msg.getOriginExpr()); - if (isPrevisit) - preVisitObjCMessage(C, msg); - else - postVisitObjCMessage(C, msg); - } - - bool GR_evalNilReceiver(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder, - ExprEngine &Eng, const ObjCMessage &msg, - ExplodedNode *Pred, const GRState *state, void *tag) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, - 0, msg.getOriginExpr(), state); - return evalNilReceiver(C, msg); - } - - bool GR_evalCallExpr(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder, - ExprEngine &Eng, const CallExpr *CE, - ExplodedNode *Pred, void *tag) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, - 0, CE); - return evalCallExpr(C, CE); - } - - // FIXME: Remove the 'tag' option. - void GR_VisitBind(ExplodedNodeSet &Dst, - StmtNodeBuilder &Builder, ExprEngine &Eng, - const Stmt *StoreE, ExplodedNode *Pred, void *tag, - SVal location, SVal val, - bool isPrevisit) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind, 0, StoreE); - assert(isPrevisit && "Only previsit supported for now."); - PreVisitBind(C, StoreE, location, val); - } - - // FIXME: Remove the 'tag' option. - void GR_visitLocation(ExplodedNodeSet &Dst, - StmtNodeBuilder &Builder, - ExprEngine &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, 0, S, state); - visitLocation(C, S, location, isLoad); - } - - void GR_evalDeadSymbols(ExplodedNodeSet &Dst, StmtNodeBuilder &Builder, - ExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, - SymbolReaper &SymReaper, void *tag) { - CheckerContext C(Dst, Builder, Eng, Pred, tag, - ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); - evalDeadSymbols(C, SymReaper); - } - -public: - virtual ~Checker(); - virtual void _PreVisit(CheckerContext &C, const Stmt *S) {} - virtual void _PostVisit(CheckerContext &C, const Stmt *S) {} - virtual void preVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {} - virtual void postVisitObjCMessage(CheckerContext &C, ObjCMessage msg) {} - virtual void visitLocation(CheckerContext &C, const Stmt *S, SVal location, - bool isLoad) {} - virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE, - SVal location, SVal val) {} - virtual void evalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {} - virtual void evalEndPath(EndOfFunctionNodeBuilder &B, void *tag, - ExprEngine &Eng) {} - - virtual void MarkLiveSymbols(const GRState *state, SymbolReaper &SymReaper) {} - - virtual void VisitBranchCondition(BranchNodeBuilder &Builder, - ExprEngine &Eng, - const Stmt *Condition, void *tag) {} - - virtual bool evalNilReceiver(CheckerContext &C, ObjCMessage msg) { - return false; - } - - virtual bool evalCallExpr(CheckerContext &C, const CallExpr *CE) { - return false; - } - - virtual const GRState *evalAssume(const GRState *state, SVal Cond, - bool Assumption, bool *respondsToCallback) { - *respondsToCallback = false; - return state; - } - - virtual bool wantsRegionChangeUpdate(const GRState *state) { return false; } - - virtual const GRState *EvalRegionChanges(const GRState *state, - const MemRegion * const *Begin, - const MemRegion * const *End, - bool *respondsToCallback) { - *respondsToCallback = false; - return state; - } - - virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, - ExprEngine &Eng) {} -}; - -} // end GR namespace - -} // end clang namespace - -#endif - diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def deleted file mode 100644 index 9b3c263e7d53..000000000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def +++ /dev/null @@ -1,48 +0,0 @@ -//===-- CheckerVisitor.def - Metadata for CheckerVisitor ----------------*-===// -// -// 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 AST nodes accepted by the CheckerVisitor class. -// -//===---------------------------------------------------------------------===// - -#ifndef PREVISIT -#define PREVISIT(NODE, FALLBACK) -#endif - -#ifndef POSTVISIT -#define POSTVISIT(NODE, FALLBACK) -#endif - -PREVISIT(ArraySubscriptExpr, Stmt) -PREVISIT(BinaryOperator, Stmt) -PREVISIT(CallExpr, GenericCall) -PREVISIT(CompoundAssignOperator, BinaryOperator) -PREVISIT(CStyleCastExpr, CastExpr) -PREVISIT(CXXConstCastExpr, CastExpr) -PREVISIT(CXXDynamicCastExpr, CastExpr) -PREVISIT(CXXFunctionalCastExpr, CastExpr) -PREVISIT(CXXOperatorCallExpr, GenericCall) -PREVISIT(CXXMemberCallExpr, GenericCall) -PREVISIT(CXXReinterpretCastExpr, CastExpr) -PREVISIT(CXXStaticCastExpr, CastExpr) -PREVISIT(DeclStmt, Stmt) -PREVISIT(ImplicitCastExpr, CastExpr) -PREVISIT(ObjCAtSynchronizedStmt, Stmt) -PREVISIT(ReturnStmt, Stmt) - -POSTVISIT(BlockExpr, Stmt) -POSTVISIT(BinaryOperator, Stmt) -POSTVISIT(CallExpr, GenericCall) -POSTVISIT(CompoundAssignOperator, BinaryOperator) -POSTVISIT(CXXOperatorCallExpr, GenericCall) -POSTVISIT(CXXMemberCallExpr, GenericCall) -POSTVISIT(ObjCIvarRefExpr, Stmt) - -#undef PREVISIT -#undef POSTVISIT diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h deleted file mode 100644 index dc76c9604741..000000000000 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h +++ /dev/null @@ -1,103 +0,0 @@ -//== CheckerVisitor.h - Abstract visitor for checkers ------------*- 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 CheckerVisitor. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_GR_CHECKERVISITOR -#define LLVM_CLANG_GR_CHECKERVISITOR -#include "clang/StaticAnalyzer/Core/PathSensitive/Checker.h" - -namespace clang { - -namespace ento { - -//===----------------------------------------------------------------------===// -// Checker visitor interface. Used by subclasses of Checker to specify their -// own checker visitor logic. -//===----------------------------------------------------------------------===// - -/// CheckerVisitor - This class implements a simple visitor for Stmt subclasses. -/// Since Expr derives from Stmt, this also includes support for visiting Exprs. -template<typename ImplClass> -class CheckerVisitor : public Checker { -public: - 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) { - switch (S->getStmtClass()) { - default: - assert(false && "Unsupport statement."); - return; - -#define PREVISIT(NAME, FALLBACK) \ -case Stmt::NAME ## Class:\ -static_cast<ImplClass*>(this)->PreVisit ## NAME(C,static_cast<const NAME*>(S));\ -break; -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def" - } - } - - void PostVisit(CheckerContext &C, const Stmt *S) { - switch (S->getStmtClass()) { - default: - assert(false && "Unsupport statement."); - return; - -#define POSTVISIT(NAME, FALLBACK) \ -case Stmt::NAME ## Class:\ -static_cast<ImplClass*>(this)->\ -PostVisit ## NAME(C,static_cast<const NAME*>(S));\ -break; -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def" - } - } - - void PreVisitGenericCall(CheckerContext &C, const CallExpr *CE) { - static_cast<ImplClass*>(this)->PreVisitStmt(C, CE); - } - void PostVisitGenericCall(CheckerContext &C, const CallExpr *CE) { - static_cast<ImplClass*>(this)->PostVisitStmt(C, CE); - } - - void PreVisitStmt(CheckerContext &C, const Stmt *S) { - *C.respondsToCallback = false; - } - - void PostVisitStmt(CheckerContext &C, const Stmt *S) { - *C.respondsToCallback = false; - } - - void PreVisitCastExpr(CheckerContext &C, const CastExpr *E) { - static_cast<ImplClass*>(this)->PreVisitStmt(C, E); - } - -#define PREVISIT(NAME, FALLBACK) \ -void PreVisit ## NAME(CheckerContext &C, const NAME* S) {\ - static_cast<ImplClass*>(this)->PreVisit ## FALLBACK(C, S);\ -} -#define POSTVISIT(NAME, FALLBACK) \ -void PostVisit ## NAME(CheckerContext &C, const NAME* S) {\ - static_cast<ImplClass*>(this)->PostVisit ## FALLBACK(C, S);\ -} -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.def" -}; - -} // end GR namespace - -} // end clang namespace - -#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 25c644734232..2c1d07c59b68 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -47,7 +47,11 @@ class CoreEngine { public: typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> > + BlocksExhausted; + + typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> > BlocksAborted; + private: SubEngine& SubEng; @@ -67,6 +71,10 @@ private: /// The locations where we stopped doing work because we visited a location /// too many times. + BlocksExhausted blocksExhausted; + + /// The locations where we stopped because the engine aborted analysis, + /// usually because it could not reason about something. BlocksAborted blocksAborted; void generateNode(const ProgramPoint& Loc, const GRState* State, @@ -110,7 +118,7 @@ public: ExplodedGraph& getGraph() { return *G.get(); } /// takeGraph - Returns the exploded graph. Ownership of the graph is - /// transfered to the caller. + /// transferred to the caller. ExplodedGraph* takeGraph() { return G.take(); } /// ExecuteWorkList - Run the worklist algorithm for a maximum number of @@ -123,10 +131,25 @@ public: // Functions for external checking of whether we have unfinished work bool wasBlockAborted() const { return !blocksAborted.empty(); } - bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); } - + bool wasBlocksExhausted() const { return !blocksExhausted.empty(); } + bool hasWorkRemaining() const { return wasBlocksExhausted() || + WList->hasWork() || + wasBlockAborted(); } + + /// Inform the CoreEngine that a basic block was aborted because + /// it could not be completely analyzed. + void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) { + blocksAborted.push_back(std::make_pair(block, node)); + } + WorkList *getWorkList() const { return WList; } + BlocksExhausted::const_iterator blocks_exhausted_begin() const { + return blocksExhausted.begin(); + } + BlocksExhausted::const_iterator blocks_exhausted_end() const { + return blocksExhausted.end(); + } BlocksAborted::const_iterator blocks_aborted_begin() const { return blocksAborted.begin(); } @@ -219,11 +242,8 @@ public: /// getStmt - Return the current block-level expression associated with /// this builder. const Stmt* getStmt() const { - CFGStmt CS = B[Idx].getAs<CFGStmt>(); - if (CS) - return CS.getStmt(); - else - return 0; + const CFGStmt *CS = B[Idx].getAs<CFGStmt>(); + return CS ? CS->getStmt() : 0; } /// getBlock - Return the CFGBlock associated with the block-level expression @@ -287,6 +307,8 @@ public: BlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} + ExplodedNode* generateNode(const Stmt *Condition, const GRState* State); + ExplodedNode* generateNode(const GRState* State, bool branch); const CFGBlock* getTargetBlock(bool branch) const { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index 732a40cb2145..193056e6b030 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -51,9 +51,10 @@ public: iterator end() const { return ExprBindings.end(); } - /// GetSVal - Fetches the current binding of the expression in the + /// getSVal - Fetches the current binding of the expression in the /// Environment. - SVal getSVal(const Stmt* Ex, SValBuilder& svalBuilder) const; + SVal getSVal(const Stmt* Ex, SValBuilder& svalBuilder, + bool useOnlyDirectBindings = false) const; /// Profile - Profile the contents of an Environment object for use /// in a FoldingSet. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 16f54ee7468d..8cd743f68f56 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -34,7 +34,6 @@ class ObjCForCollectionStmt; namespace ento { class AnalysisManager; -class Checker; class ExprEngine : public SubEngine { AnalysisManager &AMgr; @@ -74,39 +73,6 @@ class ExprEngine : public SubEngine { Selector* NSExceptionInstanceRaiseSelectors; Selector RaiseSel; - enum CallbackKind { - PreVisitStmtCallback, - PostVisitStmtCallback, - processAssumeCallback, - EvalRegionChangesCallback - }; - - typedef uint32_t CallbackTag; - - /// GetCallbackTag - Create a tag for a certain kind of callback. The 'Sub' - /// argument can be used to differentiate callbacks that depend on another - /// value from a small set of possibilities, such as statement classes. - static inline CallbackTag GetCallbackTag(CallbackKind K, uint32_t Sub = 0) { - assert(Sub == ((Sub << 8) >> 8) && "Tag sub-kind must fit into 24 bits"); - return K | (Sub << 8); - } - - typedef llvm::DenseMap<void *, unsigned> CheckerMap; - typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered; - typedef llvm::DenseMap<CallbackTag, CheckersOrdered *> CheckersOrderedCache; - - /// A registration map from checker tag to the index into the - /// ordered checkers vector. - CheckerMap CheckerM; - - /// An ordered vector of checkers that are called when evaluating - /// various expressions and statements. - CheckersOrdered Checkers; - - /// A map used for caching the checkers that respond to the callback for - /// a particular callback tag. - CheckersOrderedCache COCache; - /// The BugReporter associated with this engine. It is important that /// this object be placed at the very end of member variables so that its /// destructor is called before the rest of the ExprEngine is destroyed. @@ -165,21 +131,6 @@ public: ExplodedGraph& getGraph() { return G; } const ExplodedGraph& getGraph() const { return G; } - template <typename CHECKER> - void registerCheck(CHECKER *check) { - unsigned entry = Checkers.size(); - void *tag = CHECKER::getTag(); - Checkers.push_back(std::make_pair(tag, check)); - CheckerM[tag] = entry; - } - - Checker *lookupChecker(void *tag) const; - - template <typename CHECKER> - CHECKER *getChecker() const { - return static_cast<CHECKER*>(lookupChecker(CHECKER::getTag())); - } - /// processCFGElement - Called by CoreEngine. Used to generate new successor /// nodes by processing the 'effects' of a CFG element. void processCFGElement(const CFGElement E, StmtNodeBuilder& builder); @@ -262,11 +213,9 @@ public: const SymbolManager& getSymbolManager() const { return SymMgr; } // Functions for external checking of whether we have unfinished work - bool wasBlockAborted() const { return Engine.wasBlockAborted(); } + bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); } bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); } - bool hasWorkRemaining() const { - return wasBlockAborted() || Engine.getWorkList()->hasWork(); - } + bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); } const CoreEngine &getCoreEngine() const { return Engine; } @@ -281,27 +230,6 @@ public: ProgramPoint::Kind K = ProgramPoint::PostStmtKind, const void *tag = 0); - /// CheckerVisit - Dispatcher for performing checker-specific logic - /// at specific statements. - void CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, - CallbackKind Kind); - - void CheckerVisitObjCMessage(const ObjCMessage &msg, ExplodedNodeSet &Dst, - ExplodedNodeSet &Src, bool isPrevisit); - - bool CheckerEvalCall(const CallExpr *CE, - ExplodedNodeSet &Dst, - ExplodedNode *Pred); - - void CheckerEvalNilReceiver(const ObjCMessage &msg, - ExplodedNodeSet &Dst, - const GRState *state, - ExplodedNode *Pred); - - void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst, - ExplodedNodeSet &Src, SVal location, SVal val, - bool isPrevisit); - /// Visit - Transfer function logic for all statements. Dispatches to /// other functions that handle specific kinds of statements. void Visit(const Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -334,10 +262,8 @@ public: /// VisitCall - Transfer function for function calls. - void VisitCall(const CallExpr* CE, ExplodedNode* Pred, - CallExpr::const_arg_iterator AI, - CallExpr::const_arg_iterator AE, - ExplodedNodeSet& Dst); + void VisitCallExpr(const CallExpr* CE, ExplodedNode* Pred, + ExplodedNodeSet& Dst); /// VisitCast - Transfer function logic for all casts (implicit and explicit). void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, @@ -358,11 +284,6 @@ public: /// VisitGuardedExpr - Transfer function logic for ?, __builtin_choose void VisitGuardedExpr(const Expr* Ex, const Expr* L, const Expr* R, ExplodedNode* Pred, ExplodedNodeSet& Dst); - - /// VisitCondInit - Transfer function for handling the initialization - /// of a condition variable in an IfStmt, SwitchStmt, etc. - void VisitCondInit(const VarDecl *VD, const Stmt *S, ExplodedNode *Pred, - ExplodedNodeSet& Dst); void VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -409,9 +330,9 @@ public: void VisitOffsetOfExpr(const OffsetOfExpr* Ex, ExplodedNode* Pred, ExplodedNodeSet& Dst); - /// VisitSizeOfAlignOfExpr - Transfer function for sizeof. - void VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex, ExplodedNode* Pred, - ExplodedNodeSet& Dst); + /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof. + void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr* Ex, + ExplodedNode* Pred, ExplodedNodeSet& Dst); /// VisitUnaryOperator - Transfer function logic for unary operators. void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode* Pred, @@ -432,12 +353,6 @@ public: const MemRegion *Dest, const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, - ExplodedNodeSet &Dst); - - void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *C, - ExplodedNode *Pred, ExplodedNodeSet &Dst); - void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -463,12 +378,10 @@ public: const FunctionProtoType *FnType, ExplodedNode *Pred, ExplodedNodeSet &Dst, bool FstArgAsLValue = false); - - /// Evaluate method call itself. Used for CXXMethodCallExpr and - /// CXXOperatorCallExpr. - void evalMethodCall(const CallExpr *MCE, const CXXMethodDecl *MD, - const Expr *ThisExpr, ExplodedNode *Pred, - ExplodedNodeSet &Src, ExplodedNodeSet &Dst); + + /// Evaluate callee expression (for a function call). + void evalCallee(const CallExpr *callExpr, const ExplodedNodeSet &src, + ExplodedNodeSet &dest); /// evalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic /// expressions of the form 'x != 0' and generate new nodes (stored in Dst) diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h index 37694da6573c..a957c897b92a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/GRState.h @@ -35,7 +35,6 @@ class ASTContext; namespace ento { class GRStateManager; -class Checker; typedef ConstraintManager* (*ConstraintManagerCreator)(GRStateManager&, SubEngine&); @@ -261,7 +260,7 @@ public: const llvm::APSInt *getSymVal(SymbolRef sym) const; /// Returns the SVal bound to the statement 'S' in the state's environment. - SVal getSVal(const Stmt* S) const; + SVal getSVal(const Stmt* S, bool useOnlyDirectBindings = false) const; SVal getSValAsScalarOrLoc(const Stmt *Ex) const; @@ -274,8 +273,6 @@ public: SVal getSValAsScalarOrLoc(const MemRegion *R) const; - const llvm::APSInt *getSymVal(SymbolRef sym); - bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const; bool scanReachableSymbols(const SVal *I, const SVal *E, @@ -627,10 +624,6 @@ public: // Out-of-line method definitions for GRState. //===----------------------------------------------------------------------===// -inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) { - return getStateManager().getSymVal(this, sym); -} - inline const VarRegion* GRState::getRegion(const VarDecl *D, const LocationContext *LC) const { return getStateManager().getRegionManager().getVarRegion(D, LC); @@ -690,14 +683,15 @@ inline const llvm::APSInt *GRState::getSymVal(SymbolRef sym) const { return getStateManager().getSymVal(this, sym); } -inline SVal GRState::getSVal(const Stmt* Ex) const { - return Env.getSVal(Ex, *getStateManager().svalBuilder); +inline SVal GRState::getSVal(const Stmt* Ex, bool useOnlyDirectBindings) const{ + return Env.getSVal(Ex, *getStateManager().svalBuilder, + useOnlyDirectBindings); } inline SVal GRState::getSValAsScalarOrLoc(const Stmt *S) const { if (const Expr *Ex = dyn_cast<Expr>(S)) { QualType T = Ex->getType(); - if (Loc::isLocType(T) || T->isIntegerType()) + if (Ex->isLValue() || Loc::isLocType(T) || T->isIntegerType()) return getSVal(S); } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 8d19b5199274..db7a930b556e 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -769,7 +769,7 @@ public: } }; //===----------------------------------------------------------------------===// -// Auxillary data classes for use with MemRegions. +// Auxiliary data classes for use with MemRegions. //===----------------------------------------------------------------------===// class ElementRegion; @@ -960,7 +960,7 @@ public: getCompoundLiteralRegion(const CompoundLiteralExpr* CL, const LocationContext *LC); - /// getCXXThisRegion - Retrieve the [artifical] region associated with the + /// getCXXThisRegion - Retrieve the [artificial] region associated with the /// parameter 'this'. const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy, const LocationContext *LC); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h index 710fc6b84f9e..6d8fc89a4839 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h @@ -72,6 +72,8 @@ public: return getType(ctx); } + ObjCMethodFamily getMethodFamily() const; + Selector getSelector() const; const Expr *getInstanceReceiver() const { @@ -169,14 +171,23 @@ class CallOrObjCMessage { const CallExpr *CallE; ObjCMessage Msg; const GRState *State; - public: CallOrObjCMessage(const CallExpr *callE, const GRState *state) - : CallE(callE), State(state) { } + : CallE(callE), State(state) {} CallOrObjCMessage(const ObjCMessage &msg, const GRState *state) - : CallE(0), Msg(msg), State(state) { } + : CallE(0), Msg(msg), State(state) {} QualType getResultType(ASTContext &ctx) const; + + bool isFunctionCall() const { + return (bool) CallE; + } + + bool isCXXCall() const { + return CallE && isa<CXXMemberCallExpr>(CallE); + } + + SVal getCXXCallee() const; unsigned getNumArgs() const { if (CallE) return CallE->getNumArgs(); @@ -185,7 +196,8 @@ public: SVal getArgSVal(unsigned i) const { assert(i < getNumArgs()); - if (CallE) return State->getSVal(CallE->getArg(i)); + if (CallE) + return State->getSVal(CallE->getArg(i)); return Msg.getArgSVal(i, State); } @@ -193,13 +205,15 @@ public: const Expr *getArg(unsigned i) const { assert(i < getNumArgs()); - if (CallE) return CallE->getArg(i); + if (CallE) + return CallE->getArg(i); return Msg.getArgExpr(i); } SourceRange getArgSourceRange(unsigned i) const { assert(i < getNumArgs()); - if (CallE) return CallE->getArg(i)->getSourceRange(); + if (CallE) + return CallE->getArg(i)->getSourceRange(); return Msg.getArgSourceRange(i); } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index fc2b76e04a66..0f9e56aa2ff8 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -49,10 +49,10 @@ protected: const unsigned ArrayIndexWidth; public: - // FIXME: Make these protected again one RegionStoreManager correctly - // handles loads from differening bound value types. - virtual SVal evalCastNL(NonLoc val, QualType castTy) = 0; - virtual SVal evalCastL(Loc val, QualType castTy) = 0; + // FIXME: Make these protected again once RegionStoreManager correctly + // handles loads from different bound value types. + virtual SVal evalCastFromNonLoc(NonLoc val, QualType castTy) = 0; + virtual SVal evalCastFromLoc(Loc val, QualType castTy) = 0; public: SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, @@ -66,30 +66,30 @@ public: virtual ~SValBuilder() {} - SVal evalCast(SVal V, QualType castTy, QualType originalType); + SVal evalCast(SVal val, QualType castTy, QualType originalType); virtual SVal evalMinus(NonLoc val) = 0; virtual SVal evalComplement(NonLoc val) = 0; - virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode Op, + virtual SVal evalBinOpNN(const GRState *state, BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs, QualType resultTy) = 0; - virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode Op, + virtual SVal evalBinOpLL(const GRState *state, BinaryOperator::Opcode op, Loc lhs, Loc rhs, QualType resultTy) = 0; - virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode Op, + virtual SVal evalBinOpLN(const GRState *state, BinaryOperator::Opcode op, Loc lhs, NonLoc rhs, QualType resultTy) = 0; /// getKnownValue - evaluates a given SVal. If the SVal has only one possible /// (integer) value, that value is returned. Otherwise, returns NULL. - virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal V) = 0; + virtual const llvm::APSInt *getKnownValue(const GRState *state, SVal val) = 0; - SVal evalBinOp(const GRState *ST, BinaryOperator::Opcode Op, - SVal L, SVal R, QualType T); + SVal evalBinOp(const GRState *state, BinaryOperator::Opcode op, + SVal lhs, SVal rhs, QualType type); - DefinedOrUnknownSVal evalEQ(const GRState *ST, DefinedOrUnknownSVal L, - DefinedOrUnknownSVal R); + DefinedOrUnknownSVal evalEQ(const GRState *state, DefinedOrUnknownSVal lhs, + DefinedOrUnknownSVal rhs); ASTContext &getContext() { return Context; } const ASTContext &getContext() const { return Context; } @@ -115,46 +115,48 @@ public: // Forwarding methods to SymbolManager. - const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T, - unsigned VisitCount, - const void* SymbolTag = 0) { - return SymMgr.getConjuredSymbol(E, T, VisitCount, SymbolTag); + const SymbolConjured* getConjuredSymbol(const Stmt* stmt, QualType type, + unsigned visitCount, + const void* symbolTag = 0) { + return SymMgr.getConjuredSymbol(stmt, type, visitCount, symbolTag); } - const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount, - const void* SymbolTag = 0) { - return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag); + const SymbolConjured* getConjuredSymbol(const Expr* expr, unsigned visitCount, + const void* symbolTag = 0) { + return SymMgr.getConjuredSymbol(expr, visitCount, symbolTag); } /// makeZeroVal - Construct an SVal representing '0' for the specified type. - DefinedOrUnknownSVal makeZeroVal(QualType T); + DefinedOrUnknownSVal makeZeroVal(QualType type); - /// getRegionValueSymbolVal - make a unique symbol for value of R. - DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *R); + /// getRegionValueSymbolVal - make a unique symbol for value of region. + DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedRegion *region); - DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, - const Expr *E, unsigned Count); - DefinedOrUnknownSVal getConjuredSymbolVal(const void *SymbolTag, - const Expr *E, QualType T, - unsigned Count); + DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag, + const Expr *expr, unsigned count); + DefinedOrUnknownSVal getConjuredSymbolVal(const void *symbolTag, + const Expr *expr, QualType type, + unsigned count); - DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, - const TypedRegion *R); + DefinedOrUnknownSVal getDerivedRegionValueSymbolVal( + SymbolRef parentSymbol, const TypedRegion *region); - DefinedSVal getMetadataSymbolVal(const void *SymbolTag, const MemRegion *MR, - const Expr *E, QualType T, unsigned Count); + DefinedSVal getMetadataSymbolVal( + const void *symbolTag, const MemRegion *region, + const Expr *expr, QualType type, unsigned count); - DefinedSVal getFunctionPointer(const FunctionDecl *FD); + DefinedSVal getFunctionPointer(const FunctionDecl *func); - DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy, - const LocationContext *LC); + DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy, + const LocationContext *locContext); - NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) { - return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); + NonLoc makeCompoundVal(QualType type, llvm::ImmutableList<SVal> vals) { + return nonloc::CompoundVal(BasicVals.getCompoundValData(type, vals)); } - NonLoc makeLazyCompoundVal(const void *store, const TypedRegion *R) { - return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(store, R)); + NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedRegion *region) { + return nonloc::LazyCompoundVal( + BasicVals.getLazyCompoundValData(store, region)); } NonLoc makeZeroArrayIndex() { @@ -165,60 +167,63 @@ public: return nonloc::ConcreteInt(BasicVals.getValue(idx, ArrayIndexTy)); } - SVal convertToArrayIndex(SVal V); + SVal convertToArrayIndex(SVal val); - nonloc::ConcreteInt makeIntVal(const IntegerLiteral* I) { - return nonloc::ConcreteInt(BasicVals.getValue(I->getValue(), - I->getType()->isUnsignedIntegerType())); + nonloc::ConcreteInt makeIntVal(const IntegerLiteral* integer) { + return nonloc::ConcreteInt( + BasicVals.getValue(integer->getValue(), + integer->getType()->isUnsignedIntegerType())); } - nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *E) { - return makeTruthVal(E->getValue()); + nonloc::ConcreteInt makeBoolVal(const CXXBoolLiteralExpr *boolean) { + return makeTruthVal(boolean->getValue()); } - nonloc::ConcreteInt makeIntVal(const llvm::APSInt& V) { - return nonloc::ConcreteInt(BasicVals.getValue(V)); + nonloc::ConcreteInt makeIntVal(const llvm::APSInt& integer) { + return nonloc::ConcreteInt(BasicVals.getValue(integer)); } - loc::ConcreteInt makeIntLocVal(const llvm::APSInt &v) { - return loc::ConcreteInt(BasicVals.getValue(v)); + loc::ConcreteInt makeIntLocVal(const llvm::APSInt &integer) { + return loc::ConcreteInt(BasicVals.getValue(integer)); } - NonLoc makeIntVal(const llvm::APInt& V, bool isUnsigned) { - return nonloc::ConcreteInt(BasicVals.getValue(V, isUnsigned)); + NonLoc makeIntVal(const llvm::APInt& integer, bool isUnsigned) { + return nonloc::ConcreteInt(BasicVals.getValue(integer, isUnsigned)); } - DefinedSVal makeIntVal(uint64_t X, QualType T) { - if (Loc::isLocType(T)) - return loc::ConcreteInt(BasicVals.getValue(X, T)); + DefinedSVal makeIntVal(uint64_t integer, QualType type) { + if (Loc::isLocType(type)) + return loc::ConcreteInt(BasicVals.getValue(integer, type)); - return nonloc::ConcreteInt(BasicVals.getValue(X, T)); + return nonloc::ConcreteInt(BasicVals.getValue(integer, type)); } - NonLoc makeIntVal(uint64_t X, bool isUnsigned) { - return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned)); + NonLoc makeIntVal(uint64_t integer, bool isUnsigned) { + return nonloc::ConcreteInt(BasicVals.getIntValue(integer, isUnsigned)); } - NonLoc makeIntValWithPtrWidth(uint64_t X, bool isUnsigned) { - return nonloc::ConcreteInt(BasicVals.getIntWithPtrWidth(X, isUnsigned)); + NonLoc makeIntValWithPtrWidth(uint64_t integer, bool isUnsigned) { + return nonloc::ConcreteInt( + BasicVals.getIntWithPtrWidth(integer, isUnsigned)); } - NonLoc makeIntVal(uint64_t X, unsigned BitWidth, bool isUnsigned) { - return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned)); + NonLoc makeIntVal(uint64_t integer, unsigned bitWidth, bool isUnsigned) { + return nonloc::ConcreteInt( + BasicVals.getValue(integer, bitWidth, isUnsigned)); } - NonLoc makeLocAsInteger(Loc V, unsigned Bits) { - return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(V, Bits)); + NonLoc makeLocAsInteger(Loc loc, unsigned bits) { + return nonloc::LocAsInteger(BasicVals.getPersistentSValWithData(loc, bits)); } NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const llvm::APSInt& rhs, QualType T); + const llvm::APSInt& rhs, QualType type); NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, - const SymExpr *rhs, QualType T); + const SymExpr *rhs, QualType type); - nonloc::ConcreteInt makeTruthVal(bool b, QualType T) { - return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T)); + nonloc::ConcreteInt makeTruthVal(bool b, QualType type) { + return nonloc::ConcreteInt(BasicVals.getTruthValue(b, type)); } nonloc::ConcreteInt makeTruthVal(bool b) { @@ -229,20 +234,20 @@ public: return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth()); } - Loc makeLoc(SymbolRef Sym) { - return loc::MemRegionVal(MemMgr.getSymbolicRegion(Sym)); + Loc makeLoc(SymbolRef sym) { + return loc::MemRegionVal(MemMgr.getSymbolicRegion(sym)); } - Loc makeLoc(const MemRegion* R) { - return loc::MemRegionVal(R); + Loc makeLoc(const MemRegion* region) { + return loc::MemRegionVal(region); } - Loc makeLoc(const AddrLabelExpr *E) { - return loc::GotoLabel(E->getLabel()); + Loc makeLoc(const AddrLabelExpr *expr) { + return loc::GotoLabel(expr->getLabel()); } - Loc makeLoc(const llvm::APSInt& V) { - return loc::ConcreteInt(BasicVals.getValue(V)); + Loc makeLoc(const llvm::APSInt& integer) { + return loc::ConcreteInt(BasicVals.getValue(integer)); } }; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 0251311c27ae..21c6ae760cc8 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_GR_STORE_H #define LLVM_CLANG_GR_STORE_H +#include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" #include "llvm/ADT/DenseSet.h" @@ -28,36 +29,10 @@ class StackFrameContext; namespace ento { -/// Store - This opaque type encapsulates an immutable mapping from -/// locations to values. At a high-level, it represents the symbolic -/// memory model. Different subclasses of StoreManager may choose -/// different types to represent the locations and values. -typedef const void* Store; - class GRState; class GRStateManager; class SubRegionMap; -class StoreManager; - -class StoreRef { - Store store; - StoreManager &mgr; -public: - StoreRef(Store, StoreManager &); - StoreRef(const StoreRef &); - StoreRef &operator=(StoreRef const &); - - bool operator==(const StoreRef &x) const { - assert(&mgr == &x.mgr); - return x.store == store; - } - bool operator!=(const StoreRef &x) const { return !operator==(x); } - ~StoreRef(); - - Store getStore() const { return store; } -}; - class StoreManager { protected: SValBuilder &svalBuilder; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h new file mode 100644 index 000000000000..0662eadc93c3 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h @@ -0,0 +1,50 @@ +//== StoreRef.h - Smart pointer for store objects ---------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the type StoreRef. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_GR_STOREREF_H +#define LLVM_CLANG_GR_STOREREF_H + +#include <cassert> + +namespace clang { +namespace ento { + +/// Store - This opaque type encapsulates an immutable mapping from +/// locations to values. At a high-level, it represents the symbolic +/// memory model. Different subclasses of StoreManager may choose +/// different types to represent the locations and values. +typedef const void* Store; + +class StoreManager; + +class StoreRef { + Store store; + StoreManager &mgr; +public: + StoreRef(Store, StoreManager &); + StoreRef(const StoreRef &); + StoreRef &operator=(StoreRef const &); + + bool operator==(const StoreRef &x) const { + assert(&mgr == &x.mgr); + return x.store == store; + } + bool operator!=(const StoreRef &x) const { return !operator==(x); } + + ~StoreRef(); + + Store getStore() const { return store; } +}; + +}} +#endif diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h new file mode 100644 index 000000000000..6ccccd0bff0c --- /dev/null +++ b/include/clang/Tooling/Tooling.h @@ -0,0 +1,81 @@ +//===--- Tooling.h - Framework for standalone Clang tools -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements functions to run clang tools standalone instead +// of running them as a plugin. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_TOOLING_H +#define LLVM_CLANG_TOOLING_TOOLING_H + +#include "llvm/ADT/StringRef.h" +#include <string> +#include <vector> + +namespace clang { + +class FrontendAction; + +namespace tooling { + +/// \brief Runs (and deletes) the tool on 'Code' with the -fsynatx-only flag. +/// +/// \param ToolAction The action to run over the code. +/// \param Code C++ code. +/// +/// \return - True if 'ToolAction' was successfully executed. +bool RunSyntaxOnlyToolOnCode( + clang::FrontendAction *ToolAction, llvm::StringRef Code); + +/// \brief Runs (and deletes) the tool with the given Clang flags. +/// +/// \param ToolAction The action to run over the code. +/// \param Argc The number of elements in Argv. +/// \param Argv The command line arguments, including the path the binary +/// was started with (Argv[0]). +bool RunToolWithFlags( + clang::FrontendAction* ToolAction, int Argc, char *Argv[]); + +/// \brief Converts a vector<string> into a vector<char*> suitable to pass +/// to main-style functions taking (int Argc, char *Argv[]). +std::vector<char*> CommandLineToArgv(const std::vector<std::string>* Command); + +/// \brief Specifies the working directory and command of a compilation. +struct CompileCommand { + /// \brief The working directory the command was executed from. + std::string Directory; + + /// \brief The command line that was executed. + std::vector<std::string> CommandLine; +}; + +/// \brief Looks up the compile command for 'FileName' in 'JsonDatabase'. +/// +/// \param FileName The path to an input file for which we want the compile +/// command line. If the 'JsonDatabase' was created by CMake, this must be +/// an absolute path inside the CMake source directory which does not have +/// symlinks resolved. +/// +/// \param JsonDatabase A JSON formatted list of compile commands. This lookup +/// command supports only a subset of the JSON standard as written by CMake. +/// +/// \param ErrorMessage If non-empty, an error occurred and 'ErrorMessage' will +/// be set to contain the error message. In this case CompileCommand will +/// contain an empty directory and command line. +/// +/// \see JsonCompileCommandLineDatabase +CompileCommand FindCompileArgsInJsonDatabase( + llvm::StringRef FileName, llvm::StringRef JsonDatabase, + std::string &ErrorMessage); + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_TOOLING_H |