diff options
Diffstat (limited to 'include/clang')
127 files changed, 6052 insertions, 1853 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 87a12cde..3799451 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -62,6 +62,7 @@ namespace clang { class RecordDecl; class StoredDeclsMap; class TagDecl; + class TemplateTemplateParmDecl; class TemplateTypeParmDecl; class TranslationUnitDecl; class TypeDecl; @@ -75,6 +76,8 @@ 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 { + ASTContext &this_() { return *this; } + std::vector<Type*> Types; llvm::FoldingSet<ExtQuals> ExtQualNodes; llvm::FoldingSet<ComplexType> ComplexTypes; @@ -95,9 +98,12 @@ class ASTContext { llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes; llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes; - llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes; + llvm::ContextualFoldingSet<TemplateSpecializationType, ASTContext&> + TemplateSpecializationTypes; llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<DependentNameType> DependentNameTypes; + llvm::ContextualFoldingSet<DependentTemplateSpecializationType, ASTContext&> + DependentTemplateSpecializationTypes; llvm::FoldingSet<ObjCObjectTypeImpl> ObjCObjectTypes; llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; @@ -122,6 +128,30 @@ class ASTContext { /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; + /// \brief Representation of a "canonical" template template parameter that + /// is used in canonical template names. + class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode { + TemplateTemplateParmDecl *Parm; + + public: + CanonicalTemplateTemplateParm(TemplateTemplateParmDecl *Parm) + : Parm(Parm) { } + + TemplateTemplateParmDecl *getParam() const { return Parm; } + + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, Parm); } + + static void Profile(llvm::FoldingSetNodeID &ID, + TemplateTemplateParmDecl *Parm); + }; + llvm::FoldingSet<CanonicalTemplateTemplateParm> CanonTemplateTemplateParms; + + TemplateTemplateParmDecl *getCanonicalTemplateTemplateParmDecl( + TemplateTemplateParmDecl *TTP); + + /// \brief Whether __[u]int128_t identifier is installed. + bool IsInt128Installed; + /// BuiltinVaListType - built-in va list type. /// This is initially null and set by Sema::LazilyCreateBuiltin when /// a builtin that takes a valist is encountered. @@ -162,6 +192,8 @@ class ASTContext { /// \brief Type for the Block descriptor for Blocks CodeGen. RecordDecl *BlockDescriptorExtendedType; + TypeSourceInfo NullTypeSourceInfo; + /// \brief Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of @@ -302,7 +334,8 @@ public: /// \brief Note that the static data member \p Inst is an instantiation of /// the static data member template \p Tmpl of a class template. void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, - TemplateSpecializationKind TSK); + TemplateSpecializationKind TSK, + SourceLocation PointOfInstantiation = SourceLocation()); /// \brief If the given using decl is an instantiation of a /// (possibly unresolved) using decl from a template instantiation, @@ -329,6 +362,8 @@ public: overridden_cxx_method_iterator overridden_methods_end(const CXXMethodDecl *Method) const; + unsigned overridden_methods_size(const CXXMethodDecl *Method) const; + /// \brief Note that the given C++ \p Method overrides the given \p /// Overridden method. void addOverriddenMethod(const CXXMethodDecl *Method, @@ -534,7 +569,7 @@ public: /// getVectorType - Return the unique reference to a vector type of /// the specified element type and size. VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts, - bool AltiVec, bool IsPixel); + VectorType::AltiVecSpecific AltiVecSpec); /// getExtVectorType - Return the unique reference to an extended vector type /// of the specified element type and size. VectorType must be a built-in @@ -585,7 +620,11 @@ public: /// getTypedefType - Return the unique reference to the type for the /// specified typename decl. - QualType getTypedefType(const TypedefDecl *Decl); + QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType()); + + QualType getRecordType(const RecordDecl *Decl); + + QualType getEnumType(const EnumDecl *Decl); QualType getInjectedClassNameType(CXXRecordDecl *Decl, QualType TST); @@ -599,13 +638,15 @@ public: QualType getTemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, - QualType Canon = QualType(), - bool IsCurrentInstantiation = false); + QualType Canon = QualType()); + + QualType getCanonicalTemplateSpecializationType(TemplateName T, + const TemplateArgument *Args, + unsigned NumArgs); QualType getTemplateSpecializationType(TemplateName T, const TemplateArgumentListInfo &Args, - QualType Canon = QualType(), - bool IsCurrentInstantiation = false); + QualType Canon = QualType()); TypeSourceInfo * getTemplateSpecializationTypeInfo(TemplateName T, SourceLocation TLoc, @@ -619,10 +660,16 @@ public: NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType Canon = QualType()); - QualType getDependentNameType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const TemplateSpecializationType *TemplateId, - QualType Canon = QualType()); + + QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + const TemplateArgumentListInfo &Args); + QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args); QualType getObjCInterfaceType(const ObjCInterfaceDecl *Decl); @@ -780,6 +827,10 @@ public: /// purpose in characters. CharUnits getObjCEncodingTypeSize(QualType t); + /// \brief Whether __[u]int128_t identifier is installed. + bool isInt128Installed() const { return IsInt128Installed; } + void setInt128Installed() { IsInt128Installed = true; } + /// This setter/getter represents the ObjC 'id' type. It is setup lazily, by /// Sema. id is always a (typedef for a) pointer type, a pointer to a struct. QualType getObjCIdType() const { return ObjCIdTypedefType; } @@ -943,8 +994,9 @@ public: const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D); - /// getKeyFunction - Get the key function for the given record decl. - /// The key function is, according to the Itanium C++ ABI section 5.2.3: + /// getKeyFunction - Get the key function for the given record decl, or NULL + /// if there isn't one. The key function is, according to the Itanium C++ ABI + /// section 5.2.3: /// /// ...the first non-pure virtual function that is not inline at the point /// of class definition. @@ -1013,6 +1065,8 @@ public: return UnqualT1 == UnqualT2; } + bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); + /// \brief Retrieves the "canonical" declaration of /// \brief Retrieves the "canonical" nested name specifier for a @@ -1272,6 +1326,8 @@ public: TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()); + TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; } + /// \brief Add a deallocation callback that will be invoked when the /// ASTContext is destroyed. /// @@ -1280,6 +1336,38 @@ public: /// \brief Data Pointer data that will be provided to the callback function /// when it is called. void AddDeallocation(void (*Callback)(void*), void *Data); + + //===--------------------------------------------------------------------===// + // Statistics + //===--------------------------------------------------------------------===// + + /// \brief The number of implicitly-declared default constructors. + static unsigned NumImplicitDefaultConstructors; + + /// \brief The number of implicitly-declared default constructors for + /// which declarations were built. + static unsigned NumImplicitDefaultConstructorsDeclared; + + /// \brief The number of implicitly-declared copy constructors. + static unsigned NumImplicitCopyConstructors; + + /// \brief The number of implicitly-declared copy constructors for + /// which declarations were built. + static unsigned NumImplicitCopyConstructorsDeclared; + + /// \brief The number of implicitly-declared copy assignment operators. + static unsigned NumImplicitCopyAssignmentOperators; + + /// \brief The number of implicitly-declared copy assignment operators for + /// which declarations were built. + static unsigned NumImplicitCopyAssignmentOperatorsDeclared; + + /// \brief The number of implicitly-declared destructors. + static unsigned NumImplicitDestructors; + + /// \brief The number of implicitly-declared destructors for which + /// declarations were built. + static unsigned NumImplicitDestructorsDeclared; private: ASTContext(const ASTContext&); // DO NOT IMPLEMENT @@ -1308,6 +1396,11 @@ private: // by DeclContext objects. This probably should not be in ASTContext, // but we include it here so that ASTContext can quickly deallocate them. llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM; + + /// \brief A counter used to uniquely identify "blocks". + unsigned int UniqueBlockByRefTypeID; + unsigned int UniqueBlockParmTypeID; + friend class DeclContext; friend class DeclarationNameTable; void ReleaseDeclContextMaps(); diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 3240e50..9faa62e 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -16,6 +16,7 @@ #include "llvm/Support/Casting.h" #include "llvm/ADT/StringRef.h" +#include "clang/Basic/AttrKinds.h" #include <cassert> #include <cstring> #include <algorithm> @@ -25,6 +26,7 @@ namespace clang { class ASTContext; class IdentifierInfo; class ObjCInterfaceDecl; + class Expr; } // Defined in ASTContext.h @@ -41,75 +43,9 @@ namespace clang { /// Attr - This represents one attribute. class Attr { -public: - enum Kind { - Alias, - Aligned, - AlignMac68k, - AlwaysInline, - AnalyzerNoReturn, // Clang-specific. - Annotate, - AsmLabel, // Represent GCC asm label extension. - BaseCheck, - Blocks, - CDecl, - Cleanup, - Const, - Constructor, - Deprecated, - Destructor, - FastCall, - Final, - Format, - FormatArg, - GNUInline, - Hiding, - IBOutletKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. - IBOutletCollectionKind, // Clang-specific. - IBActionKind, // Clang-specific. Use "Kind" suffix to not conflict w/ macro. - Malloc, - MaxFieldAlignment, - NoDebug, - NoInline, - NonNull, - NoReturn, - NoThrow, - ObjCException, - ObjCNSObject, - Override, - CFReturnsRetained, // Clang/Checker-specific. - CFReturnsNotRetained, // Clang/Checker-specific. - NSReturnsRetained, // Clang/Checker-specific. - NSReturnsNotRetained, // Clang/Checker-specific. - Overloadable, // Clang-specific - Packed, - Pure, - Regparm, - ReqdWorkGroupSize, // OpenCL-specific - Section, - Sentinel, - StdCall, - ThisCall, - TransparentUnion, - Unavailable, - Unused, - Used, - Visibility, - WarnUnusedResult, - Weak, - WeakImport, - WeakRef, - - FIRST_TARGET_ATTRIBUTE, - DLLExport, - DLLImport, - MSP430Interrupt, - X86ForceAlignArgPointer - }; - private: Attr *Next; - Kind AttrKind; + attr::Kind AttrKind; bool Inherited : 1; protected: @@ -122,7 +58,7 @@ protected: } protected: - Attr(Kind AK) : Next(0), AttrKind(AK), Inherited(false) {} + Attr(attr::Kind AK) : Next(0), AttrKind(AK), Inherited(false) {} virtual ~Attr() { assert(Next == 0 && "Destroy didn't work"); } @@ -133,7 +69,7 @@ public: /// declarations. virtual bool isMerged() const { return true; } - Kind getKind() const { return AttrKind; } + attr::Kind getKind() const { return AttrKind; } Attr *getNext() { return Next; } const Attr *getNext() const { return Next; } @@ -163,13 +99,15 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *) { return true; } }; + +#include "clang/AST/Attrs.inc" class AttrWithString : public Attr { private: const char *Str; unsigned StrLen; protected: - AttrWithString(Attr::Kind AK, ASTContext &C, llvm::StringRef s); + AttrWithString(attr::Kind AK, ASTContext &C, llvm::StringRef s); llvm::StringRef getString() const { return llvm::StringRef(Str, StrLen); } void ReplaceString(ASTContext &C, llvm::StringRef newS); public: @@ -179,9 +117,9 @@ public: #define DEF_SIMPLE_ATTR(ATTR) \ class ATTR##Attr : public Attr { \ public: \ - ATTR##Attr() : Attr(ATTR) {} \ + ATTR##Attr() : Attr(attr::ATTR) {} \ virtual Attr *clone(ASTContext &C) const; \ - static bool classof(const Attr *A) { return A->getKind() == ATTR; } \ + static bool classof(const Attr *A) { return A->getKind() == attr::ATTR; } \ static bool classof(const ATTR##Attr *A) { return true; } \ } @@ -194,7 +132,7 @@ class MaxFieldAlignmentAttr : public Attr { public: MaxFieldAlignmentAttr(unsigned alignment) - : Attr(MaxFieldAlignment), Alignment(alignment) {} + : Attr(attr::MaxFieldAlignment), Alignment(alignment) {} /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } @@ -203,36 +141,58 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == MaxFieldAlignment; + return A->getKind() == attr::MaxFieldAlignment; } static bool classof(const MaxFieldAlignmentAttr *A) { return true; } }; DEF_SIMPLE_ATTR(AlignMac68k); +/// \brief Atribute for specifying the alignment of a variable or type. +/// +/// This node will either contain the precise Alignment (in bits, not bytes!) +/// or will contain the expression for the alignment attribute in the case of +/// a dependent expression within a class or function template. At template +/// instantiation time these are transformed into concrete attributes. class AlignedAttr : public Attr { unsigned Alignment; + Expr *AlignmentExpr; public: AlignedAttr(unsigned alignment) - : Attr(Aligned), Alignment(alignment) {} + : Attr(attr::Aligned), Alignment(alignment), AlignmentExpr(0) {} + AlignedAttr(Expr *E) + : Attr(attr::Aligned), Alignment(0), AlignmentExpr(E) {} + + /// getAlignmentExpr - Get a dependent alignment expression if one is present. + Expr *getAlignmentExpr() const { + return AlignmentExpr; + } + + /// isDependent - Is the alignment a dependent expression + bool isDependent() const { + return getAlignmentExpr(); + } + + /// getAlignment - The specified alignment in bits. Requires !isDependent(). + unsigned getAlignment() const { + assert(!isDependent() && "Cannot get a value dependent alignment"); + return Alignment; + } - /// getAlignment - The specified alignment in bits. - unsigned getAlignment() const { return Alignment; } - /// getMaxAlignment - Get the maximum alignment of attributes on this list. unsigned getMaxAlignment() const { const AlignedAttr *Next = getNext<AlignedAttr>(); if (Next) - return std::max(Next->getMaxAlignment(), Alignment); + return std::max(Next->getMaxAlignment(), getAlignment()); else - return Alignment; + return getAlignment(); } virtual Attr* clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == Aligned; + return A->getKind() == attr::Aligned; } static bool classof(const AlignedAttr *A) { return true; } }; @@ -240,7 +200,7 @@ public: class AnnotateAttr : public AttrWithString { public: AnnotateAttr(ASTContext &C, llvm::StringRef ann) - : AttrWithString(Annotate, C, ann) {} + : AttrWithString(attr::Annotate, C, ann) {} llvm::StringRef getAnnotation() const { return getString(); } @@ -248,7 +208,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == Annotate; + return A->getKind() == attr::Annotate; } static bool classof(const AnnotateAttr *A) { return true; } }; @@ -256,7 +216,7 @@ public: class AsmLabelAttr : public AttrWithString { public: AsmLabelAttr(ASTContext &C, llvm::StringRef L) - : AttrWithString(AsmLabel, C, L) {} + : AttrWithString(attr::AsmLabel, C, L) {} llvm::StringRef getLabel() const { return getString(); } @@ -264,7 +224,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == AsmLabel; + return A->getKind() == attr::AsmLabel; } static bool classof(const AsmLabelAttr *A) { return true; } }; @@ -274,54 +234,56 @@ DEF_SIMPLE_ATTR(AlwaysInline); class AliasAttr : public AttrWithString { public: AliasAttr(ASTContext &C, llvm::StringRef aliasee) - : AttrWithString(Alias, C, aliasee) {} + : AttrWithString(attr::Alias, C, aliasee) {} llvm::StringRef getAliasee() const { return getString(); } virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Alias; } + static bool classof(const Attr *A) { return A->getKind() == attr::Alias; } static bool classof(const AliasAttr *A) { return true; } }; class ConstructorAttr : public Attr { int priority; public: - ConstructorAttr(int p) : Attr(Constructor), priority(p) {} + ConstructorAttr(int p) : Attr(attr::Constructor), priority(p) {} int getPriority() const { return priority; } virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Constructor; } + static bool classof(const Attr *A) + { return A->getKind() == attr::Constructor; } static bool classof(const ConstructorAttr *A) { return true; } }; class DestructorAttr : public Attr { int priority; public: - DestructorAttr(int p) : Attr(Destructor), priority(p) {} + DestructorAttr(int p) : Attr(attr::Destructor), priority(p) {} int getPriority() const { return priority; } virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Destructor; } + static bool classof(const Attr *A) + { return A->getKind() == attr::Destructor; } static bool classof(const DestructorAttr *A) { return true; } }; class IBOutletAttr : public Attr { public: - IBOutletAttr() : Attr(IBOutletKind) {} + IBOutletAttr() : Attr(attr::IBOutlet) {} virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == IBOutletKind; + return A->getKind() == attr::IBOutlet; } static bool classof(const IBOutletAttr *A) { return true; } }; @@ -330,7 +292,7 @@ class IBOutletCollectionAttr : public Attr { const ObjCInterfaceDecl *D; public: IBOutletCollectionAttr(const ObjCInterfaceDecl *d = 0) - : Attr(IBOutletCollectionKind), D(d) {} + : Attr(attr::IBOutletCollection), D(d) {} const ObjCInterfaceDecl *getClass() const { return D; } @@ -338,35 +300,35 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == IBOutletCollectionKind; + return A->getKind() == attr::IBOutletCollection; } static bool classof(const IBOutletCollectionAttr *A) { return true; } }; class IBActionAttr : public Attr { public: - IBActionAttr() : Attr(IBActionKind) {} + IBActionAttr() : Attr(attr::IBAction) {} virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == IBActionKind; + return A->getKind() == attr::IBAction; } static bool classof(const IBActionAttr *A) { return true; } }; DEF_SIMPLE_ATTR(AnalyzerNoReturn); DEF_SIMPLE_ATTR(Deprecated); -DEF_SIMPLE_ATTR(Final); DEF_SIMPLE_ATTR(GNUInline); DEF_SIMPLE_ATTR(Malloc); DEF_SIMPLE_ATTR(NoReturn); +DEF_SIMPLE_ATTR(NoInstrumentFunction); class SectionAttr : public AttrWithString { public: SectionAttr(ASTContext &C, llvm::StringRef N) - : AttrWithString(Section, C, N) {} + : AttrWithString(attr::Section, C, N) {} llvm::StringRef getName() const { return getString(); } @@ -374,7 +336,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == Section; + return A->getKind() == attr::Section; } static bool classof(const SectionAttr *A) { return true; } }; @@ -408,7 +370,7 @@ public: virtual Attr *clone(ASTContext &C) const; - static bool classof(const Attr *A) { return A->getKind() == NonNull; } + static bool classof(const Attr *A) { return A->getKind() == attr::NonNull; } static bool classof(const NonNullAttr *A) { return true; } }; @@ -416,7 +378,7 @@ class FormatAttr : public AttrWithString { int formatIdx, firstArg; public: FormatAttr(ASTContext &C, llvm::StringRef type, int idx, int first) - : AttrWithString(Format, C, type), formatIdx(idx), firstArg(first) {} + : AttrWithString(attr::Format, C, type), formatIdx(idx), firstArg(first) {} llvm::StringRef getType() const { return getString(); } void setType(ASTContext &C, llvm::StringRef type); @@ -426,27 +388,27 @@ public: virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Format; } + static bool classof(const Attr *A) { return A->getKind() == attr::Format; } static bool classof(const FormatAttr *A) { return true; } }; class FormatArgAttr : public Attr { int formatIdx; public: - FormatArgAttr(int idx) : Attr(FormatArg), formatIdx(idx) {} + FormatArgAttr(int idx) : Attr(attr::FormatArg), formatIdx(idx) {} int getFormatIdx() const { return formatIdx; } virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == FormatArg; } + static bool classof(const Attr *A) { return A->getKind() == attr::FormatArg; } static bool classof(const FormatArgAttr *A) { return true; } }; class SentinelAttr : public Attr { int sentinel, NullPos; public: - SentinelAttr(int sentinel_val, int nullPos) : Attr(Sentinel), + SentinelAttr(int sentinel_val, int nullPos) : Attr(attr::Sentinel), sentinel(sentinel_val), NullPos(nullPos) {} int getSentinel() const { return sentinel; } int getNullPos() const { return NullPos; } @@ -454,7 +416,7 @@ public: virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Sentinel; } + static bool classof(const Attr *A) { return A->getKind() == attr::Sentinel; } static bool classof(const SentinelAttr *A) { return true; } }; @@ -469,7 +431,7 @@ public: private: VisibilityTypes VisibilityType; public: - VisibilityAttr(VisibilityTypes v) : Attr(Visibility), + VisibilityAttr(VisibilityTypes v) : Attr(attr::Visibility), VisibilityType(v) {} VisibilityTypes getVisibility() const { return VisibilityType; } @@ -477,7 +439,8 @@ public: virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Visibility; } + static bool classof(const Attr *A) + { return A->getKind() == attr::Visibility; } static bool classof(const VisibilityAttr *A) { return true; } }; @@ -491,13 +454,14 @@ DEF_SIMPLE_ATTR(ObjCException); class OverloadableAttr : public Attr { public: - OverloadableAttr() : Attr(Overloadable) { } + OverloadableAttr() : Attr(attr::Overloadable) { } virtual bool isMerged() const { return false; } virtual Attr *clone(ASTContext &C) const; - static bool classof(const Attr *A) { return A->getKind() == Overloadable; } + static bool classof(const Attr *A) + { return A->getKind() == attr::Overloadable; } static bool classof(const OverloadableAttr *) { return true; } }; @@ -509,14 +473,14 @@ public: private: BlocksAttrTypes BlocksAttrType; public: - BlocksAttr(BlocksAttrTypes t) : Attr(Blocks), BlocksAttrType(t) {} + BlocksAttr(BlocksAttrTypes t) : Attr(attr::Blocks), BlocksAttrType(t) {} BlocksAttrTypes getType() const { return BlocksAttrType; } virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Blocks; } + static bool classof(const Attr *A) { return A->getKind() == attr::Blocks; } static bool classof(const BlocksAttr *A) { return true; } }; @@ -526,14 +490,14 @@ class CleanupAttr : public Attr { FunctionDecl *FD; public: - CleanupAttr(FunctionDecl *fd) : Attr(Cleanup), FD(fd) {} + CleanupAttr(FunctionDecl *fd) : Attr(attr::Cleanup), FD(fd) {} const FunctionDecl *getFunctionDecl() const { return FD; } virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Cleanup; } + static bool classof(const Attr *A) { return A->getKind() == attr::Cleanup; } static bool classof(const CleanupAttr *A) { return true; } }; @@ -545,14 +509,14 @@ class RegparmAttr : public Attr { unsigned NumParams; public: - RegparmAttr(unsigned np) : Attr(Regparm), NumParams(np) {} + RegparmAttr(unsigned np) : Attr(attr::Regparm), NumParams(np) {} unsigned getNumParams() const { return NumParams; } virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == Regparm; } + static bool classof(const Attr *A) { return A->getKind() == attr::Regparm; } static bool classof(const RegparmAttr *A) { return true; } }; @@ -560,7 +524,7 @@ class ReqdWorkGroupSizeAttr : public Attr { unsigned X, Y, Z; public: ReqdWorkGroupSizeAttr(unsigned X, unsigned Y, unsigned Z) - : Attr(ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {} + : Attr(attr::ReqdWorkGroupSize), X(X), Y(Y), Z(Z) {} unsigned getXDim() const { return X; } unsigned getYDim() const { return Y; } @@ -570,22 +534,34 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == ReqdWorkGroupSize; + return A->getKind() == attr::ReqdWorkGroupSize; } static bool classof(const ReqdWorkGroupSizeAttr *A) { return true; } }; +class InitPriorityAttr : public Attr { + unsigned Priority; +public: + InitPriorityAttr(unsigned priority) + : Attr(attr::InitPriority), Priority(priority) {} + + virtual void Destroy(ASTContext &C) { Attr::Destroy(C); } + + unsigned getPriority() const { return Priority; } + + virtual Attr *clone(ASTContext &C) const; + + static bool classof(const Attr *A) + { return A->getKind() == attr::InitPriority; } + static bool classof(const InitPriorityAttr *A) { return true; } +}; + // Checker-specific attributes. DEF_SIMPLE_ATTR(CFReturnsNotRetained); DEF_SIMPLE_ATTR(CFReturnsRetained); DEF_SIMPLE_ATTR(NSReturnsNotRetained); DEF_SIMPLE_ATTR(NSReturnsRetained); -// C++0x member checking attributes. -DEF_SIMPLE_ATTR(BaseCheck); -DEF_SIMPLE_ATTR(Hiding); -DEF_SIMPLE_ATTR(Override); - // Target-specific attributes DEF_SIMPLE_ATTR(DLLImport); DEF_SIMPLE_ATTR(DLLExport); @@ -594,14 +570,15 @@ class MSP430InterruptAttr : public Attr { unsigned Number; public: - MSP430InterruptAttr(unsigned n) : Attr(MSP430Interrupt), Number(n) {} + MSP430InterruptAttr(unsigned n) : Attr(attr::MSP430Interrupt), Number(n) {} unsigned getNumber() const { return Number; } virtual Attr *clone(ASTContext &C) const; // Implement isa/cast/dyncast/etc. - static bool classof(const Attr *A) { return A->getKind() == MSP430Interrupt; } + static bool classof(const Attr *A) + { return A->getKind() == attr::MSP430Interrupt; } static bool classof(const MSP430InterruptAttr *A) { return true; } }; diff --git a/include/clang/AST/CMakeLists.txt b/include/clang/AST/CMakeLists.txt index c24ea06..3b09071 100644 --- a/include/clang/AST/CMakeLists.txt +++ b/include/clang/AST/CMakeLists.txt @@ -1,5 +1,18 @@ -set(LLVM_TARGET_DEFINITIONS StmtNodes.td) +set(LLVM_TARGET_DEFINITIONS ../Basic/Attr.td) +tablegen(Attrs.inc + -gen-clang-attr-classes + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) +add_custom_target(ClangAttrClasses + DEPENDS Attrs.inc) + +set(LLVM_TARGET_DEFINITIONS ../Basic/StmtNodes.td) tablegen(StmtNodes.inc -gen-clang-stmt-nodes) add_custom_target(ClangStmtNodes DEPENDS StmtNodes.inc) + +set(LLVM_TARGET_DEFINITIONS ../Basic/DeclNodes.td) +tablegen(DeclNodes.inc + -gen-clang-decl-nodes) +add_custom_target(ClangDeclNodes + DEPENDS DeclNodes.inc) diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 4afb81d..9f97fd8 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -247,6 +247,7 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isCharType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isWideCharType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isIntegralOrEnumerationType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isRealFloatingType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isComplexType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isAnyComplexType) @@ -269,8 +270,10 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isNullPtrType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isDependentType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isOverloadableType) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isArrayType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasPointerRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasObjCPointerRepresentation) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasFloatingRepresentation) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isPromotableIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSignedIntegerType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isUnsignedIntegerType) diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 7d5b66e..39cd51f 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -28,6 +28,8 @@ class FunctionTemplateDecl; class Stmt; class CompoundStmt; class StringLiteral; +class NestedNameSpecifier; +class TemplateParameterList; class TemplateArgumentList; class MemberSpecializationInfo; class FunctionTemplateSpecializationInfo; @@ -216,7 +218,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamedDecl *D) { return true; } - static bool classofKind(Kind K) { return K >= NamedFirst && K <= NamedLast; } + static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; } }; inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, @@ -342,6 +344,9 @@ public: static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC)); } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// ValueDecl - Represent the declaration of a variable (in which case it is @@ -361,7 +366,38 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ValueDecl *D) { return true; } - static bool classofKind(Kind K) { return K >= ValueFirst && K <= ValueLast; } + static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; } +}; + +/// QualifierInfo - A struct with extended info about a syntactic +/// name qualifier, to be used for the case of out-of-line declarations. +struct QualifierInfo { + /// NNS - The syntactic name qualifier. + NestedNameSpecifier *NNS; + /// NNSRange - The source range for the qualifier. + SourceRange NNSRange; + /// NumTemplParamLists - The number of template parameter lists + /// that were matched against the template-ids occurring into the NNS. + unsigned NumTemplParamLists; + /// TemplParamLists - A new-allocated array of size NumTemplParamLists, + /// containing pointers to the matched template parameter lists. + TemplateParameterList** TemplParamLists; + + /// Default constructor. + QualifierInfo() + : NNS(0), NNSRange(), NumTemplParamLists(0), TemplParamLists(0) {} + /// setTemplateParameterListsInfo - Sets info about matched template + /// parameter lists. + void setTemplateParameterListsInfo(ASTContext &Context, + unsigned NumTPLists, + TemplateParameterList **TPLists); + + void Destroy(ASTContext &Context); + +private: + // Copy constructor and copy assignment are disabled. + QualifierInfo(const QualifierInfo&); + QualifierInfo& operator=(const QualifierInfo&); }; /// \brief Represents a ValueDecl that came out of a declarator. @@ -369,10 +405,8 @@ public: class DeclaratorDecl : public ValueDecl { // A struct representing both a TInfo and a syntactic qualifier, // to be used for the (uncommon) case of out-of-line declarations. - struct ExtInfo { + struct ExtInfo : public QualifierInfo { TypeSourceInfo *TInfo; - NestedNameSpecifier *NNS; - SourceRange NNSRange; }; llvm::PointerUnion<TypeSourceInfo*, ExtInfo*> DeclInfo; @@ -392,32 +426,55 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return hasExtInfo() - ? DeclInfo.get<ExtInfo*>()->TInfo + ? getExtInfo()->TInfo : DeclInfo.get<TypeSourceInfo*>(); } void setTypeSourceInfo(TypeSourceInfo *TI) { if (hasExtInfo()) - DeclInfo.get<ExtInfo*>()->TInfo = TI; + getExtInfo()->TInfo = TI; else DeclInfo = TI; } + /// getInnerLocStart - Return SourceLocation representing start of source + /// range ignoring outer template declarations. + virtual SourceLocation getInnerLocStart() const { return getLocation(); } + + /// 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()); + } + NestedNameSpecifier *getQualifier() const { - return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNS : 0; + return hasExtInfo() ? getExtInfo()->NNS : 0; } SourceRange getQualifierRange() const { - return hasExtInfo() ? DeclInfo.get<ExtInfo*>()->NNSRange : SourceRange(); + return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange(); } void setQualifierInfo(NestedNameSpecifier *Qualifier, SourceRange QualifierRange); + unsigned getNumTemplateParameterLists() const { + return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; + } + TemplateParameterList *getTemplateParameterList(unsigned index) const { + assert(index < getNumTemplateParameterLists()); + return getExtInfo()->TemplParamLists[index]; + } + void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, + TemplateParameterList **TPLists) { + getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); + } + SourceLocation getTypeSpecStartLoc() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const DeclaratorDecl *D) { return true; } static bool classofKind(Kind K) { - return K >= DeclaratorFirst && K <= DeclaratorLast; + return K >= firstDeclarator && K <= lastDeclarator; } }; @@ -555,6 +612,7 @@ public: virtual void Destroy(ASTContext& C); virtual ~VarDecl(); + virtual SourceLocation getInnerLocStart() const; virtual SourceRange getSourceRange() const; StorageClass getStorageClass() const { return (StorageClass)SClass; } @@ -908,7 +966,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const VarDecl *D) { return true; } - static bool classofKind(Kind K) { return K >= VarFirst && K <= VarLast; } + static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; } }; class ImplicitParamDecl : public VarDecl { @@ -1063,6 +1121,15 @@ public: None, Extern, Static, PrivateExtern }; + /// \brief The kind of templated function a FunctionDecl can be. + enum TemplatedKind { + TK_NonTemplate, + TK_FunctionTemplate, + TK_MemberSpecialization, + TK_FunctionTemplateSpecialization, + TK_DependentFunctionTemplateSpecialization + }; + private: /// ParamInfo - new[]'d array of pointers to VarDecls for the formal /// parameters of this function. This is null if a prototype or if there are @@ -1154,17 +1221,31 @@ public: bool Qualified) const; virtual SourceRange getSourceRange() const { - return SourceRange(getLocation(), EndRangeLoc); + return SourceRange(getOuterLocStart(), EndRangeLoc); } void setLocEnd(SourceLocation E) { EndRangeLoc = E; } + /// \brief Returns true if the function has a body (definition). The + /// function body might be in any of the (re-)declarations of this + /// function. The variant that accepts a FunctionDecl pointer will + /// set that function declaration to the actual declaration + /// containing the body (if there is one). + bool hasBody(const FunctionDecl *&Definition) const; + + virtual bool hasBody() const { + const FunctionDecl* Definition; + return hasBody(Definition); + } + /// getBody - Retrieve the body (definition) of the function. The /// function body might be in any of the (re-)declarations of this /// function. The variant that accepts a FunctionDecl pointer will /// set that function declaration to the actual declaration /// containing the body (if there is one). + /// NOTE: For checking if there is a body, use hasBody() instead, to avoid + /// unnecessary PCH de-serialization of the body. Stmt *getBody(const FunctionDecl *&Definition) const; virtual Stmt *getBody() const { @@ -1301,6 +1382,12 @@ public: QualType getResultType() const { return getType()->getAs<FunctionType>()->getResultType(); } + + /// \brief Determine the type of an expression that calls this function. + QualType getCallResultType() const { + return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); + } + StorageClass getStorageClass() const { return StorageClass(SClass); } void setStorageClass(StorageClass SC) { SClass = SC; } @@ -1355,6 +1442,9 @@ public: /// X<int>::A is required, it will be instantiated from the /// declaration returned by getInstantiatedFromMemberFunction(). FunctionDecl *getInstantiatedFromMemberFunction() const; + + /// \brief What kind of templated function this is. + TemplatedKind getTemplatedKind() const; /// \brief If this function is an instantiation of a member function of a /// class template specialization, retrieves the member specialization @@ -1437,8 +1527,6 @@ public: /// \brief Specify that this function declaration is actually a function /// template specialization. /// - /// \param Context the AST context in which this function resides. - /// /// \param Template the function template that this function template /// specialization specializes. /// @@ -1450,11 +1538,53 @@ public: /// be inserted. /// /// \param TSK the kind of template specialization this is. + /// + /// \param TemplateArgsAsWritten location info of template arguments. + /// + /// \param PointOfInstantiation point at which the function template + /// specialization was first instantiated. void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, - const TemplateArgumentListInfo *TemplateArgsAsWritten = 0); + const TemplateArgumentListInfo *TemplateArgsAsWritten = 0, + SourceLocation PointOfInstantiation = SourceLocation()); + + /// \brief Specify that this function declaration is actually a function + /// template specialization. + /// + /// \param Template the function template that this function template + /// specialization specializes. + /// + /// \param NumTemplateArgs number of template arguments that produced this + /// function template specialization from the template. + /// + /// \param TemplateArgs array of template arguments that produced this + /// function template specialization from the template. + /// + /// \param TSK the kind of template specialization this is. + /// + /// \param NumTemplateArgsAsWritten number of template arguments that produced + /// this function template specialization from the template. + /// + /// \param TemplateArgsAsWritten array of location info for the template + /// arguments. + /// + /// \param LAngleLoc location of left angle token. + /// + /// \param RAngleLoc location of right angle token. + /// + /// \param PointOfInstantiation point at which the function template + /// specialization was first instantiated. + void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, + unsigned NumTemplateArgs, + const TemplateArgument *TemplateArgs, + TemplateSpecializationKind TSK, + unsigned NumTemplateArgsAsWritten, + TemplateArgumentLoc *TemplateArgsAsWritten, + SourceLocation LAngleLoc, + SourceLocation RAngleLoc, + SourceLocation PointOfInstantiation); /// \brief Specifies that this function declaration is actually a /// dependent function template specialization. @@ -1493,7 +1623,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FunctionDecl *D) { return true; } static bool classofKind(Kind K) { - return K >= FunctionFirst && K <= FunctionLast; + return K >= firstFunction && K <= lastFunction; } static DeclContext *castToDeclContext(const FunctionDecl *D) { return static_cast<DeclContext *>(const_cast<FunctionDecl*>(D)); @@ -1501,6 +1631,9 @@ public: static FunctionDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<FunctionDecl *>(const_cast<DeclContext*>(DC)); } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; @@ -1556,7 +1689,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FieldDecl *D) { return true; } - static bool classofKind(Kind K) { return K >= FieldFirst && K <= FieldLast; } + static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } }; /// EnumConstantDecl - An instance of this object exists for each enum constant @@ -1625,7 +1758,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TypeDecl *D) { return true; } - static bool classofKind(Kind K) { return K >= TypeFirst && K <= TypeLast; } + static bool classofKind(Kind K) { return K >= firstType && K <= lastType; } }; @@ -1715,10 +1848,7 @@ private: // A struct representing syntactic qualifier info, // to be used for the (uncommon) case of out-of-line declarations. - struct ExtInfo { - NestedNameSpecifier *NNS; - SourceRange NNSRange; - }; + typedef QualifierInfo ExtInfo; /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name /// is qualified, it points to the qualifier info (nns and range); @@ -1767,6 +1897,13 @@ public: 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; } + + /// getOuterLocStart - Return SourceLocation representing start of source + /// range taking into account any outer template declarations. + SourceLocation getOuterLocStart() const; virtual SourceRange getSourceRange() const; virtual TagDecl* getCanonicalDecl(); @@ -1830,24 +1967,34 @@ public: TypedefDecl *getTypedefForAnonDecl() const { return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get<TypedefDecl*>(); } - + void setTypedefForAnonDecl(TypedefDecl *TDD); - + NestedNameSpecifier *getQualifier() const { - return hasExtInfo() ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNS : 0; + return hasExtInfo() ? getExtInfo()->NNS : 0; } SourceRange getQualifierRange() const { - return hasExtInfo() - ? TypedefDeclOrQualifier.get<ExtInfo*>()->NNSRange - : SourceRange(); + return hasExtInfo() ? getExtInfo()->NNSRange : SourceRange(); } void setQualifierInfo(NestedNameSpecifier *Qualifier, SourceRange QualifierRange); + unsigned getNumTemplateParameterLists() const { + return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0; + } + TemplateParameterList *getTemplateParameterList(unsigned i) const { + assert(i < getNumTemplateParameterLists()); + return getExtInfo()->TemplParamLists[i]; + } + void setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, + TemplateParameterList **TPLists) { + getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); + } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TagDecl *D) { return true; } - static bool classofKind(Kind K) { return K >= TagFirst && K <= TagLast; } + static bool classofKind(Kind K) { return K >= firstTag && K <= lastTag; } static DeclContext *castToDeclContext(const TagDecl *D) { return static_cast<DeclContext *>(const_cast<TagDecl*>(D)); @@ -1855,6 +2002,9 @@ public: static TagDecl *castFromDeclContext(const DeclContext *DC) { return static_cast<TagDecl *>(const_cast<DeclContext*>(DC)); } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// EnumDecl - Represents an enum. As an extension, we allow forward-declared @@ -1896,9 +2046,17 @@ public: return cast<EnumDecl>(TagDecl::getCanonicalDecl()); } + const EnumDecl *getPreviousDeclaration() const { + return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration()); + } + EnumDecl *getPreviousDeclaration() { + return cast_or_null<EnumDecl>(TagDecl::getPreviousDeclaration()); + } + static EnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL, EnumDecl *PrevDecl); + static EnumDecl *Create(ASTContext &C, EmptyShell Empty); virtual void Destroy(ASTContext& C); @@ -1917,11 +2075,17 @@ public: typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; enumerator_iterator enumerator_begin() const { - return enumerator_iterator(this->decls_begin()); + const EnumDecl *E = cast_or_null<EnumDecl>(getDefinition()); + if (!E) + E = this; + return enumerator_iterator(E->decls_begin()); } enumerator_iterator enumerator_end() const { - return enumerator_iterator(this->decls_end()); + const EnumDecl *E = cast_or_null<EnumDecl>(getDefinition()); + if (!E) + E = this; + return enumerator_iterator(E->decls_end()); } /// getPromotionType - Return the integer type that enumerators @@ -2010,6 +2174,14 @@ public: SourceLocation L, IdentifierInfo *Id, SourceLocation TKL = SourceLocation(), RecordDecl* PrevDecl = 0); + static RecordDecl *Create(ASTContext &C, EmptyShell Empty); + + const RecordDecl *getPreviousDeclaration() const { + return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); + } + RecordDecl *getPreviousDeclaration() { + return cast_or_null<RecordDecl>(TagDecl::getPreviousDeclaration()); + } virtual void Destroy(ASTContext& C); @@ -2092,7 +2264,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const RecordDecl *D) { return true; } static bool classofKind(Kind K) { - return K >= RecordFirst && K <= RecordLast; + return K >= firstRecord && K <= lastRecord; } }; @@ -2127,11 +2299,13 @@ class BlockDecl : public Decl, public DeclContext { unsigned NumParams; Stmt *Body; + TypeSourceInfo *SignatureAsWritten; protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), - IsVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} + IsVariadic(false), ParamInfo(0), NumParams(0), Body(0), + SignatureAsWritten(0) {} virtual ~BlockDecl(); virtual void Destroy(ASTContext& C); @@ -2148,6 +2322,9 @@ public: Stmt *getBody() const { return (Stmt*) Body; } void setBody(CompoundStmt *B) { Body = (Stmt*) B; } + void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; } + TypeSourceInfo *getSignatureAsWritten() const { return SignatureAsWritten; } + // Iterator access to formal parameters. unsigned param_size() const { return getNumParams(); } typedef ParmVarDecl **param_iterator; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index c15aeef..2d2407f 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -68,12 +68,13 @@ class Decl { public: /// \brief Lists the kind of concrete classes of Decl. enum Kind { -#define DECL(Derived, Base) Derived, -#define DECL_RANGE(CommonBase, Start, End) \ - CommonBase##First = Start, CommonBase##Last = End, -#define LAST_DECL_RANGE(CommonBase, Start, End) \ - CommonBase##First = Start, CommonBase##Last = End -#include "clang/AST/DeclNodes.def" +#define DECL(DERIVED, BASE) DERIVED, +#define ABSTRACT_DECL(DECL) +#define DECL_RANGE(BASE, START, END) \ + first##BASE = START, last##BASE = END, +#define LAST_DECL_RANGE(BASE, START, END) \ + first##BASE = START, last##BASE = END +#include "clang/AST/DeclNodes.inc" }; /// \brief A placeholder type used to construct an empty shell of a @@ -244,7 +245,15 @@ protected: HasAttrs(false), Implicit(false), Used(false), Access(AS_none), PCHLevel(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { - if (Decl::CollectingStats()) addDeclKind(DK); + if (Decl::CollectingStats()) add(DK); + } + + Decl(Kind DK, EmptyShell Empty) + : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0), + HasAttrs(false), Implicit(false), Used(false), + Access(AS_none), PCHLevel(0), + IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { + if (Decl::CollectingStats()) add(DK); } virtual ~Decl(); @@ -296,6 +305,7 @@ public: } bool hasAttrs() const { return HasAttrs; } + void initAttrs(Attr *attrs); void addAttr(Attr *attr); const Attr *getAttrs() const { if (!HasAttrs) return 0; // common case, no attributes. @@ -328,7 +338,11 @@ public: /// \brief Whether this declaration was used, meaning that a definition /// is required. - bool isUsed() const; + /// + /// \param CheckUsedAttr When true, also consider the "used" attribute + /// (in addition to the "used" bit set by \c setUsed()) when determining + /// whether the function is used. + bool isUsed(bool CheckUsedAttr = true) const; void setUsed(bool U = true) { Used = U; } @@ -474,15 +488,16 @@ public: /// top-level Stmt* of that body. Otherwise this method returns null. virtual Stmt* getBody() const { return 0; } - /// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt. - CompoundStmt* getCompoundBody() const; + /// \brief Returns true if this Decl represents a declaration for a body of + /// code, such as a function or method definition. + virtual bool hasBody() const { return getBody() != 0; } /// getBodyRBrace - Gets the right brace of the body, if a body exists. /// This works whether the body is a CompoundStmt or a CXXTryStmt. SourceLocation getBodyRBrace() const; // global temp stats (until we have a per-module visitor) - static void addDeclKind(Kind k); + static void add(Kind k); static bool CollectingStats(bool Enable = false); static void PrintStats(); @@ -631,6 +646,8 @@ class DeclContext { /// another pointer. mutable Decl *LastDecl; + friend class ExternalASTSource; + protected: DeclContext(Decl::Kind K) : DeclKind(K), ExternalLexicalStorage(false), @@ -687,7 +704,7 @@ public: case Decl::ObjCMethod: return true; default: - return DeclKind >= Decl::FunctionFirst && DeclKind <= Decl::FunctionLast; + return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction; } } @@ -700,7 +717,7 @@ public: } bool isRecord() const { - return DeclKind >= Decl::RecordFirst && DeclKind <= Decl::RecordLast; + return DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord; } bool isNamespace() const { @@ -1083,9 +1100,10 @@ public: static bool classof(const Decl *D); static bool classof(const DeclContext *D) { return true; } -#define DECL_CONTEXT(Name) \ - static bool classof(const Name##Decl *D) { return true; } -#include "clang/AST/DeclNodes.def" +#define DECL(NAME, BASE) +#define DECL_CONTEXT(NAME) \ + static bool classof(const NAME##Decl *D) { return true; } +#include "clang/AST/DeclNodes.inc" void dumpDeclContext() const; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index c19c200..41474ab 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -92,6 +92,53 @@ namespace llvm { namespace clang { +/// AccessSpecDecl - An access specifier followed by colon ':'. +/// +/// An objects of this class represents sugar for the syntactic occurrence +/// of an access specifier followed by a colon in the list of member +/// specifiers of a C++ class definition. +/// +/// Note that they do not represent other uses of access specifiers, +/// such as those occurring in a list of base specifiers. +/// Also note that this class has nothing to do with so-called +/// "access declarations" (C++98 11.3 [class.access.dcl]). +class AccessSpecDecl : public Decl { + /// ColonLoc - The location of the ':'. + SourceLocation ColonLoc; + + AccessSpecDecl(AccessSpecifier AS, DeclContext *DC, + SourceLocation ASLoc, SourceLocation ColonLoc) + : Decl(AccessSpec, DC, ASLoc), ColonLoc(ColonLoc) { + setAccess(AS); + } +public: + /// getAccessSpecifierLoc - The location of the access specifier. + SourceLocation getAccessSpecifierLoc() const { return getLocation(); } + /// setAccessSpecifierLoc - Sets the location of the access specifier. + void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); } + + /// getColonLoc - The location of the colon following the access specifier. + SourceLocation getColonLoc() const { return ColonLoc; } + /// setColonLoc - Sets the location of the colon. + void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; } + + SourceRange getSourceRange() const { + return SourceRange(getAccessSpecifierLoc(), getColonLoc()); + } + + static AccessSpecDecl *Create(ASTContext &C, AccessSpecifier AS, + DeclContext *DC, SourceLocation ASLoc, + SourceLocation ColonLoc) { + return new (C) AccessSpecDecl(AS, DC, ASLoc, ColonLoc); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const AccessSpecDecl *D) { return true; } + static bool classofKind(Kind K) { return K == AccessSpec; } +}; + + /// CXXBaseSpecifier - A base class of a C++ class. /// /// Each CXXBaseSpecifier represents a single, direct base class (or @@ -271,7 +318,20 @@ class CXXRecordDecl : public RecordDecl { /// ComputedVisibleConversions - True when visible conversion functions are /// already computed and are available. bool ComputedVisibleConversions : 1; - + + /// \brief Whether we have already declared the default constructor or + /// do not need to have one declared. + bool DeclaredDefaultConstructor : 1; + + /// \brief Whether we have already declared the copy constructor. + bool DeclaredCopyConstructor : 1; + + /// \brief Whether we have already declared the copy-assignment operator. + bool DeclaredCopyAssignment : 1; + + /// \brief Whether we have already declared a destructor within the class. + bool DeclaredDestructor : 1; + /// Bases - Base classes of this class. /// FIXME: This is wasted space for a union. CXXBaseSpecifier *Bases; @@ -367,6 +427,13 @@ public: virtual const CXXRecordDecl *getCanonicalDecl() const { return cast<CXXRecordDecl>(RecordDecl::getCanonicalDecl()); } + + const CXXRecordDecl *getPreviousDeclaration() const { + return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDeclaration()); + } + CXXRecordDecl *getPreviousDeclaration() { + return cast_or_null<CXXRecordDecl>(RecordDecl::getPreviousDeclaration()); + } CXXRecordDecl *getDefinition() const { if (!DefinitionData) return 0; @@ -380,6 +447,7 @@ public: SourceLocation TKL = SourceLocation(), CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); + static CXXRecordDecl *Create(ASTContext &C, EmptyShell Empty); virtual void Destroy(ASTContext& C); @@ -476,6 +544,20 @@ public: return data().FirstFriend != 0; } + /// \brief Determine whether this class has had its default constructor + /// declared implicitly or does not need one declared implicitly. + /// + /// This value is used for lazy creation of default constructors. + bool hasDeclaredDefaultConstructor() const { + return data().DeclaredDefaultConstructor; + } + + /// \brief Note whether this class has already had its default constructor + /// implicitly declared or doesn't need one. + void setDeclaredDefaultConstructor(bool DDC) { + data().DeclaredDefaultConstructor = DDC; + } + /// hasConstCopyConstructor - Determines whether this class has a /// copy constructor that accepts a const-qualified argument. bool hasConstCopyConstructor(ASTContext &Context) const; @@ -484,12 +566,18 @@ public: CXXConstructorDecl *getCopyConstructor(ASTContext &Context, unsigned TypeQuals) const; - /// hasConstCopyAssignment - Determines whether this class has a - /// copy assignment operator that accepts a const-qualified argument. - /// It returns its decl in MD if found. - bool hasConstCopyAssignment(ASTContext &Context, - const CXXMethodDecl *&MD) const; - + /// \brief Retrieve the copy-assignment operator for this class, if available. + /// + /// This routine attempts to find the copy-assignment operator for this + /// class, using a simplistic form of overload resolution. + /// + /// \param ArgIsConst Whether the argument to the copy-assignment operator + /// is const-qualified. + /// + /// \returns The copy-assignment operator that can be invoked, or NULL if + /// a unique copy-assignment operator could not be found. + CXXMethodDecl *getCopyAssignmentOperator(bool ArgIsConst) const; + /// addedConstructor - Notify the class that another constructor has /// been added. This routine helps maintain information about the /// class based on which constructors have been added. @@ -509,9 +597,23 @@ public: return data().UserDeclaredCopyConstructor; } + /// \brief Determine whether this class has had its copy constructor + /// declared, either via the user or via an implicit declaration. + /// + /// This value is used for lazy creation of copy constructors. + bool hasDeclaredCopyConstructor() const { + return data().DeclaredCopyConstructor; + } + + /// \brief Note whether this class has already had its copy constructor + /// declared. + void setDeclaredCopyConstructor(bool DCC) { + data().DeclaredCopyConstructor = DCC; + } + /// addedAssignmentOperator - Notify the class that another assignment /// operator has been added. This routine helps maintain information about the - /// class based on which operators have been added. + /// class based on which operators have been added. void addedAssignmentOperator(ASTContext &Context, CXXMethodDecl *OpDecl); /// hasUserDeclaredCopyAssignment - Whether this class has a @@ -521,6 +623,20 @@ public: return data().UserDeclaredCopyAssignment; } + /// \brief Determine whether this class has had its copy assignment operator + /// declared, either via the user or via an implicit declaration. + /// + /// This value is used for lazy creation of copy assignment operators. + bool hasDeclaredCopyAssignment() const { + return data().DeclaredCopyAssignment; + } + + /// \brief Note whether this class has already had its copy assignment + /// operator declared. + void setDeclaredCopyAssignment(bool DCA) { + data().DeclaredCopyAssignment = DCA; + } + /// hasUserDeclaredDestructor - Whether this class has a /// user-declared destructor. When false, a destructor will be /// implicitly declared. @@ -533,8 +649,21 @@ public: /// fully defined, a destructor will be implicitly declared. void setUserDeclaredDestructor(bool UCD) { data().UserDeclaredDestructor = UCD; + if (UCD) + data().DeclaredDestructor = true; } + /// \brief Determine whether this class has had its destructor declared, + /// either via the user or via an implicit declaration. + /// + /// This value is used for lazy creation of destructors. + bool hasDeclaredDestructor() const { return data().DeclaredDestructor; } + + /// \brief Note whether this class has already had its destructor declared. + void setDeclaredDestructor(bool DD) { + data().DeclaredDestructor = DD; + } + /// getConversions - Retrieve the overload set containing all of the /// conversion functions in this class. UnresolvedSetImpl *getConversionFunctions() { @@ -726,10 +855,10 @@ public: void setTemplateSpecializationKind(TemplateSpecializationKind TSK); /// getDefaultConstructor - Returns the default constructor for this class - CXXConstructorDecl *getDefaultConstructor(ASTContext &Context); + CXXConstructorDecl *getDefaultConstructor(); /// getDestructor - Returns the destructor decl for this class. - CXXDestructorDecl *getDestructor(ASTContext &Context) const; + CXXDestructorDecl *getDestructor() const; /// isLocalClass - If the class is a local class [class.local], returns /// the enclosing function declaration. @@ -920,14 +1049,15 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { - return K == CXXRecord || - K == ClassTemplateSpecialization || - K == ClassTemplatePartialSpecialization; + return K >= firstCXXRecord && K <= lastCXXRecord; } static bool classof(const CXXRecordDecl *D) { return true; } static bool classof(const ClassTemplateSpecializationDecl *D) { return true; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// CXXMethodDecl - Represents a static or instance method of a @@ -984,6 +1114,7 @@ public: method_iterator begin_overridden_methods() const; method_iterator end_overridden_methods() const; + unsigned size_overridden_methods() const; /// getParent - Returns the parent of this method declaration, which /// is the class in which this method is defined. @@ -1012,7 +1143,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXMethodDecl *D) { return true; } static bool classofKind(Kind K) { - return K >= CXXMethod && K <= CXXConversion; + return K >= firstCXXMethod && K <= lastCXXMethod; } }; @@ -1387,6 +1518,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConstructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConstructor; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// CXXDestructorDecl - Represents a C++ destructor within a @@ -1450,6 +1584,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXDestructorDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXDestructor; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// CXXConversionDecl - Represents a C++ conversion function within a @@ -1504,6 +1641,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const CXXConversionDecl *D) { return true; } static bool classofKind(Kind K) { return K == CXXConversion; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// LinkageSpecDecl - This represents a linkage specification. For example: @@ -1607,7 +1747,7 @@ class UsingDirectiveDecl : public NamedDecl { SourceLocation IdentLoc, NamedDecl *Nominated, DeclContext *CommonAncestor) - : NamedDecl(Decl::UsingDirective, DC, L, getName()), + : NamedDecl(UsingDirective, DC, L, getName()), NamespaceLoc(NamespcLoc), QualifierRange(QualifierRange), Qualifier(Qualifier), IdentLoc(IdentLoc), NominatedNamespace(Nominated), @@ -1680,7 +1820,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingDirectiveDecl *D) { return true; } - static bool classofKind(Kind K) { return K == Decl::UsingDirective; } + static bool classofKind(Kind K) { return K == UsingDirective; } // Friend for getUsingDirectiveName. friend class DeclContext; @@ -1714,7 +1854,7 @@ class NamespaceAliasDecl : public NamedDecl { SourceRange QualifierRange, NestedNameSpecifier *Qualifier, SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(Decl::NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc), + : NamedDecl(NamespaceAlias, DC, L, Alias), AliasLoc(AliasLoc), QualifierRange(QualifierRange), Qualifier(Qualifier), IdentLoc(IdentLoc), Namespace(Namespace) { } @@ -1786,7 +1926,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const NamespaceAliasDecl *D) { return true; } - static bool classofKind(Kind K) { return K == Decl::NamespaceAlias; } + static bool classofKind(Kind K) { return K == NamespaceAlias; } }; /// UsingShadowDecl - Represents a shadow declaration introduced into @@ -1809,9 +1949,12 @@ class UsingShadowDecl : public NamedDecl { UsingShadowDecl(DeclContext *DC, SourceLocation Loc, UsingDecl *Using, NamedDecl *Target) - : NamedDecl(UsingShadow, DC, Loc, Target->getDeclName()), + : NamedDecl(UsingShadow, DC, Loc, DeclarationName()), Underlying(Target), Using(Using) { - IdentifierNamespace = Target->getIdentifierNamespace(); + if (Target) { + setDeclName(Target->getDeclName()); + IdentifierNamespace = Target->getIdentifierNamespace(); + } setImplicit(); } @@ -1828,7 +1971,11 @@ public: /// \brief Sets the underlying declaration which has been brought into the /// local scope. - void setTargetDecl(NamedDecl* ND) { Underlying = ND; } + void setTargetDecl(NamedDecl* ND) { + assert(ND && "Target decl is null!"); + Underlying = ND; + IdentifierNamespace = ND->getIdentifierNamespace(); + } /// \brief Gets the using declaration to which this declaration is tied. UsingDecl *getUsingDecl() const { return Using; } @@ -1866,7 +2013,7 @@ class UsingDecl : public NamedDecl { UsingDecl(DeclContext *DC, SourceLocation L, SourceRange NNR, SourceLocation UL, NestedNameSpecifier* TargetNNS, DeclarationName Name, bool IsTypeNameArg) - : NamedDecl(Decl::Using, DC, L, Name), + : NamedDecl(Using, DC, L, Name), NestedNameRange(NNR), UsingLocation(UL), TargetNestedName(TargetNNS), IsTypeName(IsTypeNameArg) { } @@ -1934,7 +2081,10 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UsingDecl *D) { return true; } - static bool classofKind(Kind K) { return K == Decl::Using; } + static bool classofKind(Kind K) { return K == Using; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// UnresolvedUsingValueDecl - Represents a dependent using @@ -1960,7 +2110,7 @@ class UnresolvedUsingValueDecl : public ValueDecl { NestedNameSpecifier *TargetNNS, SourceLocation TargetNameLoc, DeclarationName TargetName) - : ValueDecl(Decl::UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty), + : ValueDecl(UnresolvedUsingValue, DC, TargetNameLoc, TargetName, Ty), TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), TargetNestedNameSpecifier(TargetNNS) { } @@ -1997,7 +2147,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const UnresolvedUsingValueDecl *D) { return true; } - static bool classofKind(Kind K) { return K == Decl::UnresolvedUsingValue; } + static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } }; /// UnresolvedUsingTypenameDecl - Represents a dependent using @@ -2026,7 +2176,7 @@ class UnresolvedUsingTypenameDecl : public TypeDecl { SourceLocation TypenameLoc, SourceRange TargetNNR, NestedNameSpecifier *TargetNNS, SourceLocation TargetNameLoc, IdentifierInfo *TargetName) - : TypeDecl(Decl::UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), + : TypeDecl(UnresolvedUsingTypename, DC, TargetNameLoc, TargetName), TargetNestedNameRange(TargetNNR), UsingLocation(UsingLoc), TypenameLocation(TypenameLoc), TargetNestedNameSpecifier(TargetNNS) { } @@ -2070,7 +2220,7 @@ public: 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 == Decl::UnresolvedUsingTypename; } + static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } }; /// StaticAssertDecl - Represents a C++0x static_assert declaration. @@ -2098,7 +2248,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(StaticAssertDecl *D) { return true; } - static bool classofKind(Kind K) { return K == Decl::StaticAssert; } + static bool classofKind(Kind K) { return K == StaticAssert; } }; /// Insertion operator for diagnostics. This allows sending AccessSpecifier's diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index a20625d..2807d16 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -59,10 +59,14 @@ private: FriendLoc(FriendL) { } + explicit FriendDecl(EmptyShell Empty) + : Decl(Decl::Friend, Empty), NextFriend(0) { } + public: static FriendDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, FriendUnion Friend_, SourceLocation FriendL); + static FriendDecl *Create(ASTContext &C, EmptyShell Empty); /// If this friend declaration names an (untemplated but /// possibly dependent) type, return the type; otherwise @@ -87,6 +91,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FriendDecl *D) { return true; } static bool classofKind(Kind K) { return K == Decl::Friend; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// An iterator over the friend declarations of a class. diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 97d1656..fb8596f 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -239,6 +239,12 @@ public: QualType getResultType() const { return MethodDeclType; } void setResultType(QualType T) { MethodDeclType = T; } + /// \brief Determine the type of an expression that sends a message to this + /// function. + QualType getSendResultType() const { + return getResultType().getCallResultType(getASTContext()); + } + TypeSourceInfo *getResultTypeSourceInfo() const { return ResultTInfo; } void setResultTypeSourceInfo(TypeSourceInfo *TInfo) { ResultTInfo = TInfo; } @@ -417,8 +423,8 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCContainerDecl *D) { return true; } static bool classofKind(Kind K) { - return K >= ObjCContainerFirst && - K <= ObjCContainerLast; + return K >= firstObjCContainer && + K <= lastObjCContainer; } static DeclContext *castToDeclContext(const ObjCContainerDecl *D) { @@ -550,8 +556,8 @@ public: void setCategoryList(ObjCCategoryDecl *category) { CategoryList = category; } - - ObjCCategoryDecl* getClassExtension() const; + + ObjCCategoryDecl* getFirstClassExtension() const; ObjCPropertyDecl *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const; @@ -983,6 +989,7 @@ public: } bool IsClassExtension() const { return getIdentifier() == 0; } + const ObjCCategoryDecl *getNextClassExtension() const; typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; ivar_iterator ivar_begin() const { @@ -1059,7 +1066,7 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ObjCImplDecl *D) { return true; } static bool classofKind(Kind K) { - return K >= ObjCImplFirst && K <= ObjCImplLast; + return K >= firstObjCImpl && K <= lastObjCImpl; } }; @@ -1306,9 +1313,9 @@ public: enum PropertyControl { None, Required, Optional }; private: SourceLocation AtLoc; // location of @property - QualType DeclType; + TypeSourceInfo *DeclType; unsigned PropertyAttributes : 8; - + unsigned PropertyAttributesAsWritten : 8; // @required/@optional unsigned PropertyImplementation : 2; @@ -1320,9 +1327,11 @@ private: ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - SourceLocation AtLocation, QualType T) + SourceLocation AtLocation, TypeSourceInfo *T) : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), DeclType(T), - PropertyAttributes(OBJC_PR_noattr), PropertyImplementation(None), + PropertyAttributes(OBJC_PR_noattr), + PropertyAttributesAsWritten(OBJC_PR_noattr), + PropertyImplementation(None), GetterName(Selector()), SetterName(Selector()), GetterMethodDecl(0), SetterMethodDecl(0) , PropertyIvarDecl(0) {} @@ -1330,13 +1339,14 @@ public: static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation AtLocation, - QualType T, + TypeSourceInfo *T, PropertyControl propControl = None); SourceLocation getAtLoc() const { return AtLoc; } void setAtLoc(SourceLocation L) { AtLoc = L; } - QualType getType() const { return DeclType; } - void setType(QualType T) { DeclType = T; } + TypeSourceInfo *getTypeSourceInfo() const { return DeclType; } + QualType getType() const { return DeclType->getType(); } + void setType(TypeSourceInfo *T) { DeclType = T; } PropertyAttributeKind getPropertyAttributes() const { return PropertyAttributeKind(PropertyAttributes); @@ -1345,6 +1355,14 @@ public: PropertyAttributes |= PRVal; } + PropertyAttributeKind getPropertyAttributesAsWritten() const { + return PropertyAttributeKind(PropertyAttributesAsWritten); + } + + void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) { + PropertyAttributesAsWritten = PRVal; + } + void makeitReadWriteAttribute(void) { PropertyAttributes &= ~OBJC_PR_readonly; PropertyAttributes |= OBJC_PR_readwrite; diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index b7b90b1..135dd3a 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -180,18 +180,29 @@ public: TemplateArgumentListBuilder &Builder, bool TakeArgs); + /// TemplateArgumentList - It copies the template arguments into a locally + /// new[]'d array. + TemplateArgumentList(ASTContext &Context, + const TemplateArgument *Args, unsigned NumArgs); + /// Produces a shallow copy of the given template argument list. This /// assumes that the input argument list outlives it. This takes the list as /// a pointer to avoid looking like a copy constructor, since this really /// really isn't safe to use that way. explicit TemplateArgumentList(const TemplateArgumentList *Other); - + + TemplateArgumentList() : NumFlatArguments(0), NumStructuredArguments(0) { } + /// Used to release the memory associated with a TemplateArgumentList /// object. FIXME: This is currently not called anywhere, but the /// memory will still be freed when using a BumpPtrAllocator. void Destroy(ASTContext &C); ~TemplateArgumentList(); + + /// \brief Copies the template arguments into a locally new[]'d array. + void init(ASTContext &Context, + const TemplateArgument *Args, unsigned NumArgs); /// \brief Retrieve the template argument at a given index. const TemplateArgument &get(unsigned Idx) const { @@ -261,12 +272,27 @@ public: static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; } static bool classofKind(Kind K) { - return K >= TemplateFirst && K <= TemplateLast; + return K >= firstTemplate && K <= lastTemplate; + } + + SourceRange getSourceRange() const { + return SourceRange(TemplateParams->getTemplateLoc(), + TemplatedDecl->getSourceRange().getEnd()); } protected: NamedDecl *TemplatedDecl; TemplateParameterList* TemplateParams; + +public: + /// \brief Initialize the underlying templated declaration and + /// template parameters. + void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { + assert(TemplatedDecl == 0 && "TemplatedDecl already set!"); + assert(TemplateParams == 0 && "TemplateParams already set!"); + TemplatedDecl = templatedDecl; + TemplateParams = templateParams; + } }; /// \brief Provides information about a function template specialization, @@ -353,8 +379,9 @@ class MemberSpecializationInfo { public: explicit - MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK) - : MemberAndTSK(IF, TSK - 1), PointOfInstantiation() { + MemberSpecializationInfo(NamedDecl *IF, TemplateSpecializationKind TSK, + SourceLocation POI = SourceLocation()) + : MemberAndTSK(IF, TSK - 1), PointOfInstantiation(POI) { assert(TSK != TSK_Undeclared && "Cannot encode undeclared template specializations for members"); } @@ -602,6 +629,9 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K == FunctionTemplate; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; //===----------------------------------------------------------------------===// @@ -634,9 +664,11 @@ protected: public: /// Get the nesting depth of the template parameter. unsigned getDepth() const { return Depth; } + void setDepth(unsigned D) { Depth = D; } /// Get the position of the template parameter within its parameter list. unsigned getPosition() const { return Position; } + void setPosition(unsigned P) { Position = P; } /// Get the index of the template parameter within its parameter list. unsigned getIndex() const { return Position; } @@ -675,6 +707,7 @@ public: SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, bool Typename, bool ParameterPack); + static TemplateTypeParmDecl *Create(ASTContext &C, EmptyShell Empty); /// \brief Whether this template type parameter was declared with /// the 'typename' keyword. If not, it was declared with the 'class' @@ -711,6 +744,13 @@ public: DefaultArgument = 0; InheritedDefault = false; } + + /// \brief Set whether this template type parameter was declared with + /// 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; @@ -734,15 +774,16 @@ public: /// @endcode class NonTypeTemplateParmDecl : public VarDecl, protected TemplateParmPosition { - /// \brief The default template argument, if any. - Expr *DefaultArgument; + /// \brief The default template argument, if any, and whether or not + /// it was inherited. + llvm::PointerIntPair<Expr*, 1, bool> DefaultArgumentAndInherited; NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo) : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None, VarDecl::None), - TemplateParmPosition(D, P), DefaultArgument(0) + TemplateParmPosition(D, P), DefaultArgumentAndInherited(0, false) { } public: @@ -751,22 +792,43 @@ public: unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo); using TemplateParmPosition::getDepth; + using TemplateParmPosition::setDepth; using TemplateParmPosition::getPosition; + using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { return DefaultArgument; } + bool hasDefaultArgument() const { + return DefaultArgumentAndInherited.getPointer() != 0; + } /// \brief Retrieve the default argument, if any. - Expr *getDefaultArgument() const { return DefaultArgument; } + Expr *getDefaultArgument() const { + return DefaultArgumentAndInherited.getPointer(); + } /// \brief Retrieve the location of the default argument, if any. SourceLocation getDefaultArgumentLoc() const; - /// \brief Set the default argument for this template parameter. - void setDefaultArgument(Expr *DefArg) { - DefaultArgument = DefArg; + /// \brief Determines whether the default argument was inherited + /// from a previous declaration of this template. + bool defaultArgumentWasInherited() const { + return DefaultArgumentAndInherited.getInt(); + } + + /// \brief Set the default argument for this template parameter, and + /// whether that default argument was inherited from another + /// declaration. + void setDefaultArgument(Expr *DefArg, bool Inherited) { + DefaultArgumentAndInherited.setPointer(DefArg); + DefaultArgumentAndInherited.setInt(Inherited); + } + + /// \brief Removes the default argument of this template parameter. + void removeDefaultArgument() { + DefaultArgumentAndInherited.setPointer(0); + DefaultArgumentAndInherited.setInt(false); } // Implement isa/cast/dyncast/etc. @@ -785,14 +847,17 @@ public: class TemplateTemplateParmDecl : public TemplateDecl, protected TemplateParmPosition { - /// \brief The default template argument, if any. + /// DefaultArgument - The default template argument, if any. TemplateArgumentLoc DefaultArgument; + /// Whether or not the default argument was inherited. + bool DefaultArgumentWasInherited; TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params) : TemplateDecl(TemplateTemplateParm, DC, L, Id, Params), - TemplateParmPosition(D, P), DefaultArgument() + TemplateParmPosition(D, P), DefaultArgument(), + DefaultArgumentWasInherited(false) { } public: @@ -807,24 +872,45 @@ public: /// \brief Determine whether this template parameter has a default /// argument. - bool hasDefaultArgument() const { - return !DefaultArgument.getArgument().isNull(); + bool hasDefaultArgument() const { + return !DefaultArgument.getArgument().isNull(); } /// \brief Retrieve the default argument, if any. - const TemplateArgumentLoc &getDefaultArgument() const { - return DefaultArgument; + const TemplateArgumentLoc &getDefaultArgument() const { + return DefaultArgument; + } + + /// \brief Retrieve the location of the default argument, if any. + SourceLocation getDefaultArgumentLoc() const; + + /// \brief Determines whether the default argument was inherited + /// from a previous declaration of this template. + bool defaultArgumentWasInherited() const { + return DefaultArgumentWasInherited; } - /// \brief Set the default argument for this template parameter. - void setDefaultArgument(const TemplateArgumentLoc &DefArg) { + /// \brief Set the default argument for this template parameter, and + /// whether that default argument was inherited from another + /// declaration. + void setDefaultArgument(const TemplateArgumentLoc &DefArg, bool Inherited) { DefaultArgument = DefArg; + DefaultArgumentWasInherited = Inherited; + } + + /// \brief Removes the default argument of this template parameter. + void removeDefaultArgument() { + DefaultArgument = TemplateArgumentLoc(); + DefaultArgumentWasInherited = false; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateTemplateParmDecl *D) { return true; } static bool classofKind(Kind K) { return K == TemplateTemplateParm; } + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// \brief Represents a class template specialization, which refers to @@ -860,9 +946,22 @@ class ClassTemplateSpecializationDecl llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; - /// \brief The type-as-written of an explicit template specialization. + /// \brief Further info for explicit template specialization/instantiation. + struct ExplicitSpecializationInfo { + /// \brief The type-as-written. + TypeSourceInfo *TypeAsWritten; + /// \brief The location of the extern keyword. + SourceLocation ExternLoc; + /// \brief The location of the template keyword. + SourceLocation TemplateKeywordLoc; + + ExplicitSpecializationInfo() + : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {} + }; + + /// \brief Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. - TypeSourceInfo *TypeAsWritten; + ExplicitSpecializationInfo *ExplicitInfo; /// \brief The template arguments used to describe this specialization. TemplateArgumentList TemplateArgs; @@ -881,12 +980,16 @@ protected: TemplateArgumentListBuilder &Builder, ClassTemplateSpecializationDecl *PrevDecl); + explicit ClassTemplateSpecializationDecl(Kind DK); + public: static ClassTemplateSpecializationDecl * Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation L, ClassTemplateDecl *SpecializedTemplate, TemplateArgumentListBuilder &Builder, ClassTemplateSpecializationDecl *PrevDecl); + static ClassTemplateSpecializationDecl * + Create(ASTContext &Context, EmptyShell Empty); virtual void Destroy(ASTContext& C); @@ -903,6 +1006,14 @@ public: return TemplateArgs; } + /// \brief Initialize the template arguments of the class template + /// specialization. + void initTemplateArgs(TemplateArgument *Args, unsigned NumArgs) { + assert(TemplateArgs.flat_size() == 0 && + "Template arguments already initialized!"); + TemplateArgs.init(getASTContext(), Args, NumArgs); + } + /// \brief Determine the kind of specialization that this /// declaration represents. TemplateSpecializationKind getSpecializationKind() const { @@ -943,6 +1054,19 @@ public: SpecializedTemplate.get<ClassTemplateDecl*>()); } + /// \brief Retrieve the class template or class template partial + /// specialization which was specialized by this. + llvm::PointerUnion<ClassTemplateDecl *, + ClassTemplatePartialSpecializationDecl *> + getSpecializedTemplateOrPartial() const { + if (SpecializedPartialSpecialization *PartialSpec + = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) + return PartialSpec->PartialSpecialization; + + return const_cast<ClassTemplateDecl*>( + SpecializedTemplate.get<ClassTemplateDecl*>()); + } + /// \brief Retrieve the set of template arguments that should be used /// to instantiate members of the class template or class template partial /// specialization from which this class template specialization was @@ -967,6 +1091,8 @@ public: /// template arguments have been deduced. void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, TemplateArgumentList *TemplateArgs) { + assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() && + "Already set to a class template partial specialization!"); SpecializedPartialSpecialization *PS = new (getASTContext()) SpecializedPartialSpecialization(); PS->PartialSpecialization = PartialSpec; @@ -974,17 +1100,59 @@ public: SpecializedTemplate = PS; } + /// \brief Note that this class template specialization is actually an + /// instantiation of the given class template partial specialization whose + /// template arguments have been deduced. + void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, + TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + ASTContext &Ctx = getASTContext(); + setInstantiationOf(PartialSpec, + new (Ctx) TemplateArgumentList(Ctx, TemplateArgs, + NumTemplateArgs)); + } + + /// \brief Note that this class template specialization is an instantiation + /// of the given class template. + void setInstantiationOf(ClassTemplateDecl *TemplDecl) { + assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() && + "Previously set to a class template partial specialization!"); + SpecializedTemplate = TemplDecl; + } + /// \brief Sets the type of this specialization as it was written by /// the user. This will be a class template specialization type. void setTypeAsWritten(TypeSourceInfo *T) { - TypeAsWritten = T; + if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = T; } - /// \brief Gets the type of this specialization as it was written by /// the user, if it was so written. TypeSourceInfo *getTypeAsWritten() const { - return TypeAsWritten; + return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0; + } + + /// \brief Gets the location of the extern keyword, if present. + SourceLocation getExternLoc() const { + return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); + } + /// \brief Sets the location of the extern keyword. + void setExternLoc(SourceLocation Loc) { + if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + ExplicitInfo->ExternLoc = Loc; + } + + /// \brief Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc) { + if (!ExplicitInfo) ExplicitInfo = new ExplicitSpecializationInfo; + ExplicitInfo->TemplateKeywordLoc = Loc; } + /// \brief Gets the location of the template keyword, if present. + SourceLocation getTemplateKeywordLoc() const { + return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); + } + + SourceLocation getInnerLocStart() const { return getTemplateKeywordLoc(); } void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, TemplateArgs.getFlatArgumentList(), TemplateArgs.flat_size(), @@ -1001,8 +1169,8 @@ public: static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { - return K == ClassTemplateSpecialization || - K == ClassTemplatePartialSpecialization; + return K >= firstClassTemplateSpecialization && + K <= lastClassTemplateSpecialization; } static bool classof(const ClassTemplateSpecializationDecl *) { @@ -1053,6 +1221,12 @@ class ClassTemplatePartialSpecializationDecl TemplateParams(Params), ArgsAsWritten(ArgInfos), NumArgsAsWritten(NumArgInfos), SequenceNumber(SequenceNumber), InstantiatedFromMember(0, false) { } + + ClassTemplatePartialSpecializationDecl() + : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization), + TemplateParams(0), ArgsAsWritten(0), + NumArgsAsWritten(0), SequenceNumber(0), + InstantiatedFromMember(0, false) { } public: static ClassTemplatePartialSpecializationDecl * @@ -1065,16 +1239,26 @@ public: ClassTemplatePartialSpecializationDecl *PrevDecl, unsigned SequenceNumber); + static ClassTemplatePartialSpecializationDecl * + Create(ASTContext &Context, EmptyShell Empty); + /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { return TemplateParams; } + void initTemplateParameters(TemplateParameterList *Params) { + assert(TemplateParams == 0 && "TemplateParams already set"); + TemplateParams = Params; + } + /// Get the template arguments as written. TemplateArgumentLoc *getTemplateArgsAsWritten() const { return ArgsAsWritten; } + void initTemplateArgsAsWritten(const TemplateArgumentListInfo &ArgInfos); + /// Get the number of template arguments as written. unsigned getNumTemplateArgsAsWritten() const { return NumArgsAsWritten; @@ -1083,6 +1267,7 @@ public: /// \brief Get the sequence number for this class template partial /// specialization. unsigned getSequenceNumber() const { return SequenceNumber; } + void setSequenceNumber(unsigned N) { SequenceNumber = N; } /// \brief Retrieve the member class template partial specialization from /// which this particular class template partial specialization was @@ -1199,26 +1384,19 @@ protected: llvm::PointerIntPair<ClassTemplateDecl *, 1, bool> InstantiatedFromMember; }; - // FIXME: Combine PreviousDeclaration with CommonPtr, as in - // FunctionTemplateDecl. - - /// \brief Previous declaration of this class template. - ClassTemplateDecl *PreviousDeclaration; + /// \brief A pointer to the previous declaration (if this is a redeclaration) + /// or to the data that is common to all declarations of this class template. + llvm::PointerUnion<Common*, ClassTemplateDecl*> CommonOrPrev; - /// \brief Pointer to the data that is common to all of the - /// declarations of this class template. - /// - /// The first declaration of a class template (e.g., the declaration - /// with no "previous declaration") owns this pointer. - Common *CommonPtr; + /// \brief Retrieves the "common" pointer shared by all + /// (re-)declarations of the same class template. Calling this routine + /// may implicitly allocate memory for the common pointer. + Common *getCommonPtr(); ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl, - ClassTemplateDecl *PrevDecl, Common *CommonPtr) + TemplateParameterList *Params, NamedDecl *Decl) : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl), - PreviousDeclaration(PrevDecl), CommonPtr(CommonPtr) { } - - ~ClassTemplateDecl(); + CommonOrPrev((Common*)0) { } public: /// Get the underlying class declarations of the template. @@ -1226,13 +1404,30 @@ public: return static_cast<CXXRecordDecl *>(TemplatedDecl); } - /// \brief Retrieve the previous declaration of this template. - ClassTemplateDecl *getPreviousDeclaration() const { - return PreviousDeclaration; + /// \brief Retrieve the previous declaration of this class template, or + /// NULL if no such declaration exists. + const ClassTemplateDecl *getPreviousDeclaration() const { + return CommonOrPrev.dyn_cast<ClassTemplateDecl*>(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + ClassTemplateDecl *getPreviousDeclaration() { + return CommonOrPrev.dyn_cast<ClassTemplateDecl*>(); + } + + /// \brief Set the previous declaration of this class template. + void setPreviousDeclaration(ClassTemplateDecl *Prev) { + if (Prev) + CommonOrPrev = Prev; } virtual ClassTemplateDecl *getCanonicalDecl(); + const ClassTemplateDecl *getCanonicalDecl() const { + return const_cast<ClassTemplateDecl*>(this)->getCanonicalDecl(); + } + /// Create a class template node. static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1243,14 +1438,14 @@ public: /// \brief Retrieve the set of specializations of this class template. llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { - return CommonPtr->Specializations; + return getCommonPtr()->Specializations; } /// \brief Retrieve the set of partial specializations of this class /// template. llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> & getPartialSpecializations() { - return CommonPtr->PartialSpecializations; + return getCommonPtr()->PartialSpecializations; } /// \brief Retrieve the partial specializations as an ordered list. @@ -1281,7 +1476,7 @@ public: /// typedef array this_type; // "array" is equivalent to "array<T, N>" /// }; /// \endcode - QualType getInjectedClassNameSpecialization(ASTContext &Context); + QualType getInjectedClassNameSpecialization(); /// \brief Retrieve the member class template that this class template was /// derived from. @@ -1303,13 +1498,13 @@ public: /// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, also a TCD). /// /// \returns null if this is not an instantiation of a member class template. - ClassTemplateDecl *getInstantiatedFromMemberTemplate() const { - return CommonPtr->InstantiatedFromMember.getPointer(); + ClassTemplateDecl *getInstantiatedFromMemberTemplate() { + return getCommonPtr()->InstantiatedFromMember.getPointer(); } void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) { - assert(!CommonPtr->InstantiatedFromMember.getPointer()); - CommonPtr->InstantiatedFromMember.setPointer(CTD); + assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); + getCommonPtr()->InstantiatedFromMember.setPointer(CTD); } /// \brief Determines whether this template was a specialization of a @@ -1328,14 +1523,14 @@ public: /// struct X<int>::Inner { /* ... */ }; /// \endcode bool isMemberSpecialization() { - return CommonPtr->InstantiatedFromMember.getInt(); + return getCommonPtr()->InstantiatedFromMember.getInt(); } /// \brief Note that this member template is a specialization. void setMemberSpecialization() { - assert(CommonPtr->InstantiatedFromMember.getPointer() && + assert(getCommonPtr()->InstantiatedFromMember.getPointer() && "Only member templates can be member template specializations"); - CommonPtr->InstantiatedFromMember.setInt(true); + getCommonPtr()->InstantiatedFromMember.setInt(true); } // Implement isa/cast/dyncast support @@ -1344,6 +1539,9 @@ public: static bool classofKind(Kind K) { return K == ClassTemplate; } virtual void Destroy(ASTContext& C); + + friend class PCHDeclReader; + friend class PCHDeclWriter; }; /// Declaration of a friend template. For example: diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h index 140e5c0..aee1998 100644 --- a/include/clang/AST/DeclVisitor.h +++ b/include/clang/AST/DeclVisitor.h @@ -30,20 +30,19 @@ class DeclVisitor { public: RetTy Visit(Decl *D) { switch (D->getKind()) { - default: assert(false && "Decl that isn't part of DeclNodes.def!"); -#define DECL(Derived, Base) \ - case Decl::Derived: DISPATCH(Derived##Decl, Derived##Decl); -#define ABSTRACT_DECL(Derived, Base) -#include "clang/AST/DeclNodes.def" + default: assert(false && "Decl that isn't part of DeclNodes.inc!"); +#define DECL(DERIVED, BASE) \ + case Decl::DERIVED: DISPATCH(DERIVED##Decl, DERIVED##Decl); +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" } } // If the implementation chooses not to implement a certain visit // method, fall back to the parent. -#define DECL(Derived, Base) \ - RetTy Visit##Derived##Decl(Derived##Decl *D) { DISPATCH(Base, Base); } -#define ABSTRACT_DECL(Derived, Base) DECL(Derived, Base) -#include "clang/AST/DeclNodes.def" +#define DECL(DERIVED, BASE) \ + RetTy Visit##DERIVED##Decl(DERIVED##Decl *D) { DISPATCH(BASE, BASE); } +#include "clang/AST/DeclNodes.inc" RetTy VisitDecl(Decl *D) { return RetTy(); } }; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 66639e2..8076443 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -162,9 +162,6 @@ public: }; isLvalueResult isLvalue(ASTContext &Ctx) const; - // Same as above, but excluding checks for non-object and void types in C - isLvalueResult isLvalueInternal(ASTContext &Ctx) const; - /// isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, /// does not have an incomplete type, does not have a const-qualified type, /// and if it is a structure or union, does not have any member (including, @@ -194,6 +191,95 @@ public: isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = 0) const; + /// \brief The return type of classify(). Represents the C++0x expression + /// taxonomy. + class Classification { + public: + /// \brief The various classification results. Most of these mean prvalue. + enum Kinds { + CL_LValue, + CL_XValue, + CL_Function, // Functions cannot be lvalues in C. + CL_Void, // Void cannot be an lvalue 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_PRValue // A prvalue for any other reason, of any other type + }; + /// \brief The results of modification testing. + enum ModifiableType { + CM_Untested, // testModifiable was false. + CM_Modifiable, + CM_RValue, // Not modifiable because it's an rvalue + CM_Function, // Not modifiable because it's a function; C++ only + CM_LValueCast, // Same as CM_RValue, but indicates GCC cast-as-lvalue ext + CM_NotBlockQualified, // Not captured in the closure + CM_NoSetterProperty,// Implicit assignment to ObjC property without setter + CM_ConstQualified, + CM_ArrayType, + CM_IncompleteType + }; + + private: + friend class Expr; + + unsigned short Kind; + unsigned short Modifiable; + + explicit Classification(Kinds k, ModifiableType m) + : Kind(k), Modifiable(m) + {} + + public: + Classification() {} + + Kinds getKind() const { return static_cast<Kinds>(Kind); } + ModifiableType getModifiable() const { + assert(Modifiable != CM_Untested && "Did not test for modifiability."); + return static_cast<ModifiableType>(Modifiable); + } + bool isLValue() const { return Kind == CL_LValue; } + bool isXValue() const { return Kind == CL_XValue; } + bool isGLValue() const { return Kind <= CL_XValue; } + bool isPRValue() const { return Kind >= CL_Function; } + bool isRValue() const { return Kind >= CL_XValue; } + bool isModifiable() const { return getModifiable() == CM_Modifiable; } + }; + /// \brief classify - Classify this expression according to the C++0x + /// expression taxonomy. + /// + /// C++0x defines ([basic.lval]) a new taxonomy of expressions to replace the + /// old lvalue vs rvalue. This function determines the type of expression this + /// is. There are three expression types: + /// - lvalues are classical lvalues as in C++03. + /// - prvalues are equivalent to rvalues in C++03. + /// - xvalues are expressions yielding unnamed rvalue references, e.g. a + /// function returning an rvalue reference. + /// lvalues and xvalues are collectively referred to as glvalues, while + /// prvalues and xvalues together form rvalues. + /// If a + Classification Classify(ASTContext &Ctx) const { + return ClassifyImpl(Ctx, 0); + } + + /// \brief classifyModifiable - Classify this expression according to the + /// C++0x expression taxonomy, and see if it is valid on the left side + /// of an assignment. + /// + /// This function extends classify in that it also tests whether the + /// expression is modifiable (C99 6.3.2.1p1). + /// \param Loc A source location that might be filled with a relevant location + /// if the expression is not modifiable. + Classification ClassifyModifiable(ASTContext &Ctx, SourceLocation &Loc) const{ + return ClassifyImpl(Ctx, &Loc); + } + +private: + Classification ClassifyImpl(ASTContext &Ctx, SourceLocation *Loc) const; + +public: + /// \brief If this expression refers to a bit-field, retrieve the /// declaration of that bit-field. FieldDecl *getBitField(); @@ -414,6 +500,7 @@ struct ExplicitTemplateArgumentList { void initializeFrom(const TemplateArgumentListInfo &List); void copyInto(TemplateArgumentListInfo &List) const; + static std::size_t sizeFor(unsigned NumTemplateArgs); static std::size_t sizeFor(const TemplateArgumentListInfo &List); }; @@ -474,27 +561,21 @@ class DeclRefExpr : public Expr { ValueDecl *D, SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs, QualType T); + + /// \brief Construct an empty declaration reference expression. + explicit DeclRefExpr(EmptyShell Empty) + : Expr(DeclRefExprClass, Empty) { } -protected: /// \brief Computes the type- and value-dependence flags for this /// declaration reference expression. void computeDependence(); - DeclRefExpr(StmtClass SC, ValueDecl *d, QualType t, SourceLocation l) : - Expr(SC, t, false, false), DecoratedD(d, 0), Loc(l) { - computeDependence(); - } - public: DeclRefExpr(ValueDecl *d, QualType t, SourceLocation l) : Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) { computeDependence(); } - /// \brief Construct an empty declaration reference expression. - explicit DeclRefExpr(EmptyShell Empty) - : Expr(DeclRefExprClass, Empty) { } - static DeclRefExpr *Create(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -502,6 +583,10 @@ public: SourceLocation NameLoc, QualType T, const TemplateArgumentListInfo *TemplateArgs = 0); + + /// \brief Construct an empty declaration reference expression. + static DeclRefExpr *CreateEmpty(ASTContext &Context, + bool HasQualifier, unsigned NumTemplateArgs); ValueDecl *getDecl() { return DecoratedD.getPointer(); } const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } @@ -591,6 +676,9 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class PCHStmtReader; + friend class PCHStmtWriter; }; /// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__. @@ -1560,11 +1648,6 @@ public: Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {} - /// \brief Build an empty member reference expression. - explicit MemberExpr(EmptyShell Empty) - : Expr(MemberExprClass, Empty), HasQualifierOrFoundDecl(false), - HasExplicitTemplateArgumentList(false) { } - static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, ValueDecl *memberdecl, DeclAccessPair founddecl, @@ -1937,6 +2020,7 @@ public: } const CXXBaseSpecifierArray& getBasePath() const { return BasePath; } + CXXBaseSpecifierArray& getBasePath() { return BasePath; } static bool classof(const Stmt *T) { return T->getStmtClass() >= firstCastExprConstant && @@ -2169,7 +2253,8 @@ public: /// predicates to categorize the respective opcodes. bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; } - bool isAdditiveOp() const { return Opc == Add || Opc == Sub; } + static bool isAdditiveOp(Opcode Opc) { return Opc == Add || Opc == Sub; } + bool isAdditiveOp() const { return isAdditiveOp(Opc); } static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; } bool isShiftOp() const { return isShiftOp(Opc); } @@ -3153,7 +3238,7 @@ public: ~ParenListExpr() {} /// \brief Build an empty paren list. - //explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } + explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } unsigned getNumExprs() const { return NumExprs; } @@ -3183,6 +3268,9 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class PCHStmtReader; + friend class PCHStmtWriter; }; @@ -3305,12 +3393,15 @@ class BlockDeclRefExpr : public Expr { SourceLocation Loc; bool IsByRef : 1; bool ConstQualAdded : 1; + Stmt *CopyConstructorVal; public: // FIXME: Fix type/value dependence! BlockDeclRefExpr(ValueDecl *d, QualType t, SourceLocation l, bool ByRef, - bool constAdded = false) - : Expr(BlockDeclRefExprClass, t, false, false), D(d), Loc(l), IsByRef(ByRef), - ConstQualAdded(constAdded) {} + bool constAdded = false, + Stmt *copyConstructorVal = 0) + : Expr(BlockDeclRefExprClass, t, (!t.isNull() && t->isDependentType()),false), + D(d), Loc(l), IsByRef(ByRef), + ConstQualAdded(constAdded), CopyConstructorVal(copyConstructorVal) {} // \brief Build an empty reference to a declared variable in a // block. @@ -3331,6 +3422,12 @@ public: bool isConstQualAdded() const { return ConstQualAdded; } void setConstQualAdded(bool C) { ConstQualAdded = C; } + + const Expr *getCopyConstructorExpr() const + { return cast_or_null<Expr>(CopyConstructorVal); } + Expr *getCopyConstructorExpr() + { return cast_or_null<Expr>(CopyConstructorVal); } + void setCopyConstructorExpr(Expr *E) { CopyConstructorVal = E; } static bool classof(const Stmt *T) { return T->getStmtClass() == BlockDeclRefExprClass; diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 0c493f3..b955381 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -465,7 +465,6 @@ class CXXDefaultArgExpr : public Expr { /// \brief The location where the default argument expression was used. SourceLocation Loc; -protected: CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) : Expr(SC, param->hasUnparsedDefaultArg() @@ -504,9 +503,6 @@ public: // Retrieve the parameter that the argument was created from. const ParmVarDecl *getParam() const { return Param.getPointer(); } ParmVarDecl *getParam() { return Param.getPointer(); } - - /// isExprStored - Return true if this expression owns the expression. - bool isExprStored() const { return Param.getInt(); } // Retrieve the actual argument to the function call. const Expr *getExpr() const { @@ -519,16 +515,10 @@ public: return *reinterpret_cast<Expr **> (this + 1); return getParam()->getDefaultArg(); } - - void setExpr(Expr *E) { - Param.setInt(true); - Param.setPointer((ParmVarDecl*)E); - } /// \brief Retrieve the location where this default argument was actually /// used. SourceLocation getUsedLocation() const { return Loc; } - void setUsedLocation(SourceLocation L) { Loc = L; } virtual SourceRange getSourceRange() const { // Default argument expressions have no representation in the @@ -544,6 +534,9 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class PCHStmtReader; + friend class PCHStmtWriter; }; /// CXXTemporary - Represents a C++ temporary. @@ -655,6 +648,9 @@ public: static CXXBindReferenceExpr *Create(ASTContext &C, Expr *SubExpr, bool ExtendsLifetime, bool RequiresTemporaryCopy); + + explicit CXXBindReferenceExpr(EmptyShell Empty) + : Expr(CXXBindReferenceExprClass, Empty) { } const Expr *getSubExpr() const { return cast<Expr>(SubExpr); } Expr *getSubExpr() { return cast<Expr>(SubExpr); } @@ -670,7 +666,7 @@ public: // extendsLifetime - Whether binding this reference extends the lifetime of // the expression being bound. FIXME: Add C++ reference. - bool extendsLifetime() { return ExtendsLifetime; } + bool extendsLifetime() const { return ExtendsLifetime; } // Implement isa/cast/dyncast/etc. static bool classof(const Stmt *T) { @@ -681,6 +677,8 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class PCHStmtReader; }; /// CXXConstructExpr - Represents a call to a C++ constructor. @@ -711,13 +709,20 @@ protected: ConstructionKind ConstructKind = CK_Complete); ~CXXConstructExpr() { } + /// \brief Construct an empty C++ construction expression. + CXXConstructExpr(StmtClass SC, EmptyShell Empty) + : Expr(SC, Empty), Constructor(0), Elidable(0), ZeroInitialization(0), + ConstructKind(0), Args(0), NumArgs(0) { } + virtual void DoDestroy(ASTContext &C); public: - /// \brief Construct an empty C++ construction expression that will store - /// \p numargs arguments. - CXXConstructExpr(EmptyShell Empty, ASTContext &C, unsigned numargs); - + /// \brief Construct an empty C++ construction expression. + explicit CXXConstructExpr(EmptyShell Empty) + : Expr(CXXConstructExprClass, Empty), Constructor(0), + Elidable(0), ZeroInitialization(0), + ConstructKind(0), Args(0), NumArgs(0) { } + static CXXConstructExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, @@ -790,6 +795,8 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class PCHStmtReader; }; /// CXXFunctionalCastExpr - Represents an explicit C++ type conversion @@ -829,12 +836,8 @@ public: /// /// This expression type represents a C++ "functional" cast /// (C++[expr.type.conv]) with N != 1 arguments that invokes a -/// constructor to build a temporary object. If N == 0 but no -/// constructor will be called (because the functional cast is -/// performing a value-initialized an object whose class type has no -/// user-declared constructors), CXXZeroInitValueExpr will represent -/// the functional cast. Finally, with N == 1 arguments the functional -/// cast expression will be represented by CXXFunctionalCastExpr. +/// constructor to build a temporary object. With N == 1 arguments the +/// functional cast expression will be represented by CXXFunctionalCastExpr. /// Example: /// @code /// struct X { X(int, float); } @@ -853,6 +856,8 @@ public: Expr **Args,unsigned NumArgs, SourceLocation rParenLoc, bool ZeroInitialization = false); + explicit CXXTemporaryObjectExpr(EmptyShell Empty) + : CXXConstructExpr(CXXTemporaryObjectExprClass, Empty) { } ~CXXTemporaryObjectExpr() { } @@ -866,24 +871,25 @@ public: return T->getStmtClass() == CXXTemporaryObjectExprClass; } static bool classof(const CXXTemporaryObjectExpr *) { return true; } + + friend class PCHStmtReader; }; -/// CXXZeroInitValueExpr - [C++ 5.2.3p2] +/// CXXScalarValueInitExpr - [C++ 5.2.3p2] /// Expression "T()" which creates a value-initialized rvalue of type -/// T, which is either a non-class type or a class type without any -/// user-defined constructors. +/// T, which is a non-class type. /// -class CXXZeroInitValueExpr : public Expr { +class CXXScalarValueInitExpr : public Expr { SourceLocation TyBeginLoc; SourceLocation RParenLoc; public: - CXXZeroInitValueExpr(QualType ty, SourceLocation tyBeginLoc, + CXXScalarValueInitExpr(QualType ty, SourceLocation tyBeginLoc, SourceLocation rParenLoc ) : - Expr(CXXZeroInitValueExprClass, ty, false, false), + Expr(CXXScalarValueInitExprClass, ty, false, false), TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} - explicit CXXZeroInitValueExpr(EmptyShell Shell) - : Expr(CXXZeroInitValueExprClass, Shell) { } + explicit CXXScalarValueInitExpr(EmptyShell Shell) + : Expr(CXXScalarValueInitExprClass, Shell) { } SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } @@ -902,9 +908,9 @@ public: } static bool classof(const Stmt *T) { - return T->getStmtClass() == CXXZeroInitValueExprClass; + return T->getStmtClass() == CXXScalarValueInitExprClass; } - static bool classof(const CXXZeroInitValueExpr *) { return true; } + static bool classof(const CXXScalarValueInitExpr *) { return true; } // Iterators virtual child_iterator child_begin(); @@ -916,15 +922,13 @@ public: class CXXNewExpr : public Expr { // Was the usage ::new, i.e. is the global new to be used? bool GlobalNew : 1; - // Was the form (type-id) used? Otherwise, it was new-type-id. - bool ParenTypeId : 1; // Is there an initializer? If not, built-ins are uninitialized, else they're // value-initialized. bool Initializer : 1; // Do we allocate an array? If so, the first SubExpr is the size expression. bool Array : 1; // The number of placement new arguments. - unsigned NumPlacementArgs : 14; + unsigned NumPlacementArgs : 15; // The number of constructor arguments. This may be 1 even for non-class // types; use the pseudo copy constructor. unsigned NumConstructorArgs : 14; @@ -941,12 +945,18 @@ class CXXNewExpr : public Expr { // Must be null for all other types. CXXConstructorDecl *Constructor; + /// \brief If the allocated type was expressed as a parenthesized type-id, + /// the source range covering the parenthesized type-id. + SourceRange TypeIdParens; + SourceLocation StartLoc; SourceLocation EndLoc; + friend class PCHStmtReader; public: CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, - Expr **placementArgs, unsigned numPlaceArgs, bool ParenTypeId, + Expr **placementArgs, unsigned numPlaceArgs, + SourceRange TypeIdParens, Expr *arraySize, CXXConstructorDecl *constructor, bool initializer, Expr **constructorArgs, unsigned numConsArgs, FunctionDecl *operatorDelete, QualType ty, @@ -989,10 +999,11 @@ public: return cast<Expr>(SubExprs[Array + i]); } + bool isParenTypeId() const { return TypeIdParens.isValid(); } + SourceRange getTypeIdParens() const { return TypeIdParens; } + bool isGlobalNew() const { return GlobalNew; } void setGlobalNew(bool V) { GlobalNew = V; } - bool isParenTypeId() const { return ParenTypeId; } - void setParenTypeId(bool V) { ParenTypeId = V; } bool hasInitializer() const { return Initializer; } void setHasInitializer(bool V) { Initializer = V; } @@ -1082,18 +1093,26 @@ public: : Expr(CXXDeleteExprClass, ty, false, false), GlobalDelete(globalDelete), ArrayForm(arrayForm), OperatorDelete(operatorDelete), Argument(arg), Loc(loc) { } + explicit CXXDeleteExpr(EmptyShell Shell) + : Expr(CXXDeleteExprClass, Shell), OperatorDelete(0), Argument(0) { } bool isGlobalDelete() const { return GlobalDelete; } bool isArrayForm() const { return ArrayForm; } + + void setGlobalDelete(bool V) { GlobalDelete = V; } + void setArrayForm(bool V) { ArrayForm = V; } FunctionDecl *getOperatorDelete() const { return OperatorDelete; } + void setOperatorDelete(FunctionDecl *D) { OperatorDelete = D; } Expr *getArgument() { return cast<Expr>(Argument); } const Expr *getArgument() const { return cast<Expr>(Argument); } + void setArgument(Expr *E) { Argument = E; } virtual SourceRange getSourceRange() const { return SourceRange(Loc, Argument->getLocEnd()); } + void setStartLoc(SourceLocation L) { Loc = L; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXDeleteExprClass; @@ -1215,6 +1234,10 @@ public: ScopeType(ScopeType), ColonColonLoc(ColonColonLoc), TildeLoc(TildeLoc), DestroyedType(DestroyedType) { } + explicit CXXPseudoDestructorExpr(EmptyShell Shell) + : Expr(CXXPseudoDestructorExprClass, Shell), + Base(0), IsArrow(false), Qualifier(0), ScopeType(0) { } + void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast<Expr>(Base); } @@ -1227,11 +1250,13 @@ public: /// the nested-name-specifier that precedes the member name. Otherwise, /// returns an empty source range. SourceRange getQualifierRange() const { return QualifierRange; } + void setQualifierRange(SourceRange R) { QualifierRange = R; } /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. NestedNameSpecifier *getQualifier() const { return Qualifier; } + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } /// \brief Determine whether this pseudo-destructor expression was written /// using an '->' (otherwise, it used a '.'). @@ -1240,6 +1265,7 @@ public: /// \brief Retrieve the location of the '.' or '->' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } + void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } /// \brief Retrieve the scope type in a qualified pseudo-destructor /// expression. @@ -1251,13 +1277,16 @@ public: /// nested-name-specifier. It is stored as the "scope type" of the pseudo- /// destructor expression. TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } + void setScopeTypeInfo(TypeSourceInfo *Info) { ScopeType = Info; } /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor /// expression. SourceLocation getColonColonLoc() const { return ColonColonLoc; } + void setColonColonLoc(SourceLocation L) { ColonColonLoc = L; } /// \brief Retrieve the location of the '~'. SourceLocation getTildeLoc() const { return TildeLoc; } + void setTildeLoc(SourceLocation L) { TildeLoc = L; } /// \brief Retrieve the source location information for the type /// being destroyed. @@ -1285,6 +1314,17 @@ public: return DestroyedType.getLocation(); } + /// \brief Set the name of destroyed type for a dependent pseudo-destructor + /// expression. + void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) { + DestroyedType = PseudoDestructorTypeStorage(II, Loc); + } + + /// \brief Set the destroyed type. + void setDestroyedType(TypeSourceInfo *Info) { + DestroyedType = PseudoDestructorTypeStorage(Info); + } + virtual SourceRange getSourceRange() const; static bool classof(const Stmt *T) { @@ -1321,6 +1361,9 @@ public: : Expr(UnaryTypeTraitExprClass, ty, false, queried->isDependentType()), UTT(utt), Loc(loc), RParen(rparen), QueriedType(queried) { } + explicit UnaryTypeTraitExpr(EmptyShell Empty) + : Expr(UnaryTypeTraitExprClass, Empty), UTT((UnaryTypeTrait)0) { } + virtual SourceRange getSourceRange() const { return SourceRange(Loc, RParen);} UnaryTypeTrait getTrait() const { return UTT; } @@ -1337,6 +1380,8 @@ public: // Iterators virtual child_iterator child_begin(); virtual child_iterator child_end(); + + friend class PCHStmtReader; }; /// \brief A reference to an overloaded function set, either an @@ -1361,16 +1406,20 @@ class OverloadExpr : public Expr { /// The location of the name. SourceLocation NameLoc; +protected: /// True if the name was a template-id. bool HasExplicitTemplateArgs; -protected: OverloadExpr(StmtClass K, ASTContext &C, QualType T, bool Dependent, NestedNameSpecifier *Qualifier, SourceRange QRange, DeclarationName Name, SourceLocation NameLoc, bool HasTemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); + OverloadExpr(StmtClass K, EmptyShell Empty) + : Expr(K, Empty), Results(0), NumResults(0), + Qualifier(0), HasExplicitTemplateArgs(false) { } + public: /// Computes whether an unresolved lookup on the given declarations /// and optional template arguments is type- and value-dependent. @@ -1401,6 +1450,9 @@ public: decls_iterator decls_end() const { return UnresolvedSetIterator(Results + NumResults); } + + void initializeResults(ASTContext &C, + UnresolvedSetIterator Begin,UnresolvedSetIterator End); /// Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } @@ -1415,9 +1467,11 @@ public: /// Fetches the nested-name qualifier, if one was given. NestedNameSpecifier *getQualifier() const { return Qualifier; } + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } /// Fetches the range of the nested-name qualifier. SourceRange getQualifierRange() const { return QualifierRange; } + void setQualifierRange(SourceRange R) { QualifierRange = R; } /// \brief Determines whether this expression had an explicit /// template argument list, e.g. f<int>. @@ -1480,6 +1534,11 @@ class UnresolvedLookupExpr : public OverloadExpr { RequiresADL(RequiresADL), Overloaded(Overloaded), NamingClass(NamingClass) {} + UnresolvedLookupExpr(EmptyShell Empty) + : OverloadExpr(UnresolvedLookupExprClass, Empty), + RequiresADL(false), Overloaded(false), NamingClass(0) + {} + public: static UnresolvedLookupExpr *Create(ASTContext &C, bool Dependent, @@ -1511,17 +1570,23 @@ public: UnresolvedSetIterator Begin, UnresolvedSetIterator End); + static UnresolvedLookupExpr *CreateEmpty(ASTContext &C, + unsigned NumTemplateArgs); + /// True if this declaration should be extended by /// argument-dependent lookup. bool requiresADL() const { return RequiresADL; } + void setRequiresADL(bool V) { RequiresADL = V; } /// 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 @@ -1628,18 +1693,25 @@ public: SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs = 0); + static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C, + unsigned NumTemplateArgs); + /// \brief Retrieve the name that this expression refers to. DeclarationName getDeclName() const { return Name; } + void setDeclName(DeclarationName N) { Name = N; } /// \brief Retrieve the location of the name within the expression. SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } /// \brief Retrieve the source range of the nested-name-specifier. SourceRange getQualifierRange() const { return QualifierRange; } + void setQualifierRange(SourceRange R) { QualifierRange = R; } /// \brief Retrieve the nested-name-specifier that qualifies this /// declaration. NestedNameSpecifier *getQualifier() const { return Qualifier; } + void setQualifier(NestedNameSpecifier *NNS) { Qualifier = NNS; } /// Determines whether this lookup had explicit template arguments. bool hasExplicitTemplateArgs() const { return HasExplicitTemplateArgs; } @@ -1648,6 +1720,11 @@ public: // nodes, users are *forbidden* from calling these methods on objects // without explicit template arguments. + ExplicitTemplateArgumentList &getExplicitTemplateArgs() { + assert(hasExplicitTemplateArgs()); + return *reinterpret_cast<ExplicitTemplateArgumentList*>(this + 1); + } + /// Gets a reference to the explicit template argument list. const ExplicitTemplateArgumentList &getExplicitTemplateArgs() const { assert(hasExplicitTemplateArgs()); @@ -1792,6 +1869,9 @@ class CXXUnresolvedConstructExpr : public Expr { unsigned NumArgs, SourceLocation RParenLoc); + CXXUnresolvedConstructExpr(EmptyShell Empty, unsigned NumArgs) + : Expr(CXXUnresolvedConstructExprClass, Empty), NumArgs(NumArgs) { } + public: static CXXUnresolvedConstructExpr *Create(ASTContext &C, SourceLocation TyBegin, @@ -1801,6 +1881,9 @@ public: unsigned NumArgs, SourceLocation RParenLoc); + static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C, + unsigned NumArgs); + /// \brief Retrieve the source location where the type begins. SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } @@ -1845,6 +1928,11 @@ public: return *(arg_begin() + I); } + void setArg(unsigned I, Expr *E) { + assert(I < NumArgs && "Argument index out-of-range"); + *(arg_begin() + I) = E; + } + virtual SourceRange getSourceRange() const { return SourceRange(TyBeginLoc, RParenLoc); } @@ -1908,20 +1996,6 @@ class CXXDependentScopeMemberExpr : public Expr { /// \brief The location of the member name. SourceLocation MemberLoc; - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { - assert(HasExplicitTemplateArgs); - return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); - } - - /// \brief Retrieve the explicit template argument list that followed the - /// member template name, if any. - const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { - return const_cast<CXXDependentScopeMemberExpr *>(this) - ->getExplicitTemplateArgumentList(); - } - CXXDependentScopeMemberExpr(ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, @@ -1960,6 +2034,9 @@ public: SourceLocation MemberLoc, const TemplateArgumentListInfo *TemplateArgs); + static CXXDependentScopeMemberExpr * + CreateEmpty(ASTContext &C, unsigned NumTemplateArgs); + /// \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. @@ -1974,6 +2051,7 @@ public: 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. @@ -1987,10 +2065,12 @@ public: /// \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; } /// \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 @@ -2006,6 +2086,9 @@ public: NamedDecl *getFirstQualifierFoundInScope() const { return FirstQualifierFoundInScope; } + void setFirstQualifierFoundInScope(NamedDecl *D) { + FirstQualifierFoundInScope = D; + } /// \brief Retrieve the name of the member that this expression /// refers to. @@ -2023,6 +2106,20 @@ public: return HasExplicitTemplateArgs; } + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { + assert(HasExplicitTemplateArgs); + return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); + } + + /// \brief Retrieve the explicit template argument list that followed the + /// member template name, if any. + const ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() const { + return const_cast<CXXDependentScopeMemberExpr *>(this) + ->getExplicitTemplateArgumentList(); + } + /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { @@ -2030,6 +2127,12 @@ public: getExplicitTemplateArgumentList()->copyInto(List); } + /// \brief Initializes the template arguments using the given structure. + void initializeTemplateArgumentsFrom(const TemplateArgumentListInfo &List) { + assert(HasExplicitTemplateArgs); + getExplicitTemplateArgumentList()->initializeFrom(List); + } + /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { @@ -2127,6 +2230,10 @@ class UnresolvedMemberExpr : public OverloadExpr { SourceLocation MemberLoc, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); + + UnresolvedMemberExpr(EmptyShell Empty) + : OverloadExpr(UnresolvedMemberExprClass, Empty), IsArrow(false), + HasUnresolvedUsing(false), Base(0) { } public: static UnresolvedMemberExpr * @@ -2140,6 +2247,9 @@ public: const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End); + static UnresolvedMemberExpr * + CreateEmpty(ASTContext &C, unsigned NumTemplateArgs); + /// \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. @@ -2158,6 +2268,12 @@ public: 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. diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 79e4451..def9ced 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -58,67 +58,85 @@ public: virtual ~ExternalASTSource(); - /// \brief Resolve a type ID into a type, potentially building a new - /// type. - virtual QualType GetType(uint32_t ID) = 0; - /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. - virtual Decl *GetDecl(uint32_t ID) = 0; + /// + /// 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; /// \brief Resolve a selector ID into a selector. - virtual Selector GetSelector(uint32_t ID) = 0; + /// + /// This operation only needs to be implemented if the AST source + /// returns non-zero for GetNumKnownSelectors(). + virtual Selector GetExternalSelector(uint32_t ID) = 0; /// \brief Returns the number of selectors known to the external AST /// source. - virtual uint32_t GetNumKnownSelectors() = 0; + virtual uint32_t GetNumExternalSelectors() = 0; - /// \brief Resolve the offset of a statement in the decl stream into a - /// statement. + /// \brief Resolve the offset of a statement in the decl stream into + /// a statement. /// - /// This operation will read a new statement from the external - /// source each time it is called, and is meant to be used via a - /// LazyOffsetPtr. - virtual Stmt *GetDeclStmt(uint64_t Offset) = 0; + /// 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; - /// \brief Read all of the declarations lexically stored in a - /// declaration context. + /// \brief Finds all declarations with the given name in the + /// given context. /// - /// \param DC The declaration context whose declarations will be - /// read. + /// Generally the final step of this method is either to call + /// SetExternalVisibleDeclsForName or to recursively call lookup on + /// the DeclContext after calling SetExternalVisibleDecls. + virtual DeclContext::lookup_result + FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name) = 0; + + /// \brief Finds all declarations lexically contained within the given + /// DeclContext. /// - /// \param Decls Vector that will contain the declarations loaded - /// from the external source. The caller is responsible for merging - /// these declarations with any declarations already stored in the - /// declaration context. - /// - /// \returns true if there was an error while reading the - /// declarations for this declaration context. - virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, - llvm::SmallVectorImpl<uint32_t> &Decls) = 0; - - /// \brief Read all of the declarations visible from a declaration - /// context. - /// - /// \param DC The declaration context whose visible declarations - /// will be read. - /// - /// \param Decls A vector of visible declaration structures, - /// providing the mapping from each name visible in the declaration - /// context to the declaration IDs of declarations with that name. - /// - /// \returns true if there was an error while reading the - /// declarations for this declaration context. - virtual bool ReadDeclsVisibleInContext(DeclContext *DC, - llvm::SmallVectorImpl<VisibleDeclaration> & Decls) = 0; + /// \return true if an error occurred + virtual bool FindExternalLexicalDecls(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Result) = 0; /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. + /// + /// The default implementation of this method is a no-op. virtual void StartTranslationUnit(ASTConsumer *Consumer) { } /// \brief Print any statistics that have been gathered regarding /// the external AST source. + /// + /// The default implementation of this method is a no-op. virtual void PrintStats(); + +protected: + /// \brief Initialize the context's lookup map with the given decls. + /// It is assumed that none of the declarations are redeclarations of + /// each other. + static void SetExternalVisibleDecls(const DeclContext *DC, + const llvm::SmallVectorImpl<VisibleDeclaration> &Decls); + + /// \brief Initialize the context's lookup map with the given decls. + /// It is assumed that none of the declarations are redeclarations of + /// each other. + static void SetExternalVisibleDecls(const DeclContext *DC, + const llvm::SmallVectorImpl<NamedDecl*> &Decls); + + static DeclContext::lookup_result + SetExternalVisibleDeclsForName(const DeclContext *DC, + const VisibleDeclaration &VD); + + static DeclContext::lookup_result + SetExternalVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name, + llvm::SmallVectorImpl<NamedDecl*> &Decls); + + static DeclContext::lookup_result + SetNoExternalVisibleDeclsForName(const DeclContext *DC, + DeclarationName Name); }; /// \brief A lazy pointer to an AST node (of base type T) that resides @@ -185,7 +203,8 @@ public: }; /// \brief A lazy pointer to a statement. -typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetDeclStmt> LazyDeclStmtPtr; +typedef LazyOffsetPtr<Stmt, &ExternalASTSource::GetExternalDeclStmt> + LazyDeclStmtPtr; } // end namespace clang diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile index a25977c..00a1e1b 100644 --- a/include/clang/AST/Makefile +++ b/include/clang/AST/Makefile @@ -1,13 +1,23 @@ -LEVEL = ../../../../.. -BUILT_SOURCES = StmtNodes.inc +CLANG_LEVEL := ../../.. +TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic +BUILT_SOURCES = Attrs.inc StmtNodes.inc DeclNodes.inc TABLEGEN_INC_FILES_COMMON = 1 -include $(LEVEL)/Makefile.common +include $(CLANG_LEVEL)/Makefile -INPUT_TDS = $(PROJ_SRC_DIR)/StmtNodes.td +$(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang attribute classes with tblgen" + $(Verb) $(TableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \ + -I $(PROJ_SRC_DIR)/../../ $< -$(ObjDir)/StmtNodes.inc.tmp : StmtNodes.td $(TBLGEN) $(ObjDir)/.dir +$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(TBLGEN) \ + $(ObjDir)/.dir $(Echo) "Building Clang statement node tables with tblgen" $(Verb) $(TableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $< +$(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(TBLGEN) \ + $(ObjDir)/.dir + $(Echo) "Building Clang declaration node tables with tblgen" + $(Verb) $(TableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $< diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 07865e0..0853ddd 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -29,739 +29,1634 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" + +// The following three macros are used for meta programming. The code +// using them is responsible for defining macro OPERATOR(). + +// All unary operators. +#define UNARYOP_LIST() \ + OPERATOR(PostInc) OPERATOR(PostDec) \ + OPERATOR(PreInc) OPERATOR(PreDec) \ + OPERATOR(AddrOf) OPERATOR(Deref) \ + OPERATOR(Plus) OPERATOR(Minus) \ + OPERATOR(Not) OPERATOR(LNot) \ + OPERATOR(Real) OPERATOR(Imag) \ + OPERATOR(Extension) OPERATOR(OffsetOf) + +// All binary operators (excluding compound assign operators). +#define BINOP_LIST() \ + OPERATOR(PtrMemD) OPERATOR(PtrMemI) \ + OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) \ + OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) \ + OPERATOR(Shr) \ + \ + OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) \ + OPERATOR(GE) OPERATOR(EQ) OPERATOR(NE) \ + OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \ + OPERATOR(LAnd) OPERATOR(LOr) \ + \ + OPERATOR(Assign) \ + OPERATOR(Comma) + +// All compound assign operators. +#define CAO_LIST() \ + OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \ + OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor) namespace clang { -#define DISPATCH(NAME, CLASS, Var) \ -return getDerived().Visit ## NAME(static_cast<CLASS*>(Var)) - -// We use preprocessor meta-programming to generate the Visit*() -// methods for all subclasses of Stmt, Decl, and Type. Some of the -// generated definitions, however, need to be customized. The -// meta-programming technique we use doesn't let us select which -// methods to generate. Therefore we have to generate ALL of them in -// a helper class RecursiveASTVisitorImpl, and override the ones we -// don't like in a child class RecursiveASTVisitor (C++ doesn't allow -// overriding a method in the same class). -// -// Do not use this class directly - use RecursiveASTVisitor instead. +// A helper macro to implement short-circuiting when recursing. It +// invokes CALL_EXPR, which must be a method call, on the derived +// object (s.t. a user of RecursiveASTVisitor can override the method +// in CALL_EXPR). +#define TRY_TO(CALL_EXPR) \ + do { if (!getDerived().CALL_EXPR) return false; } while (0) + +/// \brief A class that does preorder depth-first traversal on the +/// entire Clang AST and visits each node. +/// +/// This class performs three distinct tasks: +/// 1. traverse the AST (i.e. go to each node); +/// 2. at a given node, walk up the class hierarchy, starting from +/// the node's dynamic type, until the top-most class (e.g. Stmt, +/// Decl, or Type) is reached. +/// 3. given a (node, class) combination, where 'class' is some base +/// class of the dynamic type of 'node', call a user-overridable +/// function to actually visit the node. +/// +/// These tasks are done by three groups of methods, respectively: +/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point +/// for traversing an AST rooted at x. This method simply +/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo +/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and +/// then recursively visits the child nodes of x. +/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work +/// similarly. +/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit +/// any child node of x. Instead, it first calls WalkUpFromBar(x) +/// where Bar is the direct parent class of Foo (unless Foo has +/// no parent), and then calls VisitFoo(x) (see the next list item). +/// 3. VisitFoo(Foo *x) does task #3. +/// +/// These three method groups are tiered (Traverse* > WalkUpFrom* > +/// Visit*). A method (e.g. Traverse*) may call methods from the same +/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*). +/// It may not call methods from a higher tier. +/// +/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar +/// is Foo's super class) before calling VisitFoo(), the result is +/// that the Visit*() methods for a given node are called in the +/// top-down order (e.g. for a node of type NamedDecl, the order will +/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). +/// +/// This scheme guarantees that all Visit*() calls for the same AST +/// node are grouped together. In other words, Visit*() methods for +/// different nodes are never interleaved. +/// +/// Clients of this visitor should subclass the visitor (providing +/// themselves as the template argument, using the curiously recurring +/// template pattern) and override any of the Traverse*, WalkUpFrom*, +/// and Visit* methods for declarations, types, statements, +/// expressions, or other AST nodes where the visitor should customize +/// behavior. Most users only need to override Visit*. Advanced +/// users may override Traverse* and WalkUpFrom* to implement custom +/// traversal strategies. Returning false from one of these overridden +/// functions will abort the entire traversal. template<typename Derived> -class RecursiveASTVisitorImpl { +class RecursiveASTVisitor { public: /// \brief Return a reference to the derived class. Derived &getDerived() { return *static_cast<Derived*>(this); } /// \brief Recursively visit a statement or expression, by - /// dispatching to Visit*() based on the argument's dynamic type. - /// This is NOT meant to be overridden by a subclass. + /// dispatching to Traverse*() based on the argument's dynamic type. /// - /// \returns true if the visitation was terminated early, false + /// \returns false if the visitation was terminated early, true /// otherwise (including when the argument is NULL). - bool Visit(Stmt *S); + bool TraverseStmt(Stmt *S); /// \brief Recursively visit a type, by dispatching to - /// Visit*Type() based on the argument's getTypeClass() property. - /// This is NOT meant to be overridden by a subclass. + /// Traverse*Type() based on the argument's getTypeClass() property. /// - /// \returns true if the visitation was terminated early, false + /// \returns false if the visitation was terminated early, true /// otherwise (including when the argument is a Null type). - bool Visit(QualType T); + bool TraverseType(QualType T); + + /// \brief Recursively visit a type with location, by dispatching to + /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. + /// + /// \returns false if the visitation was terminated early, true + /// otherwise (including when the argument is a Null type location). + bool TraverseTypeLoc(TypeLoc TL); /// \brief Recursively visit a declaration, by dispatching to - /// Visit*Decl() based on the argument's dynamic type. This is - /// NOT meant to be overridden by a subclass. + /// Traverse*Decl() based on the argument's dynamic type. /// - /// \returns true if the visitation was terminated early, false + /// \returns false if the visitation was terminated early, true /// otherwise (including when the argument is NULL). - bool Visit(Decl *D); + bool TraverseDecl(Decl *D); /// \brief Recursively visit a C++ nested-name-specifier. /// - /// \returns true if the visitation was terminated early, false otherwise. - bool VisitNestedNameSpecifier(NestedNameSpecifier *NNS); + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); - /// \brief Recursively visit a template name. + /// \brief Recursively visit a template name and dispatch to the + /// appropriate method. /// - /// \returns true if the visitation was terminated early, false otherwise. - bool VisitTemplateName(TemplateName Template); + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseTemplateName(TemplateName Template); - /// \brief Recursively visit a template argument. + /// \brief Recursively visit a template argument and dispatch to the + /// appropriate method for the argument type. /// - /// \returns true if the visitation was terminated early, false otherwise. - bool VisitTemplateArgument(const TemplateArgument &Arg); + /// \returns false if the visitation was terminated early, true otherwise. + // FIXME: migrate callers to TemplateArgumentLoc instead. + bool TraverseTemplateArgument(const TemplateArgument &Arg); - /// \brief Recursively visit a set of template arguments. + /// \brief Recursively visit a template argument location and dispatch to the + /// appropriate method for the argument type. /// - /// \returns true if the visitation was terminated early, false otherwise. - bool VisitTemplateArguments(const TemplateArgument *Args, unsigned NumArgs); - - // If the implementation chooses not to implement a certain visit method, fall - // back on VisitExpr or whatever else is the superclass. -#define STMT(CLASS, PARENT) \ -bool Visit ## CLASS(CLASS *S) { DISPATCH(PARENT, PARENT, S); } -#include "clang/AST/StmtNodes.inc" + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); - // If the implementation doesn't implement binary operator methods, fall back - // on VisitBinaryOperator. -#define BINOP_FALLBACK(NAME) \ -bool VisitBin ## NAME(BinaryOperator *S) { \ -DISPATCH(BinaryOperator, BinaryOperator, S); \ -} - BINOP_FALLBACK(PtrMemD) BINOP_FALLBACK(PtrMemI) - BINOP_FALLBACK(Mul) BINOP_FALLBACK(Div) BINOP_FALLBACK(Rem) - BINOP_FALLBACK(Add) BINOP_FALLBACK(Sub) BINOP_FALLBACK(Shl) - BINOP_FALLBACK(Shr) - - BINOP_FALLBACK(LT) BINOP_FALLBACK(GT) BINOP_FALLBACK(LE) - BINOP_FALLBACK(GE) BINOP_FALLBACK(EQ) BINOP_FALLBACK(NE) - BINOP_FALLBACK(And) BINOP_FALLBACK(Xor) BINOP_FALLBACK(Or) - BINOP_FALLBACK(LAnd) BINOP_FALLBACK(LOr) - - BINOP_FALLBACK(Assign) - BINOP_FALLBACK(Comma) -#undef BINOP_FALLBACK - - // If the implementation doesn't implement compound assignment operator - // methods, fall back on VisitCompoundAssignOperator. -#define CAO_FALLBACK(NAME) \ -bool VisitBin ## NAME(CompoundAssignOperator *S) { \ -DISPATCH(CompoundAssignOperator, CompoundAssignOperator, S); \ -} - CAO_FALLBACK(MulAssign) CAO_FALLBACK(DivAssign) CAO_FALLBACK(RemAssign) - CAO_FALLBACK(AddAssign) CAO_FALLBACK(SubAssign) CAO_FALLBACK(ShlAssign) - CAO_FALLBACK(ShrAssign) CAO_FALLBACK(AndAssign) CAO_FALLBACK(OrAssign) - CAO_FALLBACK(XorAssign) -#undef CAO_FALLBACK - - // If the implementation doesn't implement unary operator methods, fall back - // on VisitUnaryOperator. -#define UNARYOP_FALLBACK(NAME) \ -bool VisitUnary ## NAME(UnaryOperator *S) { \ -DISPATCH(UnaryOperator, UnaryOperator, S); \ -} - UNARYOP_FALLBACK(PostInc) UNARYOP_FALLBACK(PostDec) - UNARYOP_FALLBACK(PreInc) UNARYOP_FALLBACK(PreDec) - UNARYOP_FALLBACK(AddrOf) UNARYOP_FALLBACK(Deref) - - UNARYOP_FALLBACK(Plus) UNARYOP_FALLBACK(Minus) - UNARYOP_FALLBACK(Not) UNARYOP_FALLBACK(LNot) - UNARYOP_FALLBACK(Real) UNARYOP_FALLBACK(Imag) - UNARYOP_FALLBACK(Extension) UNARYOP_FALLBACK(OffsetOf) -#undef UNARYOP_FALLBACK - - /// \brief Basis for statement and expression visitation, which - /// visits all of the substatements and subexpressions. + /// \brief Recursively visit a set of template arguments. + /// This can be overridden by a subclass, but it's not expected that + /// will be needed -- this visitor always dispatches to another. /// - /// The relation between Visit(Stmt *S) and this method is that - /// the former dispatches to Visit*() based on S's dynamic type, - /// which forwards the call up the inheritance chain until - /// reaching VisitStmt(), which then calls Visit() on each - /// substatement/subexpression. - bool VisitStmt(Stmt *S); - - /// \brief Basis for type visitation, which by default does nothing. + /// \returns false if the visitation was terminated early, true otherwise. + // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead. + bool TraverseTemplateArguments(const TemplateArgument *Args, + unsigned NumArgs); + + /// \brief Recursively visit a constructor initializer. This + /// automatically dispatches to another visitor for the initializer + /// expression, but not for the name of the initializer, so may + /// be overridden for clients that need access to the name. /// - /// The relation between Visit(QualType T) and this method is - /// that the former dispatches to Visit*Type(), which forwards the - /// call up the inheritance chain until reaching VisitType(). - bool VisitType(Type *T); + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseConstructorInitializer(CXXBaseOrMemberInitializer *Init); + + // ---- Methods on Stmts ---- -#define TYPE(Class, Base) \ - bool Visit##Class##Type(Class##Type *T); + // Declare Traverse*() for all concrete Stmt classes. +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ + bool Traverse##CLASS(CLASS *S); +#include "clang/AST/StmtNodes.inc" + // The above header #undefs ABSTRACT_STMT and STMT upon exit. + + // Define WalkUpFrom*() and empty Visit*() for all Stmt classes. + bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); } + bool VisitStmt(Stmt *S) { return true; } +#define STMT(CLASS, PARENT) \ + bool WalkUpFrom##CLASS(CLASS *S) { \ + TRY_TO(WalkUpFrom##PARENT(S)); \ + TRY_TO(Visit##CLASS(S)); \ + return true; \ + } \ + bool Visit##CLASS(CLASS *S) { return true; } +#include "clang/AST/StmtNodes.inc" + + // Define Traverse*(), WalkUpFrom*(), and Visit*() for unary + // operator methods. Unary operators are not classes in themselves + // (they're all opcodes in UnaryOperator) but do have visitors. +#define OPERATOR(NAME) \ + bool TraverseUnary##NAME(UnaryOperator *S) { \ + TRY_TO(WalkUpFromUnary##NAME(S)); \ + TRY_TO(TraverseStmt(S->getSubExpr())); \ + return true; \ + } \ + bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ + TRY_TO(WalkUpFromUnaryOperator(S)); \ + TRY_TO(VisitUnary##NAME(S)); \ + return true; \ + } \ + bool VisitUnary##NAME(UnaryOperator *S) { return true; } + + UNARYOP_LIST() +#undef OPERATOR + + // Define Traverse*(), WalkUpFrom*(), and Visit*() for binary + // operator methods. Binary operators are not classes in themselves + // (they're all opcodes in BinaryOperator) but do have visitors. +#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ + bool TraverseBin##NAME(BINOP_TYPE *S) { \ + TRY_TO(WalkUpFromBin##NAME(S)); \ + TRY_TO(TraverseStmt(S->getLHS())); \ + TRY_TO(TraverseStmt(S->getRHS())); \ + return true; \ + } \ + bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ + TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \ + TRY_TO(VisitBin##NAME(S)); \ + return true; \ + } \ + bool VisitBin##NAME(BINOP_TYPE *S) { return true; } + +#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator) + BINOP_LIST() +#undef OPERATOR + + // Define Traverse*(), WalkUpFrom*(), and Visit*() for compound + // assignment methods. Compound assignment operators are not + // classes in themselves (they're all opcodes in + // CompoundAssignOperator) but do have visitors. +#define OPERATOR(NAME) \ + GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator) + + CAO_LIST() +#undef OPERATOR +#undef GENERAL_BINOP_FALLBACK + + // ---- Methods on Types ---- + // FIXME: revamp to take TypeLoc's rather than Types. + + // Declare Traverse*() for all concrete Type classes. +#define ABSTRACT_TYPE(CLASS, BASE) +#define TYPE(CLASS, BASE) \ + bool Traverse##CLASS##Type(CLASS##Type *T); +#include "clang/AST/TypeNodes.def" + // The above header #undefs ABSTRACT_TYPE and TYPE upon exit. + + // Define WalkUpFrom*() and empty Visit*() for all Type classes. + bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); } + bool VisitType(Type *T) { return true; } +#define TYPE(CLASS, BASE) \ + bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \ + TRY_TO(WalkUpFrom##BASE(T)); \ + TRY_TO(Visit##CLASS##Type(T)); \ + return true; \ + } \ + bool Visit##CLASS##Type(CLASS##Type *T) { return true; } #include "clang/AST/TypeNodes.def" - /// \brief Basis for declaration and definition visitation, which - /// visits all of the subnodes. - /// - /// The relation between Visit(Decl *) and this method is that the - /// former dispatches to Visit*Decl(), which forwards the call up - /// the inheritance chain until reaching VisitDecl(). - bool VisitDecl(Decl *D); - -#define DECL(Class, Base) \ - bool Visit##Class##Decl(Class##Decl *D) { \ - return getDerived().Visit##Base(D); \ + // ---- Methods on TypeLocs ---- + // FIXME: this currently just calls the matching Type methods + + // Declare Traverse*() for all concrete Type classes. +#define ABSTRACT_TYPELOC(CLASS, BASE) +#define TYPELOC(CLASS, BASE) \ + bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); +#include "clang/AST/TypeLocNodes.def" + // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit. + + // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes. + bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); } + bool VisitTypeLoc(TypeLoc TL) { return true; } + + // QualifiedTypeLoc and UnqualTypeLoc are not declared in + // TypeNodes.def and thus need to be handled specially. + bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) { + return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); } -#define ABSTRACT_DECL(Class, Base) DECL(Class, Base) -#include "clang/AST/DeclNodes.def" + bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; } + bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) { + return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc()); + } + bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; } + + // Note that BASE includes trailing 'Type' which CLASS doesn't. +#define TYPE(CLASS, BASE) \ + bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \ + TRY_TO(WalkUpFrom##BASE##Loc(TL)); \ + TRY_TO(Visit##CLASS##TypeLoc(TL)); \ + return true; \ + } \ + bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; } +#include "clang/AST/TypeNodes.def" + + // ---- Methods on Decls ---- + + // Declare Traverse*() for all concrete Decl classes. +#define ABSTRACT_DECL(DECL) +#define DECL(CLASS, BASE) \ + bool Traverse##CLASS##Decl(CLASS##Decl *D); +#include "clang/AST/DeclNodes.inc" + // The above header #undefs ABSTRACT_DECL and DECL upon exit. + + // Define WalkUpFrom*() and empty Visit*() for all Decl classes. + bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); } + bool VisitDecl(Decl *D) { return true; } +#define DECL(CLASS, BASE) \ + bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \ + TRY_TO(WalkUpFrom##BASE(D)); \ + TRY_TO(Visit##CLASS##Decl(D)); \ + return true; \ + } \ + bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; } +#include "clang/AST/DeclNodes.inc" + +private: + // These are helper methods used by more than one Traverse* method. + bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); + bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, + unsigned Count); + bool TraverseRecordHelper(RecordDecl *D); + bool TraverseCXXRecordHelper(CXXRecordDecl *D); + bool TraverseDeclaratorHelper(DeclaratorDecl *D); + bool TraverseDeclContextHelper(DeclContext *DC); + bool TraverseFunctionHelper(FunctionDecl *D); + bool TraverseVarHelper(VarDecl *D); }; +#define DISPATCH(NAME, CLASS, VAR) \ + return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR)) + template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::Visit(Stmt *S) { +bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) { if (!S) - return false; + return true; // If we have a binary expr, dispatch to the subcode of the binop. A smart // optimizer (e.g. LLVM) will fold this comparison into the switch stmt // below. if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) { switch (BinOp->getOpcode()) { - case BinaryOperator::PtrMemD: DISPATCH(BinPtrMemD, BinaryOperator, S); - case BinaryOperator::PtrMemI: DISPATCH(BinPtrMemI, BinaryOperator, S); - case BinaryOperator::Mul: DISPATCH(BinMul, BinaryOperator, S); - case BinaryOperator::Div: DISPATCH(BinDiv, BinaryOperator, S); - case BinaryOperator::Rem: DISPATCH(BinRem, BinaryOperator, S); - case BinaryOperator::Add: DISPATCH(BinAdd, BinaryOperator, S); - case BinaryOperator::Sub: DISPATCH(BinSub, BinaryOperator, S); - case BinaryOperator::Shl: DISPATCH(BinShl, BinaryOperator, S); - case BinaryOperator::Shr: DISPATCH(BinShr, BinaryOperator, S); - - case BinaryOperator::LT: DISPATCH(BinLT, BinaryOperator, S); - case BinaryOperator::GT: DISPATCH(BinGT, BinaryOperator, S); - case BinaryOperator::LE: DISPATCH(BinLE, BinaryOperator, S); - case BinaryOperator::GE: DISPATCH(BinGE, BinaryOperator, S); - case BinaryOperator::EQ: DISPATCH(BinEQ, BinaryOperator, S); - case BinaryOperator::NE: DISPATCH(BinNE, BinaryOperator, S); - - case BinaryOperator::And: DISPATCH(BinAnd, BinaryOperator, S); - case BinaryOperator::Xor: DISPATCH(BinXor, BinaryOperator, S); - case BinaryOperator::Or : DISPATCH(BinOr, BinaryOperator, S); - case BinaryOperator::LAnd: DISPATCH(BinLAnd, BinaryOperator, S); - case BinaryOperator::LOr : DISPATCH(BinLOr, BinaryOperator, S); - case BinaryOperator::Assign: DISPATCH(BinAssign, BinaryOperator, S); - case BinaryOperator::MulAssign: - DISPATCH(BinMulAssign, CompoundAssignOperator, S); - case BinaryOperator::DivAssign: - DISPATCH(BinDivAssign, CompoundAssignOperator, S); - case BinaryOperator::RemAssign: - DISPATCH(BinRemAssign, CompoundAssignOperator, S); - case BinaryOperator::AddAssign: - DISPATCH(BinAddAssign, CompoundAssignOperator, S); - case BinaryOperator::SubAssign: - DISPATCH(BinSubAssign, CompoundAssignOperator, S); - case BinaryOperator::ShlAssign: - DISPATCH(BinShlAssign, CompoundAssignOperator, S); - case BinaryOperator::ShrAssign: - DISPATCH(BinShrAssign, CompoundAssignOperator, S); - case BinaryOperator::AndAssign: - DISPATCH(BinAndAssign, CompoundAssignOperator, S); - case BinaryOperator::OrAssign: - DISPATCH(BinOrAssign, CompoundAssignOperator, S); - case BinaryOperator::XorAssign: - DISPATCH(BinXorAssign, CompoundAssignOperator, S); - case BinaryOperator::Comma: DISPATCH(BinComma, BinaryOperator, S); +#define OPERATOR(NAME) \ + case BinaryOperator::NAME: DISPATCH(Bin##PtrMemD, BinaryOperator, S); + + BINOP_LIST() +#undef OPERATOR +#undef BINOP_LIST + +#define OPERATOR(NAME) \ + case BinaryOperator::NAME##Assign: \ + DISPATCH(Bin##NAME##Assign, CompoundAssignOperator, S); + + CAO_LIST() +#undef OPERATOR +#undef CAO_LIST } } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) { switch (UnOp->getOpcode()) { - case UnaryOperator::PostInc: DISPATCH(UnaryPostInc, UnaryOperator, S); - case UnaryOperator::PostDec: DISPATCH(UnaryPostDec, UnaryOperator, S); - case UnaryOperator::PreInc: DISPATCH(UnaryPreInc, UnaryOperator, S); - case UnaryOperator::PreDec: DISPATCH(UnaryPreDec, UnaryOperator, S); - case UnaryOperator::AddrOf: DISPATCH(UnaryAddrOf, UnaryOperator, S); - case UnaryOperator::Deref: DISPATCH(UnaryDeref, UnaryOperator, S); - case UnaryOperator::Plus: DISPATCH(UnaryPlus, UnaryOperator, S); - case UnaryOperator::Minus: DISPATCH(UnaryMinus, UnaryOperator, S); - case UnaryOperator::Not: DISPATCH(UnaryNot, UnaryOperator, S); - case UnaryOperator::LNot: DISPATCH(UnaryLNot, UnaryOperator, S); - case UnaryOperator::Real: DISPATCH(UnaryReal, UnaryOperator, S); - case UnaryOperator::Imag: DISPATCH(UnaryImag, UnaryOperator, S); - case UnaryOperator::Extension: DISPATCH(UnaryExtension, UnaryOperator, S); - case UnaryOperator::OffsetOf: DISPATCH(UnaryOffsetOf, UnaryOperator, S); +#define OPERATOR(NAME) \ + case UnaryOperator::NAME: DISPATCH(Unary##NAME, UnaryOperator, S); + + UNARYOP_LIST() +#undef OPERATOR +#undef UNARYOP_LIST } } - // Top switch stmt: dispatch to VisitFooStmt for each FooStmt. + // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt. switch (S->getStmtClass()) { case Stmt::NoStmtClass: break; #define ABSTRACT_STMT(STMT) -#define STMT(CLASS, PARENT) \ -case Stmt::CLASS ## Class: DISPATCH(CLASS, CLASS, S); +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS##Class: DISPATCH(CLASS, CLASS, S); #include "clang/AST/StmtNodes.inc" } - return false; + return true; } template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::Visit(QualType T) { +bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) { if (T.isNull()) - return false; + return true; switch (T->getTypeClass()) { -#define ABSTRACT_TYPE(Class, Base) -#define TYPE(Class, Base) \ - case Type::Class: DISPATCH(Class##Type, Class##Type, T.getTypePtr()); +#define ABSTRACT_TYPE(CLASS, BASE) +#define TYPE(CLASS, BASE) \ + case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, T.getTypePtr()); #include "clang/AST/TypeNodes.def" } - return false; + return true; } template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::Visit(Decl *D) { +bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) { + if (TL.isNull()) + return true; + + switch (TL.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, BASE) +#define TYPELOC(CLASS, BASE) \ + case TypeLoc::CLASS: \ + return getDerived().Traverse##CLASS##TypeLoc(*cast<CLASS##TypeLoc>(&TL)); +#include "clang/AST/TypeLocNodes.def" + } + + return true; +} + + +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) { if (!D) - return false; + return true; + + // As a syntax visitor, we want to ignore declarations for + // implicitly-defined declarations (ones not typed explicitly by the + // user). + if (D->isImplicit()) + return true; switch (D->getKind()) { -#define ABSTRACT_DECL(Class, Base) -#define DECL(Class, Base) \ - case Decl::Class: DISPATCH(Class##Decl, Class##Decl, D); -#include "clang/AST/DeclNodes.def" - } +#define ABSTRACT_DECL(DECL) +#define DECL(CLASS, BASE) \ + case Decl::CLASS: DISPATCH(CLASS##Decl, CLASS##Decl, D); +#include "clang/AST/DeclNodes.inc" + } - return false; + return true; } +#undef DISPATCH + template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitNestedNameSpecifier( +bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( NestedNameSpecifier *NNS) { - if (NNS->getPrefix() && - getDerived().VisitNestedNameSpecifier(NNS->getPrefix())) + if (!NNS) return true; + if (NNS->getPrefix()) + TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix())); + switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: case NestedNameSpecifier::Namespace: case NestedNameSpecifier::Global: - return false; + return true; case NestedNameSpecifier::TypeSpec: case NestedNameSpecifier::TypeSpecWithTemplate: - return Visit(QualType(NNS->getAsType(), 0)); + TRY_TO(TraverseType(QualType(NNS->getAsType(), 0))); } - return false; + return true; } template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTemplateName(TemplateName Template) { +bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) { if (DependentTemplateName *DTN = Template.getAsDependentTemplateName()) - return DTN->getQualifier() && - getDerived().VisitNestedNameSpecifier(DTN->getQualifier()); - - if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) - return getDerived().VisitNestedNameSpecifier(QTN->getQualifier()); + TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier())); + else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName()) + TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier())); - return false; + return true; } template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTemplateArgument( +bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument( const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Declaration: case TemplateArgument::Integral: - return false; + return true; case TemplateArgument::Type: - return Visit(Arg.getAsType()); + return getDerived().TraverseType(Arg.getAsType()); case TemplateArgument::Template: - return getDerived().VisitTemplateName(Arg.getAsTemplate()); + return getDerived().TraverseTemplateName(Arg.getAsTemplate()); case TemplateArgument::Expression: - return getDerived().Visit(Arg.getAsExpr()); + return getDerived().TraverseStmt(Arg.getAsExpr()); case TemplateArgument::Pack: - return getDerived().VisitTemplateArguments(Arg.pack_begin(), - Arg.pack_size()); + return getDerived().TraverseTemplateArguments(Arg.pack_begin(), + Arg.pack_size()); } - return false; + return true; } +// FIXME: no template name location? +// FIXME: no source locations for a template argument pack? template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTemplateArguments( - const TemplateArgument *Args, - unsigned NumArgs) { - for (unsigned I = 0; I != NumArgs; ++I) - if (getDerived().VisitTemplateArgument(Args[I])) - return true; +bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc( + const TemplateArgumentLoc &ArgLoc) { + const TemplateArgument &Arg = ArgLoc.getArgument(); - return false; -} + switch (Arg.getKind()) { + case TemplateArgument::Null: + case TemplateArgument::Declaration: + case TemplateArgument::Integral: + return true; -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitStmt(Stmt *Node) { - for (Stmt::child_iterator C = Node->child_begin(), CEnd = Node->child_end(); - C != CEnd; ++C) { - if (Visit(*C)) - return true; + case TemplateArgument::Type: { + TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo(); + return getDerived().TraverseTypeLoc(TSI->getTypeLoc()); } - return false; + case TemplateArgument::Template: + return getDerived().TraverseTemplateName(Arg.getAsTemplate()); + + case TemplateArgument::Expression: + return getDerived().TraverseStmt(ArgLoc.getSourceExpression()); + + case TemplateArgument::Pack: + return getDerived().TraverseTemplateArguments(Arg.pack_begin(), + Arg.pack_size()); + } + + return true; } template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitType(Type *T) { - return false; +bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments( + const TemplateArgument *Args, + unsigned NumArgs) { + for (unsigned I = 0; I != NumArgs; ++I) { + TRY_TO(TraverseTemplateArgument(Args[I])); + } + + return true; } template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitBuiltinType(BuiltinType *T) { - return getDerived().VisitType(T); +bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer( + CXXBaseOrMemberInitializer *Init) { + // FIXME: recurse on TypeLoc of the base initializer if isBaseInitializer()? + if (Init->isWritten()) + TRY_TO(TraverseStmt(Init->getInit())); + return true; } -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitComplexType(ComplexType *T) { - if (Visit(T->getElementType())) - return true; - return getDerived().VisitType(T); -} +// ----------------- Type traversal ----------------- -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitPointerType(PointerType *T) { - if (Visit(T->getPointeeType())) - return true; +// This macro makes available a variable T, the passed-in type. +#define DEF_TRAVERSE_TYPE(TYPE, CODE) \ + template<typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##TYPE (TYPE *T) { \ + TRY_TO(WalkUpFrom##TYPE (T)); \ + { CODE; } \ + return true; \ + } - return getDerived().VisitType(T); -} +DEF_TRAVERSE_TYPE(BuiltinType, { }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitBlockPointerType( - BlockPointerType *T) { - if (Visit(T->getPointeeType())) - return true; +DEF_TRAVERSE_TYPE(ComplexType, { + TRY_TO(TraverseType(T->getElementType())); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_TYPE(PointerType, { + TRY_TO(TraverseType(T->getPointeeType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitReferenceType(ReferenceType *T) { - if (Visit(T->getPointeeType())) - return true; +DEF_TRAVERSE_TYPE(BlockPointerType, { + TRY_TO(TraverseType(T->getPointeeType())); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_TYPE(LValueReferenceType, { + TRY_TO(TraverseType(T->getPointeeType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitLValueReferenceType( - LValueReferenceType *T) { - return getDerived().VisitReferenceType(T); -} +DEF_TRAVERSE_TYPE(RValueReferenceType, { + TRY_TO(TraverseType(T->getPointeeType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitRValueReferenceType( - RValueReferenceType *T) { - return getDerived().VisitReferenceType(T); -} +DEF_TRAVERSE_TYPE(MemberPointerType, { + TRY_TO(TraverseType(QualType(T->getClass(), 0))); + TRY_TO(TraverseType(T->getPointeeType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitMemberPointerType( - MemberPointerType *T) { - if (Visit(QualType(T->getClass(), 0)) || Visit(T->getPointeeType())) - return true; +DEF_TRAVERSE_TYPE(ConstantArrayType, { + TRY_TO(TraverseType(T->getElementType())); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_TYPE(IncompleteArrayType, { + TRY_TO(TraverseType(T->getElementType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitArrayType(ArrayType *T) { - if (Visit(T->getElementType())) - return true; +DEF_TRAVERSE_TYPE(VariableArrayType, { + TRY_TO(TraverseType(T->getElementType())); + TRY_TO(TraverseStmt(T->getSizeExpr())); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_TYPE(DependentSizedArrayType, { + TRY_TO(TraverseType(T->getElementType())); + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitConstantArrayType( - ConstantArrayType *T) { - return getDerived().VisitArrayType(T); -} +DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); + TRY_TO(TraverseType(T->getElementType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitIncompleteArrayType( - IncompleteArrayType *T) { - return getDerived().VisitArrayType(T); -} +DEF_TRAVERSE_TYPE(VectorType, { + TRY_TO(TraverseType(T->getElementType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitVariableArrayType( - VariableArrayType *T) { - if (Visit(T->getSizeExpr())) - return true; +DEF_TRAVERSE_TYPE(ExtVectorType, { + TRY_TO(TraverseType(T->getElementType())); + }) - return getDerived().VisitArrayType(T); -} +DEF_TRAVERSE_TYPE(FunctionNoProtoType, { + TRY_TO(TraverseType(T->getResultType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitDependentSizedArrayType( - DependentSizedArrayType *T) { - if (T->getSizeExpr() && Visit(T->getSizeExpr())) - return true; +DEF_TRAVERSE_TYPE(FunctionProtoType, { + TRY_TO(TraverseType(T->getResultType())); - return getDerived().VisitArrayType(T); -} + for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), + AEnd = T->arg_type_end(); + A != AEnd; ++A) { + TRY_TO(TraverseType(*A)); + } -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitDependentSizedExtVectorType( - DependentSizedExtVectorType *T) { - if ((T->getSizeExpr() && Visit(T->getSizeExpr())) || - Visit(T->getElementType())) - return true; + for (FunctionProtoType::exception_iterator E = T->exception_begin(), + EEnd = T->exception_end(); + E != EEnd; ++E) { + TRY_TO(TraverseType(*E)); + } + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_TYPE(UnresolvedUsingType, { }) +DEF_TRAVERSE_TYPE(TypedefType, { }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitVectorType(VectorType *T) { - if (Visit(T->getElementType())) - return true; +DEF_TRAVERSE_TYPE(TypeOfExprType, { + TRY_TO(TraverseStmt(T->getUnderlyingExpr())); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_TYPE(TypeOfType, { + TRY_TO(TraverseType(T->getUnderlyingType())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitExtVectorType(ExtVectorType *T) { - return getDerived().VisitVectorType(T); -} +DEF_TRAVERSE_TYPE(DecltypeType, { + TRY_TO(TraverseStmt(T->getUnderlyingExpr())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitFunctionType(FunctionType *T) { - if (Visit(T->getResultType())) - return true; +DEF_TRAVERSE_TYPE(RecordType, { }) +DEF_TRAVERSE_TYPE(EnumType, { }) +DEF_TRAVERSE_TYPE(TemplateTypeParmType, { }) +DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_TYPE(TemplateSpecializationType, { + TRY_TO(TraverseTemplateName(T->getTemplateName())); + TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); + }) + +DEF_TRAVERSE_TYPE(InjectedClassNameType, { }) + +DEF_TRAVERSE_TYPE(ElaboratedType, { + if (T->getQualifier()) { + TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + } + TRY_TO(TraverseType(T->getNamedType())); + }) + +DEF_TRAVERSE_TYPE(DependentNameType, { + TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + }) + +DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, { + TRY_TO(TraverseNestedNameSpecifier(T->getQualifier())); + TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs())); + }) + +DEF_TRAVERSE_TYPE(ObjCInterfaceType, { }) + +DEF_TRAVERSE_TYPE(ObjCObjectType, { + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (T->getBaseType().getTypePtr() != T) + TRY_TO(TraverseType(T->getBaseType())); + }) + +DEF_TRAVERSE_TYPE(ObjCObjectPointerType, { + TRY_TO(TraverseType(T->getPointeeType())); + }) + +#undef DEF_TRAVERSE_TYPE + +// ----------------- TypeLoc traversal ----------------- + +// This macro makes available a variable TL, the passed-in TypeLoc. +// It calls WalkUpFrom* for the Type in the given TypeLoc, in addition +// to WalkUpFrom* for the TypeLoc itself, such that existing clients +// that override the WalkUpFrom*Type() and/or Visit*Type() methods +// continue to work. +#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \ + template<typename Derived> \ + bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \ + TRY_TO(WalkUpFrom##TYPE(TL.getTypePtr())); \ + TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \ + { CODE; } \ + return true; \ + } template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitFunctionNoProtoType( - FunctionNoProtoType *T) { - return getDerived().VisitFunctionType(T); +bool RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc( + QualifiedTypeLoc TL) { + // Move this over to the 'main' typeloc tree. Note that this is a + // move -- we pretend that we were really looking at the unqualified + // typeloc all along -- rather than a recursion, so we don't follow + // the normal CRTP plan of going through + // getDerived().TraverseTypeLoc. If we did, we'd be traversing + // twice for the same type (once as a QualifiedTypeLoc version of + // the type, once as an UnqualifiedTypeLoc version of the type), + // which in effect means we'd call VisitTypeLoc twice with the + // 'same' type. This solves that problem, at the cost of never + // seeing the qualified version of the type (unless the client + // subclasses TraverseQualifiedTypeLoc themselves). It's not a + // perfect solution. A perfect solution probably requires making + // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a + // wrapper around Type* -- rather than being its own class in the + // type hierarchy. + return TraverseTypeLoc(TL.getUnqualifiedLoc()); } +DEF_TRAVERSE_TYPELOC(BuiltinType, { }) + +// FIXME: ComplexTypeLoc is unfinished +DEF_TRAVERSE_TYPELOC(ComplexType, { + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); + }) + +DEF_TRAVERSE_TYPELOC(PointerType, { + TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); + }) + +DEF_TRAVERSE_TYPELOC(BlockPointerType, { + TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); + }) + +DEF_TRAVERSE_TYPELOC(LValueReferenceType, { + TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); + }) + +DEF_TRAVERSE_TYPELOC(RValueReferenceType, { + TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); + }) + +// FIXME: location of base class? +// We traverse this in the type case as well, but how is it not reached through +// the pointee type? +DEF_TRAVERSE_TYPELOC(MemberPointerType, { + TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0))); + TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); + }) + +DEF_TRAVERSE_TYPELOC(ConstantArrayType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + }) + +DEF_TRAVERSE_TYPELOC(IncompleteArrayType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + }) + +DEF_TRAVERSE_TYPELOC(VariableArrayType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + }) + +DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, { + TRY_TO(TraverseTypeLoc(TL.getElementLoc())); + if (TL.getTypePtr()->getSizeExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + }) + +// FIXME: order? why not size expr first? +// FIXME: base VectorTypeLoc is unfinished +DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, { + if (TL.getTypePtr()->getSizeExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); + }) + +// FIXME: VectorTypeLoc is unfinished +DEF_TRAVERSE_TYPELOC(VectorType, { + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); + }) + +// FIXME: size and attributes +// FIXME: base VectorTypeLoc is unfinished +DEF_TRAVERSE_TYPELOC(ExtVectorType, { + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); + }) + +DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, { + TRY_TO(TraverseTypeLoc(TL.getResultLoc())); + }) + +// FIXME: location of arguments, exception specifications (attributes?) +// Note that we have the ParmVarDecl's here. Do we want to use them? +DEF_TRAVERSE_TYPELOC(FunctionProtoType, { + TRY_TO(TraverseTypeLoc(TL.getResultLoc())); + + FunctionProtoType *T = TL.getTypePtr(); +/* + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TRY_TO(TraverseDecl(TL.getArg(I))); + } +*/ + for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), + AEnd = T->arg_type_end(); + A != AEnd; ++A) { + TRY_TO(TraverseType(*A)); + } + for (FunctionProtoType::exception_iterator E = T->exception_begin(), + EEnd = T->exception_end(); + E != EEnd; ++E) { + TRY_TO(TraverseType(*E)); + } + }) + +DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, { }) +DEF_TRAVERSE_TYPELOC(TypedefType, { }) + +DEF_TRAVERSE_TYPELOC(TypeOfExprType, { + TRY_TO(TraverseStmt(TL.getUnderlyingExpr())); + }) + +DEF_TRAVERSE_TYPELOC(TypeOfType, { + TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc())); + }) + +// FIXME: location of underlying expr +DEF_TRAVERSE_TYPELOC(DecltypeType, { + TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr())); + }) + +DEF_TRAVERSE_TYPELOC(RecordType, { }) +DEF_TRAVERSE_TYPELOC(EnumType, { }) +DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { }) +DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { }) + +// FIXME: use the loc for the template name? +DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, { + TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName())); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + } + }) + +DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { }) + +// FIXME: use the sourceloc on qualifier? +DEF_TRAVERSE_TYPELOC(ElaboratedType, { + if (TL.getTypePtr()->getQualifier()) { + TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + } + TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc())); + }) + +// FIXME: use the sourceloc on qualifier? +DEF_TRAVERSE_TYPELOC(DependentNameType, { + TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + }) + +DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, { + TRY_TO(TraverseNestedNameSpecifier(TL.getTypePtr()->getQualifier())); + for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I))); + } + }) + +DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { }) + +DEF_TRAVERSE_TYPELOC(ObjCObjectType, { + // We have to watch out here because an ObjCInterfaceType's base + // type is itself. + if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr()) + TRY_TO(TraverseTypeLoc(TL.getBaseLoc())); + }) + +DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, { + TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); + }) + +#undef DEF_TRAVERSE_TYPELOC + +// ----------------- Decl traversal ----------------- +// +// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing +// the children that come from the DeclContext associated with it. +// Therefore each Traverse* only needs to worry about children other +// than those. + template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitFunctionProtoType( - FunctionProtoType *T) { - for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), - AEnd = T->arg_type_end(); - A != AEnd; ++A) { - if (Visit(*A)) - return true; - } +bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) { + if (!DC) + return true; - for (FunctionProtoType::exception_iterator E = T->exception_begin(), - EEnd = T->exception_end(); - E != EEnd; ++E) { - if (Visit(*E)) - return true; + for (DeclContext::decl_iterator Child = DC->decls_begin(), + ChildEnd = DC->decls_end(); + Child != ChildEnd; ++Child) { + TRY_TO(TraverseDecl(*Child)); } - return getDerived().VisitFunctionType(T); + return true; } -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitUnresolvedUsingType( - UnresolvedUsingType *T) { - return getDerived().VisitType(T); +// This macro makes available a variable D, the passed-in decl. +#define DEF_TRAVERSE_DECL(DECL, CODE) \ +template<typename Derived> \ +bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \ + TRY_TO(WalkUpFrom##DECL (D)); \ + { CODE; } \ + TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \ + return true; \ } -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTypedefType(TypedefType *T) { - return getDerived().VisitType(T); -} +DEF_TRAVERSE_DECL(AccessSpecDecl, { }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTypeOfExprType(TypeOfExprType *T) { - if (Visit(T->getUnderlyingExpr())) - return true; +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(TraverseStmt(D->getBody())); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_DECL(FileScopeAsmDecl, { + TRY_TO(TraverseStmt(D->getAsmString())); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTypeOfType(TypeOfType *T) { - if (Visit(T->getUnderlyingType())) - return true; +DEF_TRAVERSE_DECL(FriendDecl, { + TRY_TO(TraverseDecl(D->getFriendDecl())); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_DECL(FriendTemplateDecl, { + TRY_TO(TraverseDecl(D->getFriendDecl())); + for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) { + TemplateParameterList *TPL = D->getTemplateParameterList(I); + for (TemplateParameterList::iterator ITPL = TPL->begin(), + ETPL = TPL->end(); + ITPL != ETPL; ++ITPL) { + TRY_TO(TraverseDecl(*ITPL)); + } + } + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitDecltypeType(DecltypeType *T) { - if (Visit(T->getUnderlyingExpr())) +DEF_TRAVERSE_DECL(LinkageSpecDecl, { }) + +DEF_TRAVERSE_DECL(ObjCClassDecl, { + // FIXME: implement this + }) + +DEF_TRAVERSE_DECL(ObjCForwardProtocolDecl, { + // FIXME: implement this + }) + +DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, { + // FIXME: implement this + }) + +DEF_TRAVERSE_DECL(StaticAssertDecl, { + TRY_TO(TraverseStmt(D->getAssertExpr())); + TRY_TO(TraverseStmt(D->getMessage())); + }) + +DEF_TRAVERSE_DECL(TranslationUnitDecl, { + // Code in an unnamed namespace shows up automatically in + // decls_begin()/decls_end(). Thus we don't need to recurse on + // D->getAnonymousNamespace(). + }) + +DEF_TRAVERSE_DECL(NamespaceAliasDecl, { + // We shouldn't traverse an aliased namespace, since it will be + // defined (and, therefore, traversed) somewhere else. + // + // 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; + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_DECL(NamespaceDecl, { + // Code in an unnamed namespace shows up automatically in + // decls_begin()/decls_end(). Thus we don't need to recurse on + // D->getAnonymousNamespace(). + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTagType(TagType *T) { - return getDerived().VisitType(T); -} +DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, { + // FIXME: implement + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitRecordType(RecordType *T) { - return getDerived().VisitTagType(T); -} +DEF_TRAVERSE_DECL(ObjCCategoryDecl, { + // FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, { + // FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCImplementationDecl, { + // FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCInterfaceDecl, { + // FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCProtocolDecl, { + // FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCMethodDecl, { + // FIXME: implement + }) + +DEF_TRAVERSE_DECL(ObjCPropertyDecl, { + // FIXME: implement + }) +DEF_TRAVERSE_DECL(UsingDecl, { + TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameDecl())); + }) + +DEF_TRAVERSE_DECL(UsingDirectiveDecl, { + TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + }) + +DEF_TRAVERSE_DECL(UsingShadowDecl, { }) + +// A helper method for TemplateDecl's children. template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitEnumType(EnumType *T) { - return getDerived().VisitType(T); +bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper( + TemplateParameterList *TPL) { + if (TPL) { + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + } + return true; } +DEF_TRAVERSE_DECL(ClassTemplateDecl, { + TRY_TO(TraverseDecl(D->getTemplatedDecl())); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + // We should not traverse the specializations/partial + // specializations. Those will show up in other contexts. + // getInstantiatedFromMemberTemplate() is just a link from a + // template instantiation back to the template from which it was + // instantiated, and thus should not be traversed either. + }) + +DEF_TRAVERSE_DECL(FunctionTemplateDecl, { + TRY_TO(TraverseDecl(D->getTemplatedDecl())); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + }) + +DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { + // D is the "T" in something like + // template <template <typename> class T> class container { }; + TRY_TO(TraverseDecl(D->getTemplatedDecl())); + if (D->hasDefaultArgument()) { + TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument())); + } + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + }) + +DEF_TRAVERSE_DECL(TemplateTypeParmDecl, { + // D is the "T" in something like "template<typename T> class vector;" + if (D->hasDefaultArgument()) + TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc())); + if (D->getTypeForDecl()) + TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); + }) + +DEF_TRAVERSE_DECL(TypedefDecl, { + TRY_TO(TraverseType(D->getUnderlyingType())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the typedef, 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; }; + TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type, not something that was written in the + // source. + }) + +DEF_TRAVERSE_DECL(EnumDecl, { + if (D->getTypeForDecl()) + TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0))); + + TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + // The enumerators are already traversed by + // decls_begin()/decls_end(). + }) + + +// Helper methods for RecordDecl and its children. template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTemplateTypeParmType( - TemplateTypeParmType *T) { - return getDerived().VisitType(T); +bool RecursiveASTVisitor<Derived>::TraverseRecordHelper( + RecordDecl *D) { + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type, not something that was written in the source. + // + // The anonymous struct or union object is the variable or field + // whose type is the anonymous struct or union. We shouldn't + // traverse D->getAnonymousStructOrUnionObject(), as it's not + // something that is explicitly written in the source. + TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + return true; } template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitSubstTemplateTypeParmType( - SubstTemplateTypeParmType *T) { - return getDerived().VisitType(T); +bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper( + CXXRecordDecl *D) { + if (!TraverseRecordHelper(D)) + return false; + if (D->hasDefinition()) { + for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), + E = D->bases_end(); + I != E; ++I) { + TRY_TO(TraverseType(I->getType())); + } + // We don't traverse the friends or the conversions, as they are + // already in decls_begin()/decls_end(). + } + return true; } -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitTemplateSpecializationType( - TemplateSpecializationType *T) { - if (getDerived().VisitTemplateName(T->getTemplateName()) || - getDerived().VisitTemplateArguments(T->getArgs(), T->getNumArgs())) +DEF_TRAVERSE_DECL(RecordDecl, { + TRY_TO(TraverseRecordHelper(D)); + }) + +DEF_TRAVERSE_DECL(CXXRecordDecl, { + TRY_TO(TraverseCXXRecordHelper(D)); + }) + +DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, { + // For implicit instantiations ("set<int> x;"), we don't want to + // recurse at all, since the instatiated class isn't written in + // the source code anywhere. (Note the instatiated *type* -- + // set<int> -- is written, and will still get a callback of + // TemplateSpecializationType). For explicit instantiations + // ("template set<int>;"), we do need a callback, since this + // is the only callback that's made for this instantiation. + // We use getTypeAsWritten() to distinguish. + // FIXME: see how we want to handle template specializations. + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); return true; + }) - return getDerived().VisitType(T); +template <typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper( + const TemplateArgumentLoc *TAL, unsigned Count) { + for (unsigned I = 0; I < Count; ++I) { + TRY_TO(TraverseTemplateArgumentLoc(TAL[I])); + } + return true; } +DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { + // The partial specialization. + if (TemplateParameterList *TPL = D->getTemplateParameters()) { + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) { + TRY_TO(TraverseDecl(*I)); + } + } + // The args that remains unspecialized. + TRY_TO(TraverseTemplateArgumentLocsHelper( + D->getTemplateArgsAsWritten(), D->getNumTemplateArgsAsWritten())); + + // Don't need the ClassTemplatePartialSpecializationHelper, even + // though that's our parent class -- we already visit all the + // template args here. + TRY_TO(TraverseCXXRecordHelper(D)); + }) + +DEF_TRAVERSE_DECL(EnumConstantDecl, { + TRY_TO(TraverseStmt(D->getInitExpr())); + }) + +DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, { + // Like UnresolvedUsingTypenameDecl, but without the 'typename': + // template <class T> Class A : public Base<T> { using Base<T>::foo; }; + TRY_TO(TraverseNestedNameSpecifier(D->getTargetNestedNameSpecifier())); + }) + template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitInjectedClassNameType( - InjectedClassNameType *T) { - return getDerived().VisitType(T); +bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) { + TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + if (D->getTypeSourceInfo()) + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + return true; } -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitElaboratedType(ElaboratedType *T) { - if (T->getQualifier() && - getDerived().VisitNestedNameSpecifier(T->getQualifier())) - return true; - if (Visit(T->getNamedType())) - return true; +DEF_TRAVERSE_DECL(FieldDecl, { + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, { + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + // FIXME: implement the rest. + }) + +DEF_TRAVERSE_DECL(ObjCIvarDecl, { + TRY_TO(TraverseDeclaratorHelper(D)); + if (D->isBitField()) + TRY_TO(TraverseStmt(D->getBitWidth())); + // FIXME: implement the rest. + }) template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitDependentNameType( - DependentNameType *T) { - if (T->getQualifier() && - getDerived().VisitNestedNameSpecifier(T->getQualifier())) +bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) { + TRY_TO(TraverseNestedNameSpecifier(D->getQualifier())); + + // Visit the function type itself, which can be either + // FunctionNoProtoType or FunctionProtoType, or a typedef. If it's + // not a Function*ProtoType, then it can't have a body or arguments, + // so we have to do less work. + Type *FuncType = D->getType().getTypePtr(); + if (FunctionProtoType *FuncProto = dyn_cast<FunctionProtoType>(FuncType)) { + if (D->isThisDeclarationADefinition()) { + // Don't call Traverse*, or the result type and parameter types + // will be double counted. + TRY_TO(WalkUpFromFunctionProtoType(FuncProto)); + } else { + // This works around a bug in Clang that does not add the parameters + // to decls_begin/end for function declarations (as opposed to + // definitions): + // http://llvm.org/PR7442 + // We work around this here by traversing the function type. + // This isn't perfect because we don't traverse the default + // values, if any. It also may not interact great with + // templates. But it's the best we can do until the bug is + // fixed. + // FIXME: replace the entire 'if' statement with + // TRY_TO(WalkUpFromFunctionProtoType(FuncProto)); + // when the bug is fixed. + TRY_TO(TraverseFunctionProtoType(FuncProto)); + return true; + } + } else if (FunctionNoProtoType *FuncNoProto = + dyn_cast<FunctionNoProtoType>(FuncType)) { + // Don't call Traverse*, or the result type will be double + // counted. + TRY_TO(WalkUpFromFunctionNoProtoType(FuncNoProto)); + } else { // a typedef type, or who knows what + assert(!D->isThisDeclarationADefinition() && "Unexpected function type"); + TRY_TO(TraverseType(D->getType())); return true; + } - if (T->getTemplateId() && - getDerived().VisitTemplateSpecializationType( - const_cast<TemplateSpecializationType *>(T->getTemplateId()))) - return true; + TRY_TO(TraverseType(D->getResultType())); + TRY_TO(TraverseDeclContextHelper(D)); // Parameters. - return getDerived().VisitType(T); + if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) { + // Constructor initializers. + for (CXXConstructorDecl::init_iterator I = Ctor->init_begin(), + E = Ctor->init_end(); + I != E; ++I) { + TRY_TO(TraverseConstructorInitializer(*I)); + } + } + + if (D->isThisDeclarationADefinition()) { + TRY_TO(TraverseStmt(D->getBody())); // Function body. + } + return true; } +DEF_TRAVERSE_DECL(FunctionDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); + }) + +DEF_TRAVERSE_DECL(CXXMethodDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); + }) + +DEF_TRAVERSE_DECL(CXXConstructorDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); + }) + +// CXXConversionDecl is the declaration of a type conversion operator. +// It's not a cast expression. +DEF_TRAVERSE_DECL(CXXConversionDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); + }) + +DEF_TRAVERSE_DECL(CXXDestructorDecl, { + // We skip decls_begin/decls_end, which are already covered by + // TraverseFunctionHelper(). + return TraverseFunctionHelper(D); + }) + template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitObjCInterfaceType( - ObjCInterfaceType *T) { - return getDerived().VisitObjCObjectType(T); +bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) { + TRY_TO(TraverseDeclaratorHelper(D)); + // FIXME: This often double-counts -- for instance, for all local + // vars, though not for global vars -- because the initializer is + // also captured when the var-decl is in a DeclStmt. + TRY_TO(TraverseStmt(D->getInit())); + return true; } -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitObjCObjectType(ObjCObjectType *T) { - // We have to watch out here because an ObjCInterfaceType's base - // type is itself. - if (T->getBaseType().getTypePtr() != T) - if (Visit(T->getBaseType())) - return true; +DEF_TRAVERSE_DECL(VarDecl, { + TRY_TO(TraverseVarHelper(D)); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_DECL(ImplicitParamDecl, { + TRY_TO(TraverseVarHelper(D)); + }) -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitObjCObjectPointerType( - ObjCObjectPointerType *T) { - if (Visit(T->getPointeeType())) - return true; +DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, { + // A non-type template parameter, e.g. "S" in template<int S> class Foo ... + TRY_TO(TraverseStmt(D->getDefaultArgument())); + TRY_TO(TraverseVarHelper(D)); + }) - return getDerived().VisitType(T); -} +DEF_TRAVERSE_DECL(ParmVarDecl, { + if (D->hasDefaultArg() && + D->hasUninstantiatedDefaultArg() && + !D->hasUnparsedDefaultArg()) + TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg())); -template<typename Derived> -bool RecursiveASTVisitorImpl<Derived>::VisitDecl(Decl *D) { - if (DeclContext *DC = dyn_cast<DeclContext>(D)) { - for (DeclContext::decl_iterator Child = DC->decls_begin(), - ChildEnd = DC->decls_end(); - Child != ChildEnd; ++Child) - if (Visit(*Child)) - return true; + if (D->hasDefaultArg() && + !D->hasUninstantiatedDefaultArg() && + !D->hasUnparsedDefaultArg()) + TRY_TO(TraverseStmt(D->getDefaultArg())); - return false; - } + TRY_TO(TraverseVarHelper(D)); + }) - return false; -} +#undef DEF_TRAVERSE_DECL -/// \brief A visitor that recursively walks the entire Clang AST. -/// -/// Clients of this visitor should subclass the visitor (providing -/// themselves as the template argument, using the curiously -/// recurring template pattern) and override any of the Visit* -/// methods (except Visit()) for declaration, type, statement, -/// expression, or other AST nodes where the visitor should customize -/// behavior. Returning "true" from one of these overridden functions -/// will abort the entire traversal. An overridden Visit* method -/// will not descend further into the AST for that node unless -/// Base::Visit* is called. -template<typename Derived> -class RecursiveASTVisitor : public RecursiveASTVisitorImpl<Derived> { - typedef RecursiveASTVisitorImpl<Derived> Impl; -public: - typedef RecursiveASTVisitor<Derived> Base; - - bool VisitDeclaratorDecl(DeclaratorDecl *D); - bool VisitFunctionDecl(FunctionDecl *D); - bool VisitVarDecl(VarDecl *D); - bool VisitBlockDecl(BlockDecl *D); - bool VisitDeclStmt(DeclStmt *S); - bool VisitFunctionType(FunctionType *F); - bool VisitFunctionProtoType(FunctionProtoType *F); -}; +// ----------------- Stmt traversal ----------------- +// +// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating +// over the children defined in child_begin/child_end (every stmt +// defines these, though sometimes the range is empty). Each +// individual Traverse* method only needs to worry about children +// other than those. To see what child_begin()/end() does for a given +// class, see, e.g., +// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html + +// This macro makes available a variable S, the passed-in stmt. +#define DEF_TRAVERSE_STMT(STMT, CODE) \ +template<typename Derived> \ +bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \ + TRY_TO(WalkUpFrom##STMT(S)); \ + { CODE; } \ + for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end(); \ + C != CEnd; ++C) { \ + TRY_TO(TraverseStmt(*C)); \ + } \ + return true; \ +} -#define DEFINE_VISIT(Type, Name, Statement) \ - template<typename Derived> \ - bool RecursiveASTVisitor<Derived>::Visit ## Type (Type *Name) { \ - if (Impl::Visit ## Type (Name)) return true; \ - { Statement; } \ - return false; \ - } +DEF_TRAVERSE_STMT(AsmStmt, { + TRY_TO(TraverseStmt(S->getAsmString())); + for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) { + TRY_TO(TraverseStmt(S->getInputConstraintLiteral(I))); + } + for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) { + TRY_TO(TraverseStmt(S->getOutputConstraintLiteral(I))); + } + for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) { + TRY_TO(TraverseStmt(S->getClobber(I))); + } + // child_begin()/end() iterates over inputExpr and outputExpr. + }) -DEFINE_VISIT(DeclaratorDecl, D, { - if (TypeSourceInfo *TInfo = D->getTypeSourceInfo()) - return this->Visit(TInfo->getType()); +DEF_TRAVERSE_STMT(CXXCatchStmt, { + // We don't traverse S->getCaughtType(), as we are already + // traversing the exception object, which has this type. + // child_begin()/end() iterates over the handler block. }) -DEFINE_VISIT(FunctionDecl, D, { - if (D->isThisDeclarationADefinition()) - return this->Visit(D->getBody()); +DEF_TRAVERSE_STMT(ForStmt, { + TRY_TO(TraverseDecl(S->getConditionVariable())); + // child_begin()/end() iterates over init, cond, inc, and body stmts. }) -DEFINE_VISIT(VarDecl, D, return this->Visit(D->getInit())) +DEF_TRAVERSE_STMT(IfStmt, { + TRY_TO(TraverseDecl(S->getConditionVariable())); + // child_begin()/end() iterates over cond, then, and else stmts. + }) -DEFINE_VISIT(BlockDecl, D, return this->Visit(D->getBody())) +DEF_TRAVERSE_STMT(WhileStmt, { + TRY_TO(TraverseDecl(S->getConditionVariable())); + // child_begin()/end() iterates over cond, then, and else stmts. + }) -DEFINE_VISIT(DeclStmt, S, { - for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); - I != E; ++I) { - if (this->Visit(*I)) - return true; +// These non-expr stmts (most of them), do not need any action except +// iterating over the children. +DEF_TRAVERSE_STMT(BreakStmt, { }) +DEF_TRAVERSE_STMT(CompoundStmt, { }) +DEF_TRAVERSE_STMT(ContinueStmt, { }) +DEF_TRAVERSE_STMT(CXXTryStmt, { }) +DEF_TRAVERSE_STMT(DeclStmt, { }) +DEF_TRAVERSE_STMT(DoStmt, { }) +DEF_TRAVERSE_STMT(GotoStmt, { }) +DEF_TRAVERSE_STMT(IndirectGotoStmt, { }) +DEF_TRAVERSE_STMT(LabelStmt, { }) +DEF_TRAVERSE_STMT(NullStmt, { }) +DEF_TRAVERSE_STMT(ObjCAtCatchStmt, { }) +DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, { }) +DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { }) +DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { }) +DEF_TRAVERSE_STMT(ObjCAtTryStmt, { }) +DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { }) +DEF_TRAVERSE_STMT(ReturnStmt, { }) +DEF_TRAVERSE_STMT(SwitchStmt, { }) +DEF_TRAVERSE_STMT(SwitchCase, { }) +DEF_TRAVERSE_STMT(CaseStmt, { }) +DEF_TRAVERSE_STMT(DefaultStmt, { }) + +DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, { + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper( + S->getTemplateArgs(), S->getNumTemplateArgs())); } + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); }) -// FunctionType is the common base class of FunctionNoProtoType (a -// K&R-style function declaration that has no information about -// its arguments) and FunctionProtoType. -DEFINE_VISIT(FunctionType, F, return this->Visit(F->getResultType())) +DEF_TRAVERSE_STMT(DeclRefExpr, { + TRY_TO(TraverseTemplateArgumentLocsHelper( + S->getTemplateArgs(), S->getNumTemplateArgs())); + // FIXME: Should we be recursing on the qualifier? + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + }) -DEFINE_VISIT(FunctionProtoType, F, { - for (unsigned i = 0; i != F->getNumArgs(); ++i) { - if (this->Visit(F->getArgType(i))) - return true; - } - for (unsigned i = 0; i != F->getNumExceptions(); ++i) { - if (this->Visit(F->getExceptionType(i))) - return true; +DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, { + // FIXME: Should we be recursing on these two things? + if (S->hasExplicitTemplateArgs()) { + TRY_TO(TraverseTemplateArgumentLocsHelper( + S->getExplicitTemplateArgs().getTemplateArgs(), + S->getNumTemplateArgs())); } + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); }) -#undef DEFINE_VISIT +DEF_TRAVERSE_STMT(MemberExpr, { + TRY_TO(TraverseTemplateArgumentLocsHelper( + S->getTemplateArgs(), S->getNumTemplateArgs())); + // FIXME: Should we be recursing on the qualifier? + TRY_TO(TraverseNestedNameSpecifier(S->getQualifier())); + }) -#undef DISPATCH +DEF_TRAVERSE_STMT(ImplicitCastExpr, { + // We don't traverse the cast type, as it's not written in the + // source code. + }) + +DEF_TRAVERSE_STMT(CStyleCastExpr, { + TRY_TO(TraverseType(S->getTypeAsWritten())); + }) + +DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, { + TRY_TO(TraverseType(S->getTypeAsWritten())); + }) + +DEF_TRAVERSE_STMT(CXXConstCastExpr, { + TRY_TO(TraverseType(S->getTypeAsWritten())); + }) + +DEF_TRAVERSE_STMT(CXXDynamicCastExpr, { + TRY_TO(TraverseType(S->getTypeAsWritten())); + }) + +DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, { + TRY_TO(TraverseType(S->getTypeAsWritten())); + }) + +DEF_TRAVERSE_STMT(CXXStaticCastExpr, { + TRY_TO(TraverseType(S->getTypeAsWritten())); + }) + +// InitListExpr is a tricky one, because we want to do all our work on +// the syntactic form of the listexpr, but this method takes the +// semantic form by default. We can't use the macro helper because it +// calls WalkUp*() on the semantic form, before our code can convert +// to the syntactic form. +template<typename Derived> +bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) { + if (InitListExpr *Syn = S->getSyntacticForm()) + S = Syn; + TRY_TO(WalkUpFromInitListExpr(S)); + // All we need are the default actions. FIXME: use a helper function. + for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end(); + C != CEnd; ++C) { + TRY_TO(TraverseStmt(*C)); + } + 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. + if (!S->isImplicit()) + TRY_TO(TraverseType(S->getType())); + }) + +DEF_TRAVERSE_STMT(CXXNewExpr, { + TRY_TO(TraverseType(S->getAllocatedType())); + }) + +// These exprs (most of them), do not need any action except iterating +// over the children. +DEF_TRAVERSE_STMT(AddrLabelExpr, { }) +DEF_TRAVERSE_STMT(ArraySubscriptExpr, { }) +DEF_TRAVERSE_STMT(BlockDeclRefExpr, { }) +DEF_TRAVERSE_STMT(BlockExpr, { }) +DEF_TRAVERSE_STMT(ChooseExpr, { }) +DEF_TRAVERSE_STMT(CompoundLiteralExpr, { }) +DEF_TRAVERSE_STMT(CXXBindReferenceExpr, { }) +DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { }) +DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { }) +DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { }) +DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) +DEF_TRAVERSE_STMT(CXXExprWithTemporaries, { }) +DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) +DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { }) +DEF_TRAVERSE_STMT(CXXThisExpr, { }) +DEF_TRAVERSE_STMT(CXXThrowExpr, { }) +DEF_TRAVERSE_STMT(CXXTypeidExpr, { }) +DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { }) +DEF_TRAVERSE_STMT(DesignatedInitExpr, { }) +DEF_TRAVERSE_STMT(ExtVectorElementExpr, { }) +DEF_TRAVERSE_STMT(GNUNullExpr, { }) +DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { }) +DEF_TRAVERSE_STMT(ObjCEncodeExpr, { }) +DEF_TRAVERSE_STMT(ObjCImplicitSetterGetterRefExpr, { }) +DEF_TRAVERSE_STMT(ObjCIsaExpr, { }) +DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { }) +DEF_TRAVERSE_STMT(ObjCMessageExpr, { }) +DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { }) +DEF_TRAVERSE_STMT(ObjCProtocolExpr, { }) +DEF_TRAVERSE_STMT(ObjCSelectorExpr, { }) +DEF_TRAVERSE_STMT(ObjCSuperExpr, { }) +DEF_TRAVERSE_STMT(OffsetOfExpr, { }) +DEF_TRAVERSE_STMT(ParenExpr, { }) +DEF_TRAVERSE_STMT(ParenListExpr, { }) +DEF_TRAVERSE_STMT(PredefinedExpr, { }) +DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) +DEF_TRAVERSE_STMT(SizeOfAlignOfExpr, { }) +DEF_TRAVERSE_STMT(StmtExpr, { }) +DEF_TRAVERSE_STMT(TypesCompatibleExpr, { }) +DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, { }) +DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { }) +DEF_TRAVERSE_STMT(UnresolvedMemberExpr, { }) +DEF_TRAVERSE_STMT(VAArgExpr, { }) +DEF_TRAVERSE_STMT(CXXConstructExpr, { }) + +DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { + // This is called for code like 'return T()' where T is a class type. + TRY_TO(TraverseType(S->getType())); + }) + +DEF_TRAVERSE_STMT(CallExpr, { }) +DEF_TRAVERSE_STMT(CXXMemberCallExpr, { }) +DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { }) + +// These operators (all of them) do not need any action except +// iterating over the children. +DEF_TRAVERSE_STMT(ConditionalOperator, { }) +DEF_TRAVERSE_STMT(UnaryOperator, { }) +DEF_TRAVERSE_STMT(BinaryOperator, { }) +DEF_TRAVERSE_STMT(CompoundAssignOperator, { }) + +// These literals (all of them) do not need any action. +DEF_TRAVERSE_STMT(IntegerLiteral, { }) +DEF_TRAVERSE_STMT(CharacterLiteral, { }) +DEF_TRAVERSE_STMT(FloatingLiteral, { }) +DEF_TRAVERSE_STMT(ImaginaryLiteral, { }) +DEF_TRAVERSE_STMT(StringLiteral, { }) +DEF_TRAVERSE_STMT(ObjCStringLiteral, { }) + +// FIXME: look at the following tricky-seeming exprs to see if we +// need to recurse on anything. These are ones that have methods +// returning decls or qualtypes or nestednamespecifier -- though I'm +// not sure if they own them -- or just seemed very complicated, or +// had lots of sub-types to explore. +// +// VisitOverloadExpr and its children: recurse on template args? etc? + +// FIXME: go through all the stmts and exprs again, and see which of them +// create new types, and recurse on the types (TypeLocs?) of those. +// 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_1TypesCompatibleExpr.html +// http://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html +// Every class that has getQualifier. + +#undef DEF_TRAVERSE_STMT + +#undef TRY_TO } // end namespace clang diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 01f4b29..55e1f84 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -92,6 +92,11 @@ public: return D; } + /// \brief Returns true if this is the first declaration. + bool isFirstDeclaration() const { + return RedeclLink.NextIsLatest(); + } + /// \brief Returns the most recent (re)declaration of this declaration. decl_type *getMostRecentDeclaration() { return getFirstDeclaration()->RedeclLink.getNext(); diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 9deae15..a0c95b1 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -99,11 +99,9 @@ public: NoStmtClass = 0, #define STMT(CLASS, PARENT) CLASS##Class, #define STMT_RANGE(BASE, FIRST, LAST) \ - first##BASE##Constant = FIRST##Class, \ - last##BASE##Constant = LAST##Class, + first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class, #define LAST_STMT_RANGE(BASE, FIRST, LAST) \ - first##BASE##Constant = FIRST##Class, \ - last##BASE##Constant = LAST##Class + first##BASE##Constant=FIRST##Class, last##BASE##Constant=LAST##Class #define ABSTRACT_STMT(STMT) #include "clang/AST/StmtNodes.inc" }; @@ -617,24 +615,16 @@ public: /// IfStmt - This represents an if/then/else. /// class IfStmt : public Stmt { - enum { COND, THEN, ELSE, END_EXPR }; + enum { VAR, COND, THEN, ELSE, END_EXPR }; Stmt* SubExprs[END_EXPR]; - /// \brief If non-NULL, the declaration in the "if" statement. - VarDecl *Var; - SourceLocation IfLoc; SourceLocation ElseLoc; public: - IfStmt(SourceLocation IL, VarDecl *var, Expr *cond, Stmt *then, - SourceLocation EL = SourceLocation(), Stmt *elsev = 0) - : Stmt(IfStmtClass), Var(var), IfLoc(IL), ElseLoc(EL) { - SubExprs[COND] = reinterpret_cast<Stmt*>(cond); - SubExprs[THEN] = then; - SubExprs[ELSE] = elsev; - } - + IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, + Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0); + /// \brief Build an empty if/then/else statement explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) { } @@ -646,8 +636,8 @@ public: /// printf("x is %d", x); /// } /// \endcode - VarDecl *getConditionVariable() const { return Var; } - void setConditionVariable(VarDecl *V) { Var = V; } + VarDecl *getConditionVariable() const; + void setConditionVariable(ASTContext &C, VarDecl *V); const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt *>(E); } @@ -689,9 +679,8 @@ protected: /// SwitchStmt - This represents a 'switch' stmt. /// class SwitchStmt : public Stmt { - enum { COND, BODY, END_EXPR }; + enum { VAR, COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; - VarDecl *Var; // This points to a linked list of case and default statements. SwitchCase *FirstCase; SourceLocation SwitchLoc; @@ -700,12 +689,7 @@ protected: virtual void DoDestroy(ASTContext &Ctx); public: - SwitchStmt(VarDecl *Var, Expr *cond) - : Stmt(SwitchStmtClass), Var(Var), FirstCase(0) - { - SubExprs[COND] = reinterpret_cast<Stmt*>(cond); - SubExprs[BODY] = NULL; - } + SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond); /// \brief Build a empty switch statement. explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } @@ -719,8 +703,8 @@ public: /// // ... /// } /// \endcode - VarDecl *getConditionVariable() const { return Var; } - void setConditionVariable(VarDecl *V) { Var = V; } + VarDecl *getConditionVariable() const; + void setConditionVariable(ASTContext &C, VarDecl *V); const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} const Stmt *getBody() const { return SubExprs[BODY]; } @@ -768,18 +752,12 @@ public: /// WhileStmt - This represents a 'while' stmt. /// class WhileStmt : public Stmt { - enum { COND, BODY, END_EXPR }; - VarDecl *Var; + enum { VAR, COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; SourceLocation WhileLoc; public: - WhileStmt(VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL) - : Stmt(WhileStmtClass), Var(Var) - { - SubExprs[COND] = reinterpret_cast<Stmt*>(cond); - SubExprs[BODY] = body; - WhileLoc = WL; - } + WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, + SourceLocation WL); /// \brief Build an empty while statement. explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) { } @@ -792,8 +770,8 @@ public: /// // ... /// } /// \endcode - VarDecl *getConditionVariable() const { return Var; } - void setConditionVariable(VarDecl *V) { Var = V; } + VarDecl *getConditionVariable() const; + void setConditionVariable(ASTContext &C, VarDecl *V); Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } const Expr *getCond() const { return reinterpret_cast<Expr*>(SubExprs[COND]);} @@ -875,23 +853,14 @@ public: /// specified in the source. /// class ForStmt : public Stmt { - enum { INIT, COND, INC, BODY, END_EXPR }; + enum { INIT, CONDVAR, COND, INC, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; // SubExprs[INIT] is an expression or declstmt. - VarDecl *CondVar; SourceLocation ForLoc; SourceLocation LParenLoc, RParenLoc; public: - ForStmt(Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, Stmt *Body, - SourceLocation FL, SourceLocation LP, SourceLocation RP) - : Stmt(ForStmtClass), CondVar(condVar), ForLoc(FL), LParenLoc(LP), - RParenLoc(RP) - { - SubExprs[INIT] = Init; - SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); - SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); - SubExprs[BODY] = Body; - } + ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, + Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP); /// \brief Build an empty for statement. explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } @@ -906,8 +875,8 @@ public: /// // ... /// } /// \endcode - VarDecl *getConditionVariable() const { return CondVar; } - void setConditionVariable(VarDecl *V) { CondVar = V; } + VarDecl *getConditionVariable() const; + void setConditionVariable(ASTContext &C, VarDecl *V); Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } Expr *getInc() { return reinterpret_cast<Expr*>(SubExprs[INC]); } diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index a48f4e6..4da2e34 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -16,6 +16,7 @@ #include "llvm/System/DataTypes.h" #include <cassert> +#include <cstddef> #include <iterator> namespace clang { diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 8b38001..7d5123f 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -256,6 +256,10 @@ public: return Args.NumArgs; } + /// Determines whether two template arguments are superficially the + /// same. + bool structurallyEquals(const TemplateArgument &Other) const; + /// \brief Construct a template argument pack. void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); @@ -476,6 +480,28 @@ public: const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const TemplateArgument &Arg); + +inline TemplateSpecializationType::iterator + TemplateSpecializationType::end() const { + return getArgs() + getNumArgs(); +} + +inline DependentTemplateSpecializationType::iterator + DependentTemplateSpecializationType::end() const { + return getArgs() + getNumArgs(); +} + +inline const TemplateArgument & + TemplateSpecializationType::getArg(unsigned Idx) const { + assert(Idx < getNumArgs() && "Template argument out of range"); + return getArgs()[Idx]; +} + +inline const TemplateArgument & + DependentTemplateSpecializationType::getArg(unsigned Idx) const { + assert(Idx < getNumArgs() && "Template argument out of range"); + return getArgs()[Idx]; +} } // end namespace clang diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 2e3b6df..ddfac71 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -101,6 +101,14 @@ class TemplateName { } public: + // \brief Kind of name that is actually stored. + enum NameKind { + Template, + OverloadedTemplate, + QualifiedTemplate, + DependentTemplate + }; + TemplateName() : Storage() { } explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } explicit TemplateName(OverloadedTemplateStorage *Storage) @@ -110,6 +118,9 @@ public: /// \brief Determine whether this template name is NULL. bool isNull() const { return Storage.isNull(); } + + // \brief Get the kind of name that is actually stored. + NameKind getKind() const; /// \brief Retrieve the the underlying template declaration that /// this template name refers to, if known. diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index c24bddb..a1a29e6 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -271,6 +271,8 @@ public: } } + bool isSupersetOf(Qualifiers Other) const; + bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } @@ -627,6 +629,14 @@ public: bool isAtLeastAsQualifiedAs(QualType Other) const; QualType getNonReferenceType() const; + /// \brief Determine the type of an expression that calls a function of + /// with the given result type. + /// + /// This routine removes a top-level reference (since there are no + /// expressions of reference type) and deletes top-level cvr-qualifiers + /// from non-class types (in C++) or all types (in C). + QualType getCallResultType(ASTContext &Context) const; + /// getDesugaredType - Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of /// the type is already concrete, it returns it unmodified. This is similar @@ -835,6 +845,9 @@ public: /// Helper methods to distinguish type categories. All type predicates /// operate on the canonical type, ignoring typedefs and qualifiers. + /// isBuiltinType - returns true if the type is a builtin type. + bool isBuiltinType() const; + /// isSpecificBuiltinType - Test for a particular builtin type. bool isSpecificBuiltinType(unsigned K) const; @@ -846,8 +859,11 @@ public: bool isCharType() const; bool isWideCharType() const; bool isAnyCharacterType() const; - bool isIntegralType() const; + bool isIntegralType(ASTContext &Ctx) const; + /// \brief Determine whether this type is an integral or enumeration type. + bool isIntegralOrEnumerationType() const; + /// Floating point categories. bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double) /// isComplexType() does *not* include complex integers (a GCC extension). @@ -923,6 +939,10 @@ public: /// an objective pointer type for the purpose of GC'ability bool hasObjCPointerRepresentation() const; + /// \brief Determine whether this type has a floating-point representation + /// of some sort, e.g., it is a floating-point type or a vector thereof. + bool hasFloatingRepresentation() const; + // Type Checking Functions: Check to see if this type is structurally the // specified type, ignoring typedefs and qualifiers, and return a pointer to // the best type we can. @@ -1001,6 +1021,9 @@ public: CanQualType getCanonicalTypeUnqualified() const; // in CanonicalType.h void dump() const; static bool classof(const Type *) { return true; } + + friend class PCHReader; + friend class PCHWriter; }; template <> inline const TypedefType *Type::getAs() const { @@ -1640,6 +1663,13 @@ public: /// Since the constructor takes the number of vector elements, the /// client is responsible for converting the size into the number of elements. class VectorType : public Type, public llvm::FoldingSetNode { +public: + enum AltiVecSpecific { + NotAltiVec, // is not AltiVec vector + AltiVec, // is AltiVec vector + Pixel, // is AltiVec 'vector Pixel' + Bool // is AltiVec 'vector bool ...' + }; protected: /// ElementType - The element type of the vector. QualType ElementType; @@ -1647,21 +1677,16 @@ protected: /// NumElements - The number of elements in the vector. unsigned NumElements; - /// AltiVec - True if this is for an Altivec vector. - bool AltiVec; - - /// Pixel - True if this is for an Altivec vector pixel. - bool Pixel; + AltiVecSpecific AltiVecSpec; VectorType(QualType vecType, unsigned nElements, QualType canonType, - bool isAltiVec, bool isPixel) : + AltiVecSpecific altiVecSpec) : Type(Vector, canonType, vecType->isDependentType()), - ElementType(vecType), NumElements(nElements), - AltiVec(isAltiVec), Pixel(isPixel) {} + ElementType(vecType), NumElements(nElements), AltiVecSpec(altiVecSpec) {} VectorType(TypeClass tc, QualType vecType, unsigned nElements, - QualType canonType, bool isAltiVec, bool isPixel) + QualType canonType, AltiVecSpecific altiVecSpec) : Type(tc, canonType, vecType->isDependentType()), ElementType(vecType), - NumElements(nElements), AltiVec(isAltiVec), Pixel(isPixel) {} + NumElements(nElements), AltiVecSpec(altiVecSpec) {} friend class ASTContext; // ASTContext creates these. virtual Linkage getLinkageImpl() const; @@ -1674,22 +1699,18 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - bool isAltiVec() const { return AltiVec; } - - bool isPixel() const { return Pixel; } - + AltiVecSpecific getAltiVecSpecific() const { return AltiVecSpec; } + void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getElementType(), getNumElements(), getTypeClass(), - AltiVec, Pixel); + Profile(ID, getElementType(), getNumElements(), getTypeClass(), AltiVecSpec); } static void Profile(llvm::FoldingSetNodeID &ID, QualType ElementType, unsigned NumElements, TypeClass TypeClass, - bool isAltiVec, bool isPixel) { + unsigned AltiVecSpec) { ID.AddPointer(ElementType.getAsOpaquePtr()); ID.AddInteger(NumElements); ID.AddInteger(TypeClass); - ID.AddBoolean(isAltiVec); - ID.AddBoolean(isPixel); + ID.AddInteger(AltiVecSpec); } static bool classof(const Type *T) { @@ -1705,7 +1726,7 @@ public: /// points, colors, and textures (modeled after OpenGL Shading Language). class ExtVectorType : public VectorType { ExtVectorType(QualType vecType, unsigned nElements, QualType canonType) : - VectorType(ExtVector, vecType, nElements, canonType, false, false) {} + VectorType(ExtVector, vecType, nElements, canonType, NotAltiVec) {} friend class ASTContext; // ASTContext creates these. public: static int getPointAccessorIdx(char c) { @@ -1875,6 +1896,7 @@ protected: public: QualType getResultType() const { return ResultType; } + unsigned getRegParmType() const { return RegParm; } bool getNoReturnAttr() const { return NoReturn; } CallingConv getCallConv() const { return (CallingConv)CallConv; } @@ -1882,6 +1904,12 @@ public: return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv); } + /// \brief Determine the type of an expression that calls a function of + /// this type. + QualType getCallResultType(ASTContext &Context) const { + return getResultType().getCallResultType(Context); + } + static llvm::StringRef getNameForCallConv(CallingConv CC); static bool classof(const Type *T) { @@ -2416,23 +2444,14 @@ public: /// dependent. class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { - - // The ASTContext is currently needed in order to profile expressions. - // FIXME: avoid this. - // - // The bool is whether this is a current instantiation. - llvm::PointerIntPair<ASTContext*, 1, bool> ContextAndCurrentInstantiation; - - /// \brief The name of the template being specialized. + /// \brief The name of the template being specialized. TemplateName Template; /// \brief - The number of template arguments named in this class /// template specialization. unsigned NumArgs; - TemplateSpecializationType(ASTContext &Context, - TemplateName T, - bool IsCurrentInstantiation, + TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, unsigned NumArgs, QualType Canon); @@ -2467,13 +2486,13 @@ public: /// True if this template specialization type matches a current /// instantiation in the context in which it is found. bool isCurrentInstantiation() const { - return ContextAndCurrentInstantiation.getInt(); + return isa<InjectedClassNameType>(getCanonicalTypeInternal()); } typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } - iterator end() const; + iterator end() const; // defined inline in TemplateBase.h /// \brief Retrieve the name of the template that we are specializing. TemplateName getTemplateName() const { return Template; } @@ -2488,20 +2507,18 @@ public: /// \brief Retrieve a specific template argument as a type. /// \precondition @c isArgType(Arg) - const TemplateArgument &getArg(unsigned Idx) const; + const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h bool isSugared() const { return !isDependentType() || isCurrentInstantiation(); } QualType desugar() const { return getCanonicalTypeInternal(); } - void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Template, isCurrentInstantiation(), getArgs(), NumArgs, - *ContextAndCurrentInstantiation.getPointer()); + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Ctx) { + Profile(ID, Template, getArgs(), NumArgs, Ctx); } static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - bool IsCurrentInstantiation, const TemplateArgument *Args, unsigned NumArgs, ASTContext &Context); @@ -2545,6 +2562,9 @@ class InjectedClassNameType : public Type { friend class ASTContext; // ASTContext creates these. friend class TagDecl; // TagDecl mutilates the Decl + friend class PCHReader; // FIXME: ASTContext::getInjectedClassNameType is not + // currently suitable for PCH reading, too much + // interdependencies. InjectedClassNameType(CXXRecordDecl *D, QualType TST) : Type(InjectedClassName, QualType(), true), Decl(D), InjectedType(TST) { @@ -2679,6 +2699,7 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these public: + ~ElaboratedType(); /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2723,11 +2744,8 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { /// \brief The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; - typedef llvm::PointerUnion<const IdentifierInfo *, - const TemplateSpecializationType *> NameType; - /// \brief The type that this typename specifier refers to. - NameType Name; + const IdentifierInfo *Name; DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType CanonType) @@ -2737,17 +2755,10 @@ class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { "DependentNameType requires a dependent nested-name-specifier"); } - DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - const TemplateSpecializationType *Ty, QualType CanonType) - : TypeWithKeyword(Keyword, DependentName, CanonType, true), - NNS(NNS), Name(Ty) { - assert(NNS->isDependent() && - "DependentNameType requires a dependent nested-name-specifier"); - } - friend class ASTContext; // ASTContext creates these public: + virtual ~DependentNameType(); /// \brief Retrieve the qualification on this type. NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2759,13 +2770,7 @@ public: /// form of the original typename was terminated by an identifier, /// e.g., "typename T::type". const IdentifierInfo *getIdentifier() const { - return Name.dyn_cast<const IdentifierInfo *>(); - } - - /// \brief Retrieve the type named by the typename specifier as a - /// type specialization. - const TemplateSpecializationType *getTemplateId() const { - return Name.dyn_cast<const TemplateSpecializationType *>(); + return Name; } bool isSugared() const { return false; } @@ -2776,10 +2781,10 @@ public: } static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, NameType Name) { + NestedNameSpecifier *NNS, const IdentifierInfo *Name) { ID.AddInteger(Keyword); ID.AddPointer(NNS); - ID.AddPointer(Name.getOpaqueValue()); + ID.AddPointer(Name); } static bool classof(const Type *T) { @@ -2788,6 +2793,83 @@ public: static bool classof(const DependentNameType *T) { return true; } }; +/// DependentTemplateSpecializationType - Represents a template +/// specialization type whose template cannot be resolved, e.g. +/// A<T>::template B<T> +class DependentTemplateSpecializationType : + public TypeWithKeyword, public llvm::FoldingSetNode { + + /// \brief The nested name specifier containing the qualifier. + NestedNameSpecifier *NNS; + + /// \brief The identifier of the template. + const IdentifierInfo *Name; + + /// \brief - The number of template arguments named in this class + /// template specialization. + unsigned NumArgs; + + const TemplateArgument *getArgBuffer() const { + return reinterpret_cast<const TemplateArgument*>(this+1); + } + TemplateArgument *getArgBuffer() { + return reinterpret_cast<TemplateArgument*>(this+1); + } + + DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args, + QualType Canon); + + virtual void Destroy(ASTContext& C); + + friend class ASTContext; // ASTContext creates these + +public: + virtual ~DependentTemplateSpecializationType(); + + NestedNameSpecifier *getQualifier() const { return NNS; } + const IdentifierInfo *getIdentifier() const { return Name; } + + /// \brief Retrieve the template arguments. + const TemplateArgument *getArgs() const { + return getArgBuffer(); + } + + /// \brief Retrieve the number of template arguments. + unsigned getNumArgs() const { return NumArgs; } + + const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h + + typedef const TemplateArgument * iterator; + iterator begin() const { return getArgs(); } + iterator end() const; // inline in TemplateBase.h + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + void Profile(llvm::FoldingSetNodeID &ID, ASTContext &Context) { + Profile(ID, Context, getKeyword(), NNS, Name, NumArgs, getArgs()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, + ASTContext &Context, + ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *Qualifier, + const IdentifierInfo *Name, + unsigned NumArgs, + const TemplateArgument *Args); + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentTemplateSpecialization; + } + static bool classof(const DependentTemplateSpecializationType *T) { + return true; + } +}; + /// ObjCObjectType - Represents a class type in Objective C. /// Every Objective C type is a combination of a base type and a /// list of protocols. @@ -3310,6 +3392,12 @@ 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 @@ -3454,6 +3542,10 @@ inline bool Type::isTemplateTypeParmType() const { return isa<TemplateTypeParmType>(CanonicalType); } +inline bool Type::isBuiltinType() const { + return getAs<BuiltinType>(); +} + inline bool Type::isSpecificBuiltinType(unsigned K) const { if (const BuiltinType *BT = getAs<BuiltinType>()) if (BT->getKind() == (BuiltinType::Kind) K) diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index f988f0e..842c068 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -142,7 +142,7 @@ private: /// \brief Return the TypeLoc for a type source info. inline TypeLoc TypeSourceInfo::getTypeLoc() const { - return TypeLoc(Ty, (void*)(this + 1)); + return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1))); } /// \brief Wrapper of type source information for a type with @@ -657,7 +657,7 @@ struct ObjCInterfaceLocInfo { }; /// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, +class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc, ObjCInterfaceTypeLoc, ObjCInterfaceType, ObjCInterfaceLocInfo> { @@ -1033,13 +1033,20 @@ public: setLAngleLoc(Loc); setRAngleLoc(Loc); setTemplateNameLoc(Loc); + initializeArgLocs(getNumArgs(), getTypePtr()->getArgs(), + getArgInfos(), Loc); + } - for (unsigned i = 0, e = getNumArgs(); i != e; ++i) { + static void initializeArgLocs(unsigned NumArgs, + const TemplateArgument *Args, + TemplateArgumentLocInfo *ArgInfos, + SourceLocation Loc) { + for (unsigned i = 0, e = NumArgs; i != e; ++i) { TemplateArgumentLocInfo Info; #ifndef NDEBUG // If asserts are enabled, be sure to initialize the argument // loc with the right kind of pointer. - switch (getTypePtr()->getArg(i).getKind()) { + switch (Args[i].getKind()) { case TemplateArgument::Expression: case TemplateArgument::Declaration: Info = TemplateArgumentLocInfo((Expr*) 0); @@ -1050,7 +1057,7 @@ public: break; case TemplateArgument::Template: - Info = TemplateArgumentLocInfo(SourceRange(), SourceLocation()); + Info = TemplateArgumentLocInfo(SourceRange(Loc), Loc); break; case TemplateArgument::Integral: @@ -1060,7 +1067,7 @@ public: break; } #endif - getArgInfos()[i] = Info; + ArgInfos[i] = Info; } } @@ -1251,9 +1258,9 @@ public: } }; -struct DependentNameLocInfo { - SourceLocation KeywordLoc; - SourceRange QualifierRange; +// This is exactly the structure of an ElaboratedTypeLoc whose inner +// type is some sort of TypeDeclTypeLoc. +struct DependentNameLocInfo : ElaboratedLocInfo { SourceLocation NameLoc; }; @@ -1303,6 +1310,107 @@ public: } }; +// This is exactly the structure of an ElaboratedTypeLoc whose inner +// type is some sort of TemplateSpecializationTypeLoc. +struct DependentTemplateSpecializationLocInfo : DependentNameLocInfo { + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; + // followed by a TemplateArgumentLocInfo[] +}; + +class DependentTemplateSpecializationTypeLoc : + public ConcreteTypeLoc<UnqualTypeLoc, + DependentTemplateSpecializationTypeLoc, + DependentTemplateSpecializationType, + DependentTemplateSpecializationLocInfo> { +public: + SourceLocation getKeywordLoc() const { + return this->getLocalData()->KeywordLoc; + } + void setKeywordLoc(SourceLocation Loc) { + this->getLocalData()->KeywordLoc = Loc; + } + + SourceRange getQualifierRange() const { + return this->getLocalData()->QualifierRange; + } + void setQualifierRange(SourceRange Range) { + this->getLocalData()->QualifierRange = Range; + } + + SourceLocation getNameLoc() const { + return this->getLocalData()->NameLoc; + } + void setNameLoc(SourceLocation Loc) { + this->getLocalData()->NameLoc = Loc; + } + + SourceLocation getLAngleLoc() const { + return this->getLocalData()->LAngleLoc; + } + void setLAngleLoc(SourceLocation Loc) { + this->getLocalData()->LAngleLoc = Loc; + } + + SourceLocation getRAngleLoc() const { + return this->getLocalData()->RAngleLoc; + } + void setRAngleLoc(SourceLocation Loc) { + this->getLocalData()->RAngleLoc = Loc; + } + + unsigned getNumArgs() const { + return getTypePtr()->getNumArgs(); + } + + void setArgLocInfo(unsigned i, TemplateArgumentLocInfo AI) { +#ifndef NDEBUG + AI.validateForArgument(getTypePtr()->getArg(i)); +#endif + getArgInfos()[i] = AI; + } + TemplateArgumentLocInfo getArgLocInfo(unsigned i) const { + return getArgInfos()[i]; + } + + TemplateArgumentLoc getArgLoc(unsigned i) const { + return TemplateArgumentLoc(getTypePtr()->getArg(i), getArgLocInfo(i)); + } + + SourceRange getLocalSourceRange() const { + if (getKeywordLoc().isValid()) + return SourceRange(getKeywordLoc(), getRAngleLoc()); + else + return SourceRange(getQualifierRange().getBegin(), getRAngleLoc()); + } + + void copy(DependentTemplateSpecializationTypeLoc Loc) { + unsigned size = getFullDataSize(); + assert(size == Loc.getFullDataSize()); + memcpy(Data, Loc.Data, size); + } + + void initializeLocal(SourceLocation Loc) { + setKeywordLoc(Loc); + setQualifierRange(SourceRange(Loc)); + setNameLoc(Loc); + setLAngleLoc(Loc); + setRAngleLoc(Loc); + TemplateSpecializationTypeLoc::initializeArgLocs(getNumArgs(), + getTypePtr()->getArgs(), + getArgInfos(), Loc); + } + + unsigned getExtraLocalDataSize() const { + return getNumArgs() * sizeof(TemplateArgumentLocInfo); + } + +private: + TemplateArgumentLocInfo *getArgInfos() const { + return static_cast<TemplateArgumentLocInfo*>(getExtraLocalData()); + } +}; + } #endif diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h index e729488..880af26 100644 --- a/include/clang/AST/TypeLocBuilder.h +++ b/include/clang/AST/TypeLocBuilder.h @@ -79,7 +79,14 @@ class TypeLocBuilder { size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); } - + + /// Resets this builder to the newly-initialized state. + void clear() { +#ifndef NDEBUG + LastTy = QualType(); +#endif + Index = Capacity; + } /// Pushes space for a new TypeLoc of the given type. Invalidates /// any TypeLocs previously retrieved from this builder. diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 02508af..9cb5686 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -92,6 +92,7 @@ NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) +DEPENDENT_TYPE(DependentTemplateSpecialization, Type) TYPE(ObjCObject, Type) TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) diff --git a/include/clang/AST/UsuallyTinyPtrVector.h b/include/clang/AST/UsuallyTinyPtrVector.h index 5ee40e0..534d4d4 100644 --- a/include/clang/AST/UsuallyTinyPtrVector.h +++ b/include/clang/AST/UsuallyTinyPtrVector.h @@ -41,6 +41,7 @@ public: typedef const T **iterator; iterator begin() const; iterator end() const; + size_t size() const; void push_back(T *Method); void Destroy(); @@ -56,7 +57,6 @@ UsuallyTinyPtrVector<T>::begin() const { return &Vec->front(); } - template<typename T> typename UsuallyTinyPtrVector<T>::iterator UsuallyTinyPtrVector<T>::end() const { @@ -72,6 +72,15 @@ UsuallyTinyPtrVector<T>::end() const { } template<typename T> +size_t UsuallyTinyPtrVector<T>::size() const { + if ((Storage & 0x01) == 0) + return (Storage == 0) ? 0 : 1; + + vector_type *Vec = reinterpret_cast<vector_type *>(Storage & ~0x01); + return Vec->size(); +} + +template<typename T> void UsuallyTinyPtrVector<T>::push_back(T *Element) { if (Storage == 0) { // 0 -> 1 element. diff --git a/include/clang/Analysis/Analyses/PrintfFormatString.h b/include/clang/Analysis/Analyses/PrintfFormatString.h index e4f7c57..d907637 100644 --- a/include/clang/Analysis/Analyses/PrintfFormatString.h +++ b/include/clang/Analysis/Analyses/PrintfFormatString.h @@ -25,8 +25,8 @@ namespace analyze_printf { class ArgTypeResult { public: - enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CStrTy, - WCStrTy }; + enum Kind { UnknownTy, InvalidTy, SpecificTy, ObjCPointerTy, CPointerTy, + CStrTy, WCStrTy }; private: const Kind K; QualType T; @@ -57,6 +57,7 @@ public: InvalidSpecifier = 0, // C99 conversion specifiers. dArg, // 'd' + IntAsCharArg, // 'c' iArg, // 'i', oArg, // 'o', uArg, // 'u', @@ -70,7 +71,6 @@ public: GArg, // 'G', aArg, // 'a', AArg, // 'A', - IntAsCharArg, // 'c' CStrArg, // 's' VoidPtrArg, // 'p' OutIntPtrArg, // 'n' @@ -124,45 +124,87 @@ public: bool isUIntArg() const { return kind >= oArg && kind <= XArg; } bool isDoubleArg() const { return kind >= fArg && kind <= AArg; } Kind getKind() const { return kind; } + void setKind(Kind k) { kind = k; } unsigned getLength() const { // Conversion specifiers currently only are represented by // single characters, but we be flexible. return 1; } + const char *toString() const; private: const char *Position; Kind kind; }; -enum LengthModifier { - None, - AsChar, // 'hh' - AsShort, // 'h' - AsLong, // 'l' - AsLongLong, // 'll', 'q' (BSD, deprecated) - AsIntMax, // 'j' - AsSizeT, // 'z' - AsPtrDiff, // 't' - AsLongDouble, // 'L' - AsWideChar = AsLong // for '%ls' +class LengthModifier { +public: + enum Kind { + None, + AsChar, // 'hh' + AsShort, // 'h' + AsLong, // 'l' + AsLongLong, // 'll', 'q' (BSD, deprecated) + AsIntMax, // 'j' + AsSizeT, // 'z' + AsPtrDiff, // 't' + AsLongDouble, // 'L' + AsWideChar = AsLong // for '%ls' + }; + + LengthModifier() + : Position(0), kind(None) {} + LengthModifier(const char *pos, Kind k) + : Position(pos), kind(k) {} + + const char *getStart() const { + return Position; + } + + unsigned getLength() const { + switch (kind) { + default: + return 1; + case AsLongLong: + case AsChar: + return 2; + case None: + return 0; + } + } + + Kind getKind() const { return kind; } + void setKind(Kind k) { kind = k; } + + const char *toString() const; + +private: + const char *Position; + Kind kind; }; class OptionalAmount { public: enum HowSpecified { NotSpecified, Constant, Arg, Invalid }; - OptionalAmount(HowSpecified h, unsigned i, const char *st) - : start(st), hs(h), amt(i) {} + OptionalAmount(HowSpecified howSpecified, + unsigned amount, + const char *amountStart, + unsigned amountLength, + bool usesPositionalArg) + : start(amountStart), length(amountLength), hs(howSpecified), amt(amount), + UsesPositionalArg(usesPositionalArg), UsesDotPrefix(0) {} - OptionalAmount(bool b = true) - : start(0), hs(b ? NotSpecified : Invalid), amt(0) {} + OptionalAmount(bool valid = true) + : start(0),length(0), hs(valid ? NotSpecified : Invalid), amt(0), + UsesPositionalArg(0), UsesDotPrefix(0) {} bool isInvalid() const { return hs == Invalid; } HowSpecified getHowSpecified() const { return hs; } + void setHowSpecified(HowSpecified h) { hs = h; } bool hasDataArgument() const { return hs == Arg; } @@ -177,36 +219,87 @@ public: } const char *getStart() const { - return start; + // We include the . character if it is given. + return start - UsesDotPrefix; + } + + unsigned getConstantLength() const { + assert(hs == Constant); + return length + UsesDotPrefix; } ArgTypeResult getArgType(ASTContext &Ctx) const; + void toString(llvm::raw_ostream &os) const; + + bool usesPositionalArg() const { return (bool) UsesPositionalArg; } + unsigned getPositionalArgIndex() const { + assert(hasDataArgument()); + return amt + 1; + } + + bool usesDotPrefix() const { return UsesDotPrefix; } + void setUsesDotPrefix() { UsesDotPrefix = true; } + private: const char *start; + unsigned length; HowSpecified hs; unsigned amt; + bool UsesPositionalArg : 1; + bool UsesDotPrefix; +}; + +// Class representing optional flags with location and representation +// information. +class OptionalFlag { +public: + OptionalFlag(const char *Representation) + : representation(Representation), flag(false) {} + bool isSet() { return flag; } + void set() { flag = true; } + void clear() { flag = false; } + void setPosition(const char *position) { + assert(position); + this->position = position; + } + const char *getPosition() const { + assert(position); + return position; + } + const char *toString() const { return representation; } + + // Overloaded operators for bool like qualities + operator bool() const { return flag; } + OptionalFlag& operator=(const bool &rhs) { + flag = rhs; + return *this; // Return a reference to myself. + } +private: + const char *representation; + const char *position; + bool flag; }; class FormatSpecifier { LengthModifier LM; - unsigned IsLeftJustified : 1; - unsigned HasPlusPrefix : 1; - unsigned HasSpacePrefix : 1; - unsigned HasAlternativeForm : 1; - unsigned HasLeadingZeroes : 1; + OptionalFlag IsLeftJustified; // '-' + OptionalFlag HasPlusPrefix; // '+' + OptionalFlag HasSpacePrefix; // ' ' + OptionalFlag HasAlternativeForm; // '#' + OptionalFlag HasLeadingZeroes; // '0' /// Positional arguments, an IEEE extension: /// IEEE Std 1003.1, 2004 Edition /// http://www.opengroup.org/onlinepubs/009695399/functions/printf.html - unsigned UsesPositionalArg : 1; + bool UsesPositionalArg; unsigned argIndex; ConversionSpecifier CS; OptionalAmount FieldWidth; OptionalAmount Precision; public: - FormatSpecifier() : LM(None), - IsLeftJustified(0), HasPlusPrefix(0), HasSpacePrefix(0), - HasAlternativeForm(0), HasLeadingZeroes(0), UsesPositionalArg(0), + FormatSpecifier() : + IsLeftJustified("-"), HasPlusPrefix("+"), HasSpacePrefix(" "), + HasAlternativeForm("#"), HasLeadingZeroes("0"), UsesPositionalArg(false), argIndex(0) {} static FormatSpecifier Parse(const char *beg, const char *end); @@ -218,12 +311,27 @@ public: void setLengthModifier(LengthModifier lm) { LM = lm; } - void setIsLeftJustified() { IsLeftJustified = 1; } - void setHasPlusPrefix() { HasPlusPrefix = 1; } - void setHasSpacePrefix() { HasSpacePrefix = 1; } - void setHasAlternativeForm() { HasAlternativeForm = 1; } - void setHasLeadingZeros() { HasLeadingZeroes = 1; } - void setUsesPositionalArg() { UsesPositionalArg = 1; } + void setIsLeftJustified(const char *position) { + IsLeftJustified = true; + IsLeftJustified.setPosition(position); + } + void setHasPlusPrefix(const char *position) { + HasPlusPrefix = true; + HasPlusPrefix.setPosition(position); + } + void setHasSpacePrefix(const char *position) { + HasSpacePrefix = true; + HasSpacePrefix.setPosition(position); + } + void setHasAlternativeForm(const char *position) { + HasAlternativeForm = true; + HasAlternativeForm.setPosition(position); + } + void setHasLeadingZeros(const char *position) { + HasLeadingZeroes = true; + HasLeadingZeroes.setPosition(position); + } + void setUsesPositionalArg() { UsesPositionalArg = true; } void setArgIndex(unsigned i) { assert(CS.consumesDataArgument()); @@ -235,13 +343,18 @@ public: return argIndex; } + unsigned getPositionalArgIndex() const { + assert(CS.consumesDataArgument()); + return argIndex + 1; + } + // Methods for querying the format specifier. const ConversionSpecifier &getConversionSpecifier() const { return CS; } - LengthModifier getLengthModifier() const { + const LengthModifier &getLengthModifier() const { return LM; } @@ -255,6 +368,7 @@ public: void setPrecision(const OptionalAmount &Amt) { Precision = Amt; + Precision.setUsesDotPrefix(); } const OptionalAmount &getPrecision() const { @@ -268,12 +382,30 @@ public: /// more than one type. ArgTypeResult getArgType(ASTContext &Ctx) const; - bool isLeftJustified() const { return (bool) IsLeftJustified; } - bool hasPlusPrefix() const { return (bool) HasPlusPrefix; } - bool hasAlternativeForm() const { return (bool) HasAlternativeForm; } - bool hasLeadingZeros() const { return (bool) HasLeadingZeroes; } - bool hasSpacePrefix() const { return (bool) HasSpacePrefix; } - bool usesPositionalArg() const { return (bool) UsesPositionalArg; } + const OptionalFlag &isLeftJustified() const { return IsLeftJustified; } + const OptionalFlag &hasPlusPrefix() const { return HasPlusPrefix; } + const OptionalFlag &hasAlternativeForm() const { return HasAlternativeForm; } + const OptionalFlag &hasLeadingZeros() const { return HasLeadingZeroes; } + const OptionalFlag &hasSpacePrefix() const { return HasSpacePrefix; } + bool usesPositionalArg() const { return UsesPositionalArg; } + + /// Changes the specifier and length according to a QualType, retaining any + /// flags or options. Returns true on success, or false when a conversion + /// was not successful. + bool fixType(QualType QT); + + void toString(llvm::raw_ostream &os) const; + + // Validation methods - to check if any element results in undefined behavior + bool hasValidPlusPrefix() const; + bool hasValidAlternativeForm() const; + bool hasValidLeadingZeros() const; + bool hasValidSpacePrefix() const; + bool hasValidLeftJustified() const; + + bool hasValidLengthModifier() const; + bool hasValidPrecision() const; + bool hasValidFieldWidth() const; }; enum PositionContext { FieldWidthPos = 0, PrecisionPos = 1 }; diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index c6c9eed..7cd4812 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -24,6 +24,7 @@ #include "llvm/ADT/PointerIntPair.h" #include <algorithm> #include <cstring> +#include <memory> namespace clang { diff --git a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h index d627b88..f20a49a 100644 --- a/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h +++ b/include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h @@ -22,13 +22,14 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclCXX.h" -#define DISPATCH_CASE(CASE,CLASS) \ -case Decl::CASE: \ -static_cast<ImplClass*>(this)->Visit##CLASS(static_cast<CLASS*>(D));\ +#define DISPATCH_CASE(CLASS) \ +case Decl::CLASS: \ +static_cast<ImplClass*>(this)->Visit##CLASS##Decl( \ + static_cast<CLASS##Decl*>(D)); \ break; -#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS(CLASS* D) {} -#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS(CLASS* D)\ +#define DEFAULT_DISPATCH(CLASS) void Visit##CLASS##Decl(CLASS##Decl* D) {} +#define DEFAULT_DISPATCH_VARDECL(CLASS) void Visit##CLASS##Decl(CLASS##Decl* D)\ { static_cast<ImplClass*>(this)->VisitVarDecl(D); } @@ -55,34 +56,39 @@ public: void VisitDecl(Decl* D) { switch (D->getKind()) { - DISPATCH_CASE(Function,FunctionDecl) - DISPATCH_CASE(CXXMethod,CXXMethodDecl) - DISPATCH_CASE(Var,VarDecl) - DISPATCH_CASE(ParmVar,ParmVarDecl) // FIXME: (same) - DISPATCH_CASE(ImplicitParam,ImplicitParamDecl) - DISPATCH_CASE(EnumConstant,EnumConstantDecl) - DISPATCH_CASE(Typedef,TypedefDecl) - DISPATCH_CASE(Record,RecordDecl) // FIXME: Refine. VisitStructDecl? - DISPATCH_CASE(Enum,EnumDecl) + DISPATCH_CASE(Function) + DISPATCH_CASE(CXXMethod) + DISPATCH_CASE(Var) + DISPATCH_CASE(ParmVar) // FIXME: (same) + DISPATCH_CASE(ImplicitParam) + DISPATCH_CASE(EnumConstant) + DISPATCH_CASE(Typedef) + DISPATCH_CASE(Record) // FIXME: Refine. VisitStructDecl? + DISPATCH_CASE(CXXRecord) + DISPATCH_CASE(Enum) default: assert(false && "Subtype of ScopedDecl not handled."); } } - DEFAULT_DISPATCH(VarDecl) - DEFAULT_DISPATCH(FunctionDecl) - DEFAULT_DISPATCH(CXXMethodDecl) - DEFAULT_DISPATCH_VARDECL(ParmVarDecl) - DEFAULT_DISPATCH(ImplicitParamDecl) - DEFAULT_DISPATCH(EnumConstantDecl) - DEFAULT_DISPATCH(TypedefDecl) - DEFAULT_DISPATCH(RecordDecl) - DEFAULT_DISPATCH(EnumDecl) - DEFAULT_DISPATCH(ObjCInterfaceDecl) - DEFAULT_DISPATCH(ObjCClassDecl) - DEFAULT_DISPATCH(ObjCMethodDecl) - DEFAULT_DISPATCH(ObjCProtocolDecl) - DEFAULT_DISPATCH(ObjCCategoryDecl) + DEFAULT_DISPATCH(Var) + DEFAULT_DISPATCH(Function) + DEFAULT_DISPATCH(CXXMethod) + DEFAULT_DISPATCH_VARDECL(ParmVar) + DEFAULT_DISPATCH(ImplicitParam) + DEFAULT_DISPATCH(EnumConstant) + DEFAULT_DISPATCH(Typedef) + DEFAULT_DISPATCH(Record) + DEFAULT_DISPATCH(Enum) + DEFAULT_DISPATCH(ObjCInterface) + DEFAULT_DISPATCH(ObjCClass) + DEFAULT_DISPATCH(ObjCMethod) + DEFAULT_DISPATCH(ObjCProtocol) + DEFAULT_DISPATCH(ObjCCategory) + + void VisitCXXRecordDecl(CXXRecordDecl *D) { + static_cast<ImplClass*>(this)->VisitRecordDecl(D); + } }; } // end namespace clang diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td new file mode 100644 index 0000000..98871d2 --- /dev/null +++ b/include/clang/Basic/Attr.td @@ -0,0 +1,382 @@ +//////////////////////////////////////////////////////////////////////////////// +// Note: This file is a work in progress. Please do not apply non-trivial +// updates unless you have talked to Sean Hunt <rideau3@gmail.com> prior. +// Merely adding a new attribute is a trivial update. +//////////////////////////////////////////////////////////////////////////////// + +// An attribute's subject is whatever it appertains to. In this file, it is +// more accurately a list of things that an attribute can appertain to. All +// Decls and Stmts are possibly AttrSubjects (even though the syntax may not +// allow attributes on a given Decl or Stmt). +class AttrSubject; + +include "clang/Basic/DeclNodes.td" +include "clang/Basic/StmtNodes.td" + +// A subset-subject is an AttrSubject constrained to operate only on some subset +// of that subject. +// +// The description is used in output messages to specify what the subject +// represents. FIXME: Deal with translation issues. +// +// The code fragment is a boolean expression that will confirm that the subject +// meets the requirements; the subject will have the name S, and will have the +// type specified by the base. It should be a simple boolean expression. +class SubsetSubject<AttrSubject base, string description, code check> + : AttrSubject { + AttrSubject Base = base; + string Description = description; + code CheckCode = check; +} + +// This is the type of a variable which C++0x defines [[aligned()]] as being +// a possible subject. +def NormalVar : SubsetSubject<Var, "non-register, non-parameter variable", + [{S->getStorageClass() != VarDecl::Register && + S->getKind() != Decl::ImplicitParam + S->getKind() != Decl::ParmVar + S->getKind() != Decl::NonTypeTemplateParm}]>; +def CXXVirtualMethod : SubsetSubject<CXXRecord, "virtual member function", + [{S->isVirtual()}]>; +def NonBitField : SubsetSubject<Field, "non-bit field", + [{!S->isBitField()}]>; + +// A single argument to an attribute +class Argument<string name> { + string Name = name; +} + +class IdentifierArgument<string name> : Argument<name>; +class IntArgument<string name> : Argument<name>; +class StringArgument<string name> : Argument<name>; +class ExprArgument<string name> : Argument<name>; +class FunctionArgument<string name> : Argument<name>; +class ObjCInterfaceArgument<string name> : Argument<name>; +class UnsignedIntArgument<string name> : Argument<name>; +class UnsignedIntOrTypeArgument<string name> : Argument<name>; + +// An integer argument with a default value +class DefaultIntArgument<string name, int default> : IntArgument<name> { + int Default = default; +} + +// Zero or more arguments of a type +class VariadicArgument<Argument arg> : Argument<arg.Name> { + Argument VariadicArg = arg; +} + +class Attr { + // The various ways in which an attribute can be spelled in source + list<string> Spellings; + // The things to which an attribute can appertain + list<AttrSubject> Subjects; + // The arguments allowed on an attribute + list<Argument> Args = []; + // The namespaces in which the attribute appears in C++0x attributes. + // The attribute will not be permitted in C++0x attribute-specifiers if + // this is empty; the empty string can be used as a namespace. + list<string> Namespaces = []; + // A temporary development bit to tell TableGen not to emit certain + // information about the attribute. + bit DoNotEmit = 1; +} + +// +// Attributes begin here +// + +def Alias : Attr { + let Spellings = ["alias"]; + let Args = [StringArgument<"AliasName">]; +} + +def Aligned : Attr { + let Spellings = ["align", "aligned"]; + let Subjects = [NonBitField, NormalVar, Tag]; + let Args = [UnsignedIntOrTypeArgument<"Alignment">]; + let Namespaces = ["", "std"]; +} + +def AlignMac68k : Attr { + let Spellings = []; +} + +def AlwaysInline : Attr { + let Spellings = ["always_inline"]; +} + +def AnalyzerNoReturn : Attr { + let Spellings = ["analyzer_noreturn"]; +} + +def Annotate : Attr { + let Spellings = ["annotate"]; + let Args = [StringArgument<"Annotation">]; +} + +def AsmLabel : Attr { + let Spellings = []; + let Args = [StringArgument<"Label">]; +} + +def BaseCheck : Attr { + let Spellings = ["base_check"]; + let Subjects = [CXXRecord]; + let Namespaces = ["", "std"]; + let DoNotEmit = 0; +} + +def Blocks : Attr { + let Spellings = ["blocks"]; + let Args = [IdentifierArgument<"Type">]; +} + +def CarriesDependency : Attr { + let Spellings = ["carries_dependency"]; + let Subjects = [ParmVar, Function]; + let Namespaces = ["", "std"]; + let DoNotEmit = 0; +} + +def CDecl : Attr { + let Spellings = ["cdecl", "__cdecl"]; +} + +def CFReturnsRetained : Attr { + let Spellings = ["cf_returns_retained"]; +} + +def CFReturnsNotRetained : Attr { + let Spellings = ["cf_returns_not_retained"]; +} + +def Cleanup : Attr { + let Spellings = ["cleanup"]; + let Args = [FunctionArgument<"FunctionDecl">]; +} + +def Const : Attr { + let Spellings = ["const"]; +} + +def Constructor : Attr { + let Spellings = ["constructor"]; + let Args = [IntArgument<"Priority">]; +} + +def Deprecated : Attr { + let Spellings = ["deprecated"]; +} + +def Destructor : Attr { + let Spellings = ["destructor"]; + let Args = [IntArgument<"Priority">]; +} + +def DLLExport : Attr { + let Spellings = ["dllexport"]; +} + +def DLLImport : Attr { + let Spellings = ["dllimport"]; +} + +def FastCall : Attr { + let Spellings = ["fastcall", "__fastcall"]; +} + +def Final : Attr { + let Spellings = ["final"]; + let Subjects = [CXXRecord, CXXVirtualMethod]; + let Namespaces = ["", "std"]; + let DoNotEmit = 0; +} + +def Format : Attr { + let Spellings = ["format"]; + let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, + IntArgument<"FirstArg">]; +} + +def FormatArg : Attr { + let Spellings = ["format_arg"]; + let Args = [IntArgument<"FormatIdx">]; +} + +def GNUInline : Attr { + let Spellings = ["gnu_inline"]; +} + +def Hiding : Attr { + let Spellings = ["hiding"]; + let Subjects = [Field, CXXMethod]; + let Namespaces = ["", "std"]; + let DoNotEmit = 0; +} + +def IBAction : Attr { + let Spellings = ["ibaction"]; +} + +def IBOutlet : Attr { + let Spellings = ["iboutlet"]; +} + +def IBOutletCollection : Attr { + let Spellings = ["iboutletcollection"]; + let Args = [ObjCInterfaceArgument<"Class">]; +} + +def Malloc : Attr { + let Spellings = ["malloc"]; +} + +def MaxFieldAlignment : Attr { + let Spellings = []; + let Args = [UnsignedIntArgument<"Alignment">]; +} + +def MSP430Interrupt : Attr { + let Spellings = []; + let Args = [UnsignedIntArgument<"Number">]; +} + +def NoDebug : Attr { + let Spellings = ["nodebug"]; +} + +def NoInline : Attr { + let Spellings = ["noinline"]; +} + +def NonNull : Attr { + let Spellings = ["nonnull"]; + let Args = [VariadicArgument<UnsignedIntArgument<"Args">>]; +} + +def NoReturn : Attr { + let Spellings = ["noreturn"]; + // FIXME: Does GCC allow this on the function instead? + let Subjects = [Function]; + let Namespaces = ["", "std"]; +} + +def NoInstrumentFunction : Attr { + let Spellings = ["no_instrument_function"]; + let Subjects = [Function]; +} + +def NoThrow : Attr { + let Spellings = ["nothrow"]; +} + +def NSReturnsRetained : Attr { + let Spellings = ["ns_returns_retained"]; +} + +def NSReturnsNotRetained : Attr { + let Spellings = ["ns_returns_not_retained"]; +} + +def ObjCException : Attr { + let Spellings = ["objc_exception"]; +} + +def ObjCNSObject : Attr { + let Spellings = ["NSOjbect"]; +} + +def Override : Attr { + let Spellings = ["override"]; + let Subjects = [CXXVirtualMethod]; + let Namespaces = ["", "std"]; + let DoNotEmit = 0; +} + +def Overloadable : Attr { + let Spellings = ["overloadable"]; +} + +def Packed : Attr { + let Spellings = ["packed"]; +} + +def Pure : Attr { + let Spellings = ["pure"]; +} + +def Regparm : Attr { + let Spellings = ["regparm"]; + let Args = [UnsignedIntArgument<"NumParams">]; +} + +def ReqdWorkGroupSize : Attr { + let Spellings = ["reqd_work_group_size"]; + let Args = [UnsignedIntArgument<"XDim">, UnsignedIntArgument<"YDim">, + UnsignedIntArgument<"ZDim">]; +} + +def InitPriority : Attr { + let Spellings = ["init_priority"]; + let Args = [UnsignedIntArgument<"Priority">]; +} + +def Section : Attr { + let Spellings = ["section"]; + let Args = [StringArgument<"Name">]; +} + +def Sentinel : Attr { + let Spellings = ["sentinel"]; + let Args = [DefaultIntArgument<"NulPos", 0>, + DefaultIntArgument<"Sentinel", 0>]; +} + +def StdCall : Attr { + let Spellings = ["stdcall", "__stdcall"]; +} + +def ThisCall : Attr { + let Spellings = ["thiscall", "__thiscall"]; +} + +def TransparentUnion : Attr { + let Spellings = ["transparent_union"]; +} + +def Unavailable : Attr { + let Spellings = ["unavailable"]; +} + +def Unused : Attr { + let Spellings = ["unused"]; +} + +def Used : Attr { + let Spellings = ["used"]; +} + +def Visibility : Attr { + let Spellings = ["visibility"]; + let Args = [StringArgument<"Visibility">]; +} + +def WarnUnusedResult : Attr { + let Spellings = ["warn_unused_result"]; +} + +def Weak : Attr { + let Spellings = ["weak"]; +} + +def WeakImport : Attr { + let Spellings = ["weak_import"]; +} + +def WeakRef : Attr { + let Spellings = ["weakref"]; +} + +def X86ForceAlignArgPointer : Attr { + let Spellings = []; +} diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h new file mode 100644 index 0000000..822573b --- /dev/null +++ b/include/clang/Basic/AttrKinds.h @@ -0,0 +1,31 @@ +//===----- Attr.h - Enum values for C Attribute Kinds ----------*- 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 attr::Kind enum +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ATTRKINDS_H +#define LLVM_CLANG_ATTRKINDS_H + +namespace clang { + +namespace attr { + +// Kind - This is a list of all the recognized kinds of attributes. +enum Kind { +#define ATTR(X) X, +#include "clang/Basic/AttrList.inc" + NUM_ATTRS +}; + +} // end namespace attr +} // end namespace clang + +#endif diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index b306954..cad2824 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -540,6 +540,7 @@ LIBBUILTIN(siglongjmp, "vSJi", "fr", "setjmp.h") // id objc_msgSend(id, SEL) // but we need new type letters for that. LIBBUILTIN(objc_msgSend, "v*.", "f", "objc/message.h") +BUILTIN(__builtin_objc_memmove_collectable, "v*v*vC*z", "nF") // Builtin math library functions LIBBUILTIN(pow, "ddd", "fe", "math.h") diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def index 4973076a..54e4c2b 100644 --- a/include/clang/Basic/BuiltinsARM.def +++ b/include/clang/Basic/BuiltinsARM.def @@ -14,7 +14,13 @@ // The format of this database matches clang/Basic/Builtins.def. -// FIXME: This is just a placeholder. NEON intrinsics should be listed here. +// In libgcc +BUILTIN(__clear_cache, "vc*c*", "") BUILTIN(__builtin_thread_pointer, "v*", "") +// NEON +#define GET_NEON_BUILTINS +#include "clang/Basic/arm_neon.inc" +#undef GET_NEON_BUILTINS + #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index 287bba9..e0518dc 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -18,14 +18,6 @@ // The format of this database matches clang/Basic/Builtins.def. // This is just a placeholder, the types and attributes are wrong. -BUILTIN(__builtin_altivec_abs_v16qi, "V16UcV16Sc", "") -BUILTIN(__builtin_altivec_abs_v8hi, "V8UsV8Ss", "") -BUILTIN(__builtin_altivec_abs_v4si, "V4UiV4Si", "") - -BUILTIN(__builtin_altivec_abss_v16qi, "V16UcV16Sc", "") -BUILTIN(__builtin_altivec_abss_v8hi, "V8UsV8Ss", "") -BUILTIN(__builtin_altivec_abss_v4si, "V4UiV4Si", "") - BUILTIN(__builtin_altivec_vaddcuw, "V4UiV4UiV4Ui", "") BUILTIN(__builtin_altivec_vaddsbs, "V16ScV16ScV16Sc", "") @@ -49,6 +41,67 @@ BUILTIN(__builtin_altivec_vavguh, "V8UsV8UsV8Us", "") BUILTIN(__builtin_altivec_vavgsw, "V4SiV4SiV4Si", "") BUILTIN(__builtin_altivec_vavguw, "V4UiV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vrfip, "V4fV4f", "") + +BUILTIN(__builtin_altivec_vcfsx, "V4fV4ii", "") +BUILTIN(__builtin_altivec_vcfux, "V4fV4ii", "") +BUILTIN(__builtin_altivec_vctsxs, "V4SiV4fi", "") +BUILTIN(__builtin_altivec_vctuxs, "V4UiV4fi", "") + +BUILTIN(__builtin_altivec_dss, "vUi", "") +BUILTIN(__builtin_altivec_dssall, "v", "") +BUILTIN(__builtin_altivec_dst, "vv*iUi", "") +BUILTIN(__builtin_altivec_dstt, "vv*iUi", "") +BUILTIN(__builtin_altivec_dstst, "vv*iUi", "") +BUILTIN(__builtin_altivec_dststt, "vv*iUi", "") + +BUILTIN(__builtin_altivec_vexptefp, "V4fV4f", "") + +BUILTIN(__builtin_altivec_vrfim, "V4fV4f", "") + +BUILTIN(__builtin_altivec_lvx, "V4iiv*", "") +BUILTIN(__builtin_altivec_lvxl, "V4iiv*", "") +BUILTIN(__builtin_altivec_lvebx, "V16civ*", "") +BUILTIN(__builtin_altivec_lvehx, "V8siv*", "") +BUILTIN(__builtin_altivec_lvewx, "V4iiv*", "") + +BUILTIN(__builtin_altivec_vlogefp, "V4fV4f", "") + +BUILTIN(__builtin_altivec_lvsl, "V16cUcv*", "") +BUILTIN(__builtin_altivec_lvsr, "V16cUcv*", "") + +BUILTIN(__builtin_altivec_vmaddfp, "V4fV4fV4fV4f", "") +BUILTIN(__builtin_altivec_vmhaddshs, "V8sV8sV8sV8s", "") +BUILTIN(__builtin_altivec_vmhraddshs, "V8sV8sV8sV8s", "") + +BUILTIN(__builtin_altivec_vmsumubm, "V4UiV16UcV16UcV4Ui", "") +BUILTIN(__builtin_altivec_vmsummbm, "V4SiV16ScV16UcV4Si", "") +BUILTIN(__builtin_altivec_vmsumuhm, "V4UiV8UsV8UsV4Ui", "") +BUILTIN(__builtin_altivec_vmsumshm, "V4SiV8SsV8SsV4Si", "") +BUILTIN(__builtin_altivec_vmsumuhs, "V4UiV8UsV8UsV4Ui", "") +BUILTIN(__builtin_altivec_vmsumshs, "V4SiV8SsV8SsV4Si", "") + +BUILTIN(__builtin_altivec_vmuleub, "V8UsV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vmulesb, "V8SsV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vmuleuh, "V4UiV8UsV8Us", "") +BUILTIN(__builtin_altivec_vmulesh, "V4SiV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vmuloub, "V8UsV16UcV16Uc", "") +BUILTIN(__builtin_altivec_vmulosb, "V8SsV16ScV16Sc", "") +BUILTIN(__builtin_altivec_vmulouh, "V4UiV8UsV8Us", "") +BUILTIN(__builtin_altivec_vmulosh, "V4SiV8SsV8Ss", "") + +BUILTIN(__builtin_altivec_vnmsubfp, "V4fV4fV4fV4f", "") + +BUILTIN(__builtin_altivec_vpkpx, "V8sV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vpkuhus, "V16UcV8UsV8Us", "") +BUILTIN(__builtin_altivec_vpkshss, "V16ScV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vpkuwus, "V8UsV4UiV4Ui", "") +BUILTIN(__builtin_altivec_vpkswss, "V8SsV4SiV4Si", "") +BUILTIN(__builtin_altivec_vpkshus, "V16UcV8SsV8Ss", "") +BUILTIN(__builtin_altivec_vpkswus, "V8UsV4SiV4Si", "") + +BUILTIN(__builtin_altivec_vperm_4si, "V4iV4iV4iV16Uc", "") + BUILTIN(__builtin_altivec_stvx, "vV4iiv*", "") BUILTIN(__builtin_altivec_stvxl, "vV4iiv*", "") BUILTIN(__builtin_altivec_stvebx, "vV16civ*", "") @@ -92,6 +145,48 @@ BUILTIN(__builtin_altivec_vminfp, "V4fV4fV4f", "") BUILTIN(__builtin_altivec_mtvscr, "vV4i", "") +BUILTIN(__builtin_altivec_vrefp, "V4fV4f", "") + +BUILTIN(__builtin_altivec_vrlb, "V16cV16cV16Uc", "") +BUILTIN(__builtin_altivec_vrlh, "V8sV8sV8Us", "") +BUILTIN(__builtin_altivec_vrlw, "V4iV4iV4Ui", "") + +BUILTIN(__builtin_altivec_vsel_4si, "V4iV4iV4iV4Ui", "") + +BUILTIN(__builtin_altivec_vsl, "V4iV4iV4i", "") +BUILTIN(__builtin_altivec_vslo, "V4iV4iV4i", "") + +BUILTIN(__builtin_altivec_vsrab, "V16cV16cV16Uc", "") +BUILTIN(__builtin_altivec_vsrah, "V8sV8sV8Us", "") +BUILTIN(__builtin_altivec_vsraw, "V4iV4iV4Ui", "") + +BUILTIN(__builtin_altivec_vsr, "V4iV4iV4i", "") +BUILTIN(__builtin_altivec_vsro, "V4iV4iV4i", "") + +BUILTIN(__builtin_altivec_vrfin, "V4fV4f", "") + +BUILTIN(__builtin_altivec_vrsqrtefp, "V4fV4f", "") + +BUILTIN(__builtin_altivec_vsubcuw, "V4UiV4UiV4Ui", "") + +BUILTIN(__builtin_altivec_vsum4sbs, "V4SiV16ScV4Si", "") +BUILTIN(__builtin_altivec_vsum4ubs, "V4UiV16UcV4Ui", "") +BUILTIN(__builtin_altivec_vsum4shs, "V4SiV8SsV4Si", "") + +BUILTIN(__builtin_altivec_vsum2sws, "V4SiV4SiV4Si", "") + +BUILTIN(__builtin_altivec_vsumsws, "V4SiV4SiV4Si", "") + +BUILTIN(__builtin_altivec_vrfiz, "V4fV4f", "") + +BUILTIN(__builtin_altivec_vupkhsb, "V8sV16c", "") +BUILTIN(__builtin_altivec_vupkhpx, "V4UiV8s", "") +BUILTIN(__builtin_altivec_vupkhsh, "V4iV8s", "") + +BUILTIN(__builtin_altivec_vupklsb, "V8sV16c", "") +BUILTIN(__builtin_altivec_vupklpx, "V4UiV8s", "") +BUILTIN(__builtin_altivec_vupklsh, "V4iV8s", "") + BUILTIN(__builtin_altivec_vcmpbfp_p, "iiV4fV4f", "") BUILTIN(__builtin_altivec_vcmpgefp_p, "iiV4fV4f", "") diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index c2a4e13..c595236 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -18,3 +18,15 @@ tablegen(DiagnosticGroups.inc -gen-clang-diag-groups) add_custom_target(ClangDiagnosticGroups DEPENDS DiagnosticGroups.inc) + +set(LLVM_TARGET_DEFINITIONS Attr.td) +tablegen(AttrList.inc + -gen-clang-attr-list + -I ${CMAKE_CURRENT_SOURCE_DIR}/../../) +add_custom_target(ClangAttrList + DEPENDS AttrList.inc) + +# ARM NEON +set(LLVM_TARGET_DEFINITIONS arm_neon.td) +tablegen(arm_neon.inc -gen-arm-neon-sema) +add_custom_target(ClangARMNeon DEPENDS arm_neon.inc) diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td new file mode 100644 index 0000000..203fb45 --- /dev/null +++ b/include/clang/Basic/DeclNodes.td @@ -0,0 +1,70 @@ +class AttrSubject; + +class Decl<bit abstract = 0> : AttrSubject { + bit Abstract = abstract; +} + +class DDecl<Decl base, bit abstract = 0> : Decl<abstract> { + Decl Base = base; +} + +class DeclContext { } + +def TranslationUnit : Decl, DeclContext; +def Named : Decl<1>; + def Namespace : DDecl<Named>, DeclContext; + def UsingDirective : DDecl<Named>; + def NamespaceAlias : DDecl<Named>; + def Type : DDecl<Named, 1>; + def Typedef : DDecl<Type>; + def UnresolvedUsingTypename : DDecl<Type>; + def Tag : DDecl<Type, 1>, DeclContext; + def Enum : DDecl<Tag>; + def Record : DDecl<Tag>; + def CXXRecord : DDecl<Record>; + def ClassTemplateSpecialization : DDecl<CXXRecord>; + def ClassTemplatePartialSpecialization + : DDecl<ClassTemplateSpecialization>; + def TemplateTypeParm : DDecl<Type>; + def Value : DDecl<Named, 1>; + def EnumConstant : DDecl<Value>; + def UnresolvedUsingValue : DDecl<Value>; + def Declarator : DDecl<Value, 1>; + def Function : DDecl<Declarator>, DeclContext; + def CXXMethod : DDecl<Function>; + def CXXConstructor : DDecl<CXXMethod>; + def CXXDestructor : DDecl<CXXMethod>; + def CXXConversion : DDecl<CXXMethod>; + def Field : DDecl<Declarator>; + def ObjCIvar : DDecl<Field>; + def ObjCAtDefsField : DDecl<Field>; + def Var : DDecl<Declarator>; + def ImplicitParam : DDecl<Var>; + def ParmVar : DDecl<Var>; + def NonTypeTemplateParm : DDecl<Var>; + def Template : DDecl<Named, 1>; + def FunctionTemplate : DDecl<Template>; + def ClassTemplate : DDecl<Template>; + def TemplateTemplateParm : DDecl<Template>; + def Using : DDecl<Named>; + def UsingShadow : DDecl<Named>; + def ObjCMethod : DDecl<Named>, DeclContext; + def ObjCContainer : DDecl<Named, 1>, DeclContext; + def ObjCCategory : DDecl<ObjCContainer>; + def ObjCProtocol : DDecl<ObjCContainer>; + def ObjCInterface : DDecl<ObjCContainer>; + def ObjCImpl : DDecl<ObjCContainer, 1>; + def ObjCCategoryImpl : DDecl<ObjCImpl>; + def ObjCImplementation : DDecl<ObjCImpl>; + def ObjCProperty : DDecl<Named>; + def ObjCCompatibleAlias : DDecl<Named>; +def LinkageSpec : Decl, DeclContext; +def ObjCPropertyImpl : Decl; +def ObjCForwardProtocol : Decl; +def ObjCClass : Decl; +def FileScopeAsm : Decl; +def AccessSpec : Decl; +def Friend : Decl; +def FriendTemplate : Decl; +def StaticAssert : Decl; +def Block : Decl, DeclContext; diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 62f06ed..1fe0d81 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -24,7 +24,6 @@ namespace llvm { template <typename T> class SmallVectorImpl; - class raw_ostream; } namespace clang { @@ -36,8 +35,6 @@ namespace clang { class LangOptions; class PartialDiagnostic; class Preprocessor; - class SourceManager; - class SourceRange; // Import the diagnostic enums themselves. namespace diag { @@ -98,8 +95,8 @@ namespace clang { /// compilation. class FixItHint { public: - /// \brief Tokens that should be removed to correct the error. - SourceRange RemoveRange; + /// \brief Code that should be removed to correct the error. + CharSourceRange RemoveRange; /// \brief The location at which we should insert code to correct /// the error. @@ -129,15 +126,18 @@ public: /// \brief Create a code modification hint that removes the given /// source range. - static FixItHint CreateRemoval(SourceRange RemoveRange) { + static FixItHint CreateRemoval(CharSourceRange RemoveRange) { FixItHint Hint; Hint.RemoveRange = RemoveRange; return Hint; } - + static FixItHint CreateRemoval(SourceRange RemoveRange) { + return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange)); + } + /// \brief Create a code modification hint that replaces the given /// source range with the given code string. - static FixItHint CreateReplacement(SourceRange RemoveRange, + static FixItHint CreateReplacement(CharSourceRange RemoveRange, llvm::StringRef Code) { FixItHint Hint; Hint.RemoveRange = RemoveRange; @@ -145,6 +145,11 @@ public: Hint.CodeToInsert = Code; return Hint; } + + static FixItHint CreateReplacement(SourceRange RemoveRange, + llvm::StringRef Code) { + return CreateReplacement(CharSourceRange::getTokenRange(RemoveRange), Code); + } }; /// Diagnostic - This concrete class is used by the front-end to report @@ -176,7 +181,14 @@ public: ak_nestednamespec, // NestedNameSpecifier * ak_declcontext // DeclContext * }; - + + /// Specifies which overload candidates to display when overload resolution + /// fails. + enum OverloadsShown { + Ovl_All, ///< Show all overloads. + Ovl_Best ///< Show just the "best" overload candidates. + }; + /// ArgumentValue - This typedef represents on argument value, which is a /// union discriminated by ArgumentKind, with a value. typedef std::pair<ArgumentKind, intptr_t> ArgumentValue; @@ -188,6 +200,7 @@ private: bool ErrorsAsFatal; // Treat errors like fatal errors. bool SuppressSystemWarnings; // Suppress warnings in system headers. bool SuppressAllDiagnostics; // Suppress all diagnostics. + OverloadsShown ShowOverloads; // Which overload candidates to show. unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit. unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, // 0 -> no limit. @@ -318,6 +331,13 @@ public: } bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } + /// \brief Specify which overload candidates to show when overload resolution + /// fails. By default, we show all candidates. + void setShowOverloads(OverloadsShown Val) { + ShowOverloads = Val; + } + OverloadsShown getShowOverloads() const { return ShowOverloads; } + /// \brief Pretend that the last diagnostic issued was ignored. This can /// be used by clients who suppress diagnostics themselves. void setLastDiagnosticIgnored() { @@ -582,7 +602,7 @@ private: /// DiagRanges - The list of ranges added to this diagnostic. It currently /// only support 10 ranges, could easily be extended if needed. - SourceRange DiagRanges[10]; + CharSourceRange DiagRanges[10]; enum { MaxFixItHints = 3 }; @@ -681,7 +701,7 @@ public: } } - void AddSourceRange(const SourceRange &R) const { + void AddSourceRange(const CharSourceRange &R) const { assert(NumRanges < sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) && "Too many arguments to diagnostic!"); @@ -752,11 +772,17 @@ operator<<(const DiagnosticBuilder &DB, T *DC) { inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const SourceRange &R) { - DB.AddSourceRange(R); + DB.AddSourceRange(CharSourceRange::getTokenRange(R)); return DB; } inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + const CharSourceRange &R) { + DB.AddSourceRange(R); + return DB; +} + +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, const FixItHint &Hint) { DB.AddFixItHint(Hint); return DB; @@ -849,7 +875,7 @@ public: return DiagObj->NumDiagRanges; } - SourceRange getRange(unsigned Idx) const { + const CharSourceRange &getRange(unsigned Idx) const { assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!"); return DiagObj->DiagRanges[Idx]; } @@ -886,7 +912,7 @@ class StoredDiagnostic { Diagnostic::Level Level; FullSourceLoc Loc; std::string Message; - std::vector<SourceRange> Ranges; + std::vector<CharSourceRange> Ranges; std::vector<FixItHint> FixIts; public: @@ -902,7 +928,7 @@ public: const FullSourceLoc &getLocation() const { return Loc; } llvm::StringRef getMessage() const { return Message; } - typedef std::vector<SourceRange>::const_iterator range_iterator; + typedef std::vector<CharSourceRange>::const_iterator range_iterator; range_iterator range_begin() const { return Ranges.begin(); } range_iterator range_end() const { return Ranges.end(); } unsigned range_size() const { return Ranges.size(); } diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 88e7dc1..4b0bf57 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -66,6 +66,7 @@ def err_target_unknown_triple : Error< "unknown target triple '%0', please use -triple or -arch">; def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; +def err_target_unknown_cxxabi : Error<"unknown C++ ABI '%0'">; def err_target_invalid_feature : Error<"invalid target feature '%0'">; // Source manager diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index c7cad73..989ec38 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -18,7 +18,10 @@ def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal; // Error generated by the backend. def err_fe_inline_asm : Error<"%0">, CatInlineAsm; -def note_fe_inline_asm_here : Note<"generated from here">; +def note_fe_inline_asm_here : Note<"instantated into assembly here">; + + + def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; def err_fe_stdout_binary : Error<"unable to change standard output to binary">, @@ -186,9 +189,6 @@ def warn_pch_math_errno : Error< "math functions %select{do not respect|respect}0 'errno' in PCH " "file but they are currently set to %select{not respect|respect}1 " "'errno'">; -def warn_pch_overflow_checking : Error< - "signed integer overflow checking was %select{disabled|enabled}0 in PCH " - "file but is currently %select{disabled|enabled}1">; def warn_pch_optimize : Error< "the macro '__OPTIMIZE__' was %select{not defined|defined}0 in " "the PCH file but is currently %select{undefined|defined}1">; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index b79bf8e..930fe42 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -17,11 +17,14 @@ def Implicit : DiagGroup<"implicit", [ ]>; // Empty DiagGroups are recognized by clang but ignored. +def : DiagGroup<"abi">; def : DiagGroup<"address">; def AddressOfTemporary : DiagGroup<"address-of-temporary">; def : DiagGroup<"aggregate-return">; +def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">; def : DiagGroup<"attributes">; def : DiagGroup<"bad-function-cast">; +def BoolConversions : DiagGroup<"bool-conversions">; def : DiagGroup<"c++-compat">; def : DiagGroup<"cast-align">; def : DiagGroup<"cast-qual">; @@ -51,6 +54,7 @@ def : DiagGroup<"inline">; def : DiagGroup<"int-to-pointer-cast">; def : DiagGroup<"invalid-pch">; def LiteralRange : DiagGroup<"literal-range">; +def : DiagGroup<"main">; def MissingBraces : DiagGroup<"missing-braces">; def : DiagGroup<"missing-declarations">; def : DiagGroup<"missing-format-attribute">; @@ -62,6 +66,7 @@ def : DiagGroup<"newline-eof">; def LongLong : DiagGroup<"long-long">; def MismatchedTags : DiagGroup<"mismatched-tags">; def MissingFieldInitializers : DiagGroup<"missing-field-initializers">; +def InitializerOverrides : DiagGroup<"initializer-overrides">; def NonNull : DiagGroup<"nonnull">; def : DiagGroup<"nonportable-cfstrings">; def : DiagGroup<"non-virtual-dtor">; @@ -70,13 +75,17 @@ def : DiagGroup<"overflow">; def : DiagGroup<"overloaded-virtual">; def : DiagGroup<"packed">; def PointerArith : DiagGroup<"pointer-arith">; +def PoundWarning : DiagGroup<"#warnings">, + DiagCategory<"#warning Directive">; def : DiagGroup<"pointer-to-int-cast">; def : DiagGroup<"redundant-decls">; def ReturnType : DiagGroup<"return-type">; +def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy">; def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; def : DiagGroup<"sequence-point">; def Shadow : DiagGroup<"shadow">; def : DiagGroup<"shorten-64-to-32">; +def : DiagGroup<"sign-promo">; def SignCompare : DiagGroup<"sign-compare">; def : DiagGroup<"synth">; @@ -108,6 +117,7 @@ def Trigraphs : DiagGroup<"trigraphs">; def : DiagGroup<"type-limits">; def Uninitialized : DiagGroup<"uninitialized">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; +def UnknownAttributes : DiagGroup<"unknown-attributes">; def UnusedArgument : DiagGroup<"unused-argument">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; def UnusedFunction : DiagGroup<"unused-function">; @@ -137,7 +147,7 @@ def Parentheses : DiagGroup<"parentheses", [DiagGroup<"idiomatic-parentheses">]> // -Wconversion has its own warnings, but we split this one out for // legacy reasons. def Conversion : DiagGroup<"conversion", - [DiagGroup<"shorten-64-to-32">]>, + [DiagGroup<"shorten-64-to-32">, BoolConversions]>, DiagCategory<"Value Conversion Issue">; def Unused : DiagGroup<"unused", @@ -157,6 +167,7 @@ def Format2 : DiagGroup<"format=2", def Extra : DiagGroup<"extra", [ MissingFieldInitializers, + InitializerOverrides, SemiBeforeMethodBody, SignCompare, UnusedParameter diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 848e85c..21c93e7 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -106,7 +106,7 @@ def err_invalid_pth_file : Error< //===----------------------------------------------------------------------===// // Preprocessor Diagnostics //===----------------------------------------------------------------------===// -def pp_hash_warning : Warning<"#warning%0">, InGroup<DiagGroup<"#warnings">>; +def pp_hash_warning : Warning<"#warning%0">, InGroup<PoundWarning>; def pp_include_next_in_primary : Warning< "#include_next in primary source file">; def pp_include_macros_out_of_predefines : Error< @@ -225,6 +225,9 @@ def err__Pragma_malformed : Error< "_Pragma takes a parenthesized string literal">; def err_pragma_comment_malformed : Error< "pragma comment requires parenthesized identifier and optional string">; +def err_pragma_message_malformed : Error< + "pragma message requires parenthesized string">; +def warn_pragma_message : Warning<"%0">; def warn_pragma_ignored : Warning<"unknown pragma ignored">, InGroup<UnknownPragmas>, DefaultIgnore; def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 934bd0d..ca761f9 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -24,7 +24,9 @@ def ext_empty_source_file : Extension<"ISO C forbids an empty source file">; def ext_top_level_semi : Extension< "extra ';' outside of a function">; def ext_extra_struct_semi : Extension< - "extra ';' inside a struct or union">; + "extra ';' inside a %0">; +def ext_extra_ivar_semi : Extension< + "extra ';' inside instance variable list">; def ext_duplicate_declspec : Extension<"duplicate '%0' declaration specifier">; def ext_plain_complex : ExtWarn< @@ -35,6 +37,7 @@ def ext_thread_before : Extension<"'__thread' before 'static'">; def ext_empty_struct_union_enum : Extension<"use of empty %0 extension">; +def error_empty_enum : Error<"use of empty enum">; def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; def err_invalid_short_spec : Error<"'short %0' is invalid">; def err_invalid_long_spec : Error<"'long %0' is invalid">; @@ -103,7 +106,7 @@ def err_expected_fn_body : Error< "expected function body after function declarator">; def err_expected_method_body : Error<"expected method body">; def err_invalid_token_after_toplevel_declarator : Error< - "invalid token after top level declarator">; + "expected ';' after top level declarator">; 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">; @@ -168,11 +171,15 @@ def err_typename_invalid_functionspec : Error< def err_invalid_decl_spec_combination : Error< "cannot combine with previous '%0' declaration specifier">; def err_invalid_vector_decl_spec_combination : Error< - "cannot combine with previous '%0' declaration specifier. '__vector' must be first">; + "cannot combine with previous '%0' declaration specifier. " + "'__vector' must be first">; def err_invalid_pixel_decl_spec_combination : Error< - "'__pixel' must be preceded by '__vector'. '%0' declaration specifier not allowed here">; -def err_invalid_vector_double_decl_spec_combination : Error< - "cannot use 'double' with '__vector'">; + "'__pixel' must be preceded by '__vector'. " + "'%0' declaration specifier not allowed here">; +def err_invalid_vector_decl_spec : Error< + "cannot use '%0' with '__vector'">; +def err_invalid_vector_bool_decl_spec : Error< + "cannot use '%0' with '__vector bool'">; def warn_vector_long_decl_spec_combination : Warning< "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>; def err_friend_invalid_in_context : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 0ba31ae..8fac1ed 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -21,12 +21,6 @@ def ext_expr_not_ice : Extension< "expression is not integer constant expression " "(but is allowed as an extension)">; -def ext_null_pointer_expr_not_ice : Extension< - "null pointer expression is not an integer constant expression " - "(but is allowed as an extension)">; - - - // Semantic analysis of constant literals. def ext_predef_outside_function : Warning< "predefined identifier is only valid inside function">; @@ -80,9 +74,10 @@ def err_designator_for_scalar_init : Error< "designator in initializer for scalar type %0">; def warn_subobject_initializer_overrides : Warning< "subobject initialization overrides initialization of other fields " - "within its enclosing subobject">; + "within its enclosing subobject">, InGroup<InitializerOverrides>; def warn_initializer_overrides : Warning< - "initializer overrides prior initialization of this subobject">; + "initializer overrides prior initialization of this subobject">, + InGroup<InitializerOverrides>; def note_previous_initializer : Note< "previous initialization %select{|with side effects }0is here" "%select{| (side effects may not occur at run time)}0">; @@ -125,6 +120,8 @@ def warn_use_out_of_scope_declaration : Warning< "use of out-of-scope declaration of %0">; def err_inline_non_function : Error< "'inline' can only appear on functions">; +def warn_qual_return_type : Warning< + "'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">; def warn_decl_shadow : Warning<"declaration shadows a %select{" @@ -230,6 +227,7 @@ def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 " /// parser diagnostics def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">; +def err_typedef_not_identifier : Error<"typedef name must be an identifier">; def err_statically_allocated_object : Error< "interface type cannot be statically allocated">; def err_object_cannot_be_passed_returned_by_value : Error< @@ -458,6 +456,9 @@ def warn_weak_vtable : Warning< "emitted in every translation unit">, InGroup<DiagGroup<"weak-vtables">>, DefaultIgnore; +def ext_using_undefined_std : ExtWarn< + "using directive refers to implicitly-defined namespace 'std'">; + // C++ exception specifications def err_exception_spec_in_typedef : Error< "exception specifications are not allowed in typedefs">; @@ -486,6 +487,10 @@ def err_access : Error< "%1 is a %select{private|protected}0 member of %3">, NoSFINAE; def err_access_ctor : Error< "calling a %select{private|protected}0 constructor of class %2">, NoSFINAE; +def ext_rvalue_to_reference_access_ctor : ExtWarn< + "C++98 requires an accessible copy constructor for class %2 when binding " + "a reference to a temporary; was %select{private|protected}0">, + NoSFINAE, InGroup<BindToTemporaryCopy>; def err_access_base : Error< "%select{base class|inherited virtual base class}0 %1 has %select{private|" "protected}3 %select{constructor|copy constructor|copy assignment operator|" @@ -507,6 +512,9 @@ def err_access_dtor_vbase : def err_access_dtor_temp : Error<"temporary of type %0 has %select{private|protected}1 destructor">, NoSFINAE; +def err_access_dtor_exception : + Error<"exception object of type %0 has %select{private|protected}1 " + "destructor">, NoSFINAE; def err_access_dtor_field : Error<"field of type %1 has %select{private|protected}2 destructor">, NoSFINAE; @@ -549,6 +557,9 @@ def err_dependent_nested_name_spec : Error< "parameter">; def err_nested_name_member_ref_lookup_ambiguous : Error< "lookup of %0 in member access expression is ambiguous">; +def ext_nested_name_member_ref_lookup_ambiguous : ExtWarn< + "lookup of %0 in member access expression is ambiguous; using member of %1">, + InGroup<AmbigMemberTemplate>; def note_ambig_member_ref_object_type : Note< "lookup in the object type %0 refers here">; def note_ambig_member_ref_scope : Note< @@ -744,6 +755,13 @@ def err_temp_copy_no_viable : Error< "returning object|throwing object|copying member subobject|copying array " "element|allocating object|copying temporary|initializing base subobject|" "initializing vector element}0 of type %1">; +def ext_rvalue_to_reference_temp_copy_no_viable : ExtWarn< + "no viable constructor %select{copying variable|copying parameter|" + "returning object|throwing object|copying member subobject|copying array " + "element|allocating object|copying temporary|initializing base subobject|" + "initializing vector element}0 of type %1; C++98 requires a copy " + "constructor when binding a reference to a temporary">, + InGroup<BindToTemporaryCopy>; def err_temp_copy_ambiguous : Error< "ambiguous constructor call when %select{copying variable|copying " "parameter|returning object|throwing object|copying member subobject|copying " @@ -797,9 +815,15 @@ def err_attribute_wrong_number_arguments : Error< "attribute requires %0 argument(s)">; def err_attribute_missing_parameter_name : Error< "attribute requires unquoted parameter">; -def err_attribute_invalid_vector_type : Error<"invalid vector type %0">; +def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">; def err_attribute_argument_not_int : Error< "'%0' attribute requires integer constant">; +def err_attribute_argument_outof_range : Error< + "init_priority attribute requires integer constant between " + "101 and 65535 inclusive">; +def err_init_priority_object_attr : Error< + "can only use ‘init_priority’ attribute on file-scope definitions " + "of objects of class type">; def err_attribute_argument_n_not_int : Error< "'%0' attribute requires parameter %1 to be an integer constant">; def err_attribute_argument_n_not_string : Error< @@ -838,7 +862,8 @@ def err_attribute_address_space_too_high : Error< def err_attribute_address_multiple_qualifiers : Error< "multiple address spaces specified for type">; def err_implicit_pointer_address_space_cast : Error< - "illegal implicit cast between two pointers with different address spaces">; + "illegal implicit conversion between two pointers with different address " + "spaces">; def err_as_qualified_auto_decl : Error< "automatic variable qualified with an address space">; def err_arg_with_address_space : Error< @@ -854,6 +879,8 @@ def err_attribute_aligned_not_power_of_two : Error< def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< "'%0' redeclared without %1 attribute: previous %1 ignored">; def warn_attribute_ignored : Warning<"%0 attribute ignored">; +def warn_unknown_attribute_ignored : Warning< + "unknown attribute %0 ignored">, InGroup<UnknownAttributes>; def warn_attribute_precede_definition : Warning< "attribute declaration must precede definition">; def warn_attribute_void_function_method : Warning< @@ -899,30 +926,34 @@ def err_cconv_knr : Error< "function with no prototype cannot use %0 calling convention">; def err_cconv_varargs : Error< "variadic function cannot use %0 calling convention">; +def err_regparm_mismatch : Error<"function declared with with regparm(%0) " + "attribute was previously declared %plural{0:without the regparm|1:" + "with the regparm(1)|2:with the regparm(2)|3:with the regparm(3)|:with the" + "regparm}1 attribute">; def warn_impcast_vector_scalar : Warning< - "implicit cast turns vector to scalar: %0 to %1">, + "implicit conversion turns vector to scalar: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_complex_scalar : Warning< - "implicit cast discards imaginary component: %0 to %1">, + "implicit conversion discards imaginary component: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_float_precision : Warning< - "implicit cast loses floating-point precision: %0 to %1">, + "implicit conversion loses floating-point precision: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_float_integer : Warning< - "implicit cast turns floating-point number into integer: %0 to %1">, + "implicit conversion turns floating-point number into integer: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_integer_sign : Warning< - "implicit cast changes signedness: %0 to %1">, + "implicit conversion changes signedness: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_integer_sign_conditional : Warning< "operand of ? changes signedness: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_integer_precision : Warning< - "implicit cast loses integer precision: %0 to %1">, + "implicit conversion loses integer precision: %0 to %1">, InGroup<DiagGroup<"conversion">>, DefaultIgnore; def warn_impcast_integer_64_32 : Warning< - "implicit cast loses integer precision: %0 to %1">, + "implicit conversion loses integer precision: %0 to %1">, InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore; def warn_attribute_ignored_for_field_of_type : Warning< @@ -937,8 +968,8 @@ def warn_transparent_union_attribute_not_definition : Warning< "transparent_union attribute can only be applied to a union definition; " "attribute ignored">; def warn_transparent_union_attribute_floating : Warning< - "first field of a transparent union cannot have floating point or vector " - "type; transparent_union attribute ignored">; + "first field of a transparent union cannot have %select{floating point|" + "vector}0 type %1; transparent_union attribute ignored">; def warn_transparent_union_attribute_zero_fields : Warning< "transparent union definition must contain at least one field; " "transparent_union attribute ignored">; @@ -1077,6 +1108,9 @@ 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">; +def note_ovl_too_many_candidates : Note< + "remaining %0 candidate%s0 omitted; " + "pass -fshow-overloads=all to show them">; def note_ovl_candidate : Note<"candidate " "%select{function|function|constructor|" "function |function |constructor |" @@ -1084,6 +1118,10 @@ def note_ovl_candidate : Note<"candidate " "is the implicit copy constructor|" "is the implicit copy assignment operator}0%1">; +def warn_init_pointer_from_false : Warning< + "initialization of pointer of type %0 from literal 'false'">, + InGroup<BoolConversions>; + def note_ovl_candidate_bad_deduction : Note< "candidate template ignored: failed template argument deduction">; def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: " @@ -1168,6 +1206,17 @@ def note_ovl_candidate_bad_cvr : Note<"candidate " "%select{const|volatile|const and volatile|restrict|const and restrict|" "volatile and restrict|const, volatile, and restrict}3 qualifier" "%select{||s||s|s|s}3">; +def note_ovl_candidate_bad_base_to_derived_conv : 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)}0%1" + " not viable: cannot %select{convert from|convert from|bind}2 " + "%select{base class pointer|superclass|base class object of type}2 %3 to " + "%select{derived class pointer|subclass|derived class reference}2 %4 for " + "%ordinal5 argument">; + def note_ambiguous_type_conversion: Note< "because of ambiguity in conversion of %0 to %1">; def note_ovl_builtin_binary_candidate : Note< @@ -1234,6 +1283,7 @@ def err_template_param_different_kind : Error< "%select{|template parameter }0redeclaration">; def note_template_param_different_kind : Note< "template parameter has a different kind in template argument">; + def err_template_nontype_parm_different_type : Error< "template non-type parameter has a different type %0 in template " "%select{|template parameter }1redeclaration">; @@ -1528,6 +1578,8 @@ def err_explicit_instantiation_nontemplate_type : Error< "explicit instantiation of non-templated type %0">; def note_nontemplate_decl_here : Note< "non-templated declaration is here">; +def err_explicit_instantiation_in_class : Error< + "explicit instantiation of %0 in class scope">; def err_explicit_instantiation_out_of_scope : Error< "explicit instantiation of %0 not in a namespace enclosing %1">; def err_explicit_instantiation_must_be_global : Error< @@ -1560,10 +1612,9 @@ def note_explicit_instantiation_candidate : Note< "explicit instantiation candidate function template here %0">; def err_explicit_instantiation_inline : Error< "explicit instantiation cannot be 'inline'">; -def err_explicit_instantiation_without_qualified_id : Error< - "qualifier in explicit instantiation of %q0 requires a template-id">; -def err_explicit_instantiation_without_qualified_id_quals : Error< - "qualifier in explicit instantiation of '%0%1' requires a template-id">; +def ext_explicit_instantiation_without_qualified_id : ExtWarn< + "qualifier in explicit instantiation of %q0 requires a template-id " + "(a typedef is not permitted)">; def err_explicit_instantiation_unqualified_wrong_namespace : Error< "explicit instantiation of %q0 must occur in %1">; def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning< @@ -1588,6 +1639,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 ext_typename_outside_of_template : ExtWarn< + "'typename' occurs outside of a template">; def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">; @@ -1599,6 +1652,8 @@ def note_referenced_class_template : Error< "class template declared here">; def err_template_kw_missing : Error< "missing 'template' keyword prior to dependent template name '%0%1'">; +def ext_template_outside_of_template : ExtWarn< + "'template' keyword outside of a template">; // C++0x Variadic Templates def err_template_param_pack_default_arg : Error< @@ -1606,6 +1661,18 @@ def err_template_param_pack_default_arg : Error< def err_template_param_pack_must_be_last_template_parameter : Error< "template parameter pack must be the last template parameter">; +def err_template_parameter_pack_non_pack : Error< + "template %select{type|non-type|template}0 parameter%select{| pack}1 " + "conflicts with previous template %select{type|non-type|template}0 " + "parameter%select{ pack|}1">; +def note_template_parameter_pack_non_pack : Note< + "template %select{type|non-type|template}0 parameter%select{| pack}1 " + "does not match template %select{type|non-type|template}0 " + "parameter%select{ pack|}1 in template argument">; +def note_template_parameter_pack_here : Note< + "previous template %select{type|non-type|template}0 " + "parameter%select{| pack}1 declared here">; + def err_unexpected_typedef : Error< "unexpected type name %0: expected expression">; def err_unexpected_namespace : Error< @@ -1674,6 +1741,9 @@ def ext_forward_ref_enum : Extension< "ISO C forbids forward references to 'enum' types">; def err_forward_ref_enum : Error< "ISO C++ forbids forward references to 'enum' types">; +def ext_forward_ref_enum_def : Extension< + "redeclaration of already-defined enum %0 is a GNU extension">, InGroup<GNU>; + def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">; def err_duplicate_member : Error<"duplicate member %0">; def err_misplaced_ivar : Error< @@ -1848,6 +1918,8 @@ def err_illegal_decl_array_of_functions : Error< "'%0' declared as array of functions of type %1">; def err_illegal_decl_array_incomplete_type : Error< "array has incomplete element type %0">; +def err_illegal_message_expr_incomplete_type : Error< + "objective-c message has incomplete result type %0">; def err_illegal_decl_array_of_references : Error< "'%0' declared as array of references of type %1">; def err_array_star_outside_prototype : Error< @@ -2028,6 +2100,11 @@ def err_typecheck_unary_expr : Error< "invalid argument type %0 to unary expression">; def err_typecheck_indirection_requires_pointer : Error< "indirection requires pointer operand (%0 invalid)">; +def warn_indirection_through_null : Warning< + "indirection of non-volatile null pointer will be deleted, not trap">; +def note_indirection_through_null : Note< + "consider using __builtin_trap() or qualifying pointer with 'volatile'">; + def err_indirection_requires_nonfragile_object : Error< "indirection cannot be to an interface in non-fragile ABI (%0 invalid)">; def err_direct_interface_unsupported : Error< @@ -2046,8 +2123,12 @@ def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn< "ordered comparison of function pointers (%0 and %1)">; def ext_typecheck_comparison_of_fptr_to_void : Extension< "equality comparison between function pointer and void pointer (%0 and %1)">; +def err_typecheck_comparison_of_fptr_to_void : Error< + "equality comparison between function pointer and void pointer (%0 and %1)">; def ext_typecheck_comparison_of_pointer_integer : ExtWarn< "comparison between pointer and integer (%0 and %1)">; +def err_typecheck_comparison_of_pointer_integer : Error< + "comparison between pointer and integer (%0 and %1)">; def ext_typecheck_comparison_of_distinct_pointers : ExtWarn< "comparison of distinct pointer types (%0 and %1)">; def ext_typecheck_cond_incompatible_operands : ExtWarn< @@ -2081,9 +2162,11 @@ def err_invalid_member_use_in_static_method : Error< "invalid use of member %0 in static member function">; def err_invalid_qualified_function_type : Error< "type qualifier is not allowed on this function">; +def err_invalid_qualified_function_pointer : Error< + "type qualifier is not allowed on this function %select{pointer|reference}0">; def err_invalid_qualified_typedef_function_type_use : Error< - "a qualified function type cannot be used to declare a nonmember function " - "or a static member function">; + "a qualified function type cannot be used to declare a " + "%select{static member|nonmember}0 function">; def err_invalid_non_static_member_use : Error< "invalid use of nonstatic data member %0">; @@ -2260,13 +2343,26 @@ def err_new_array_nonconst : Error< "only the first dimension of an allocated array may have dynamic size">; def err_new_array_init_args : Error< "array 'new' cannot have initialization arguments">; -def err_new_paren_array_nonconst : Error< +def ext_new_paren_array_nonconst : ExtWarn< "when type is in parentheses, array cannot have dynamic size">; def err_placement_new_non_placement_delete : Error< "'new' expression with placement arguments refers to non-placement " "'operator delete'">; def err_array_size_not_integral : Error< "array size expression must have integral or enumerated type, not %0">; +def err_array_size_incomplete_type : Error< + "array size expression has incomplete class type %0">; +def err_array_size_explicit_conversion : Error< + "array size expression of type %0 requires explicit conversion to type %1">; +def note_array_size_conversion : Note< + "conversion to %select{integral|enumeration}0 type %1 declared here">; +def err_array_size_ambiguous_conversion : Error< + "ambiguous conversion of array size expression of type %0 to an integral or " + "enumeration type">; +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">; + def err_default_init_const : Error< "default initialization of an object of const type %0" "%select{| requires a user-provided default constructor}1">; @@ -2866,11 +2962,17 @@ def warn_printf_asterisk_missing_arg : Warning< def warn_printf_asterisk_wrong_type : Warning< "field %select{width|precision}0 should have type %1, but argument has type %2">, InGroup<Format>; -def warn_printf_nonsensical_precision: Warning< - "precision used in '%0' conversion specifier (where it has no meaning)">, +def warn_printf_nonsensical_optional_amount: Warning< + "%select{field width|precision}0 used with '%1' conversion specifier, resulting in undefined behavior">, InGroup<Format>; def warn_printf_nonsensical_flag: Warning< - "flag '%0' results in undefined behavior in '%1' conversion specifier">, + "flag '%0' results in undefined behavior with '%1' conversion specifier">, + InGroup<Format>; +def warn_printf_nonsensical_length: Warning< + "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">, + InGroup<Format>; +def warn_printf_ignored_flag: Warning< + "flag '%0' is ignored when flag '%1' is present">, InGroup<Format>; // CHECK: returning address/reference of stack memory @@ -2886,8 +2988,10 @@ def err_ret_local_block : Error< // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. -def warn_selfcomparison : Warning< - "self-comparison always results in a constant value">; +// Array comparisons have similar warnings +def warn_comparison_always : Warning< + "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">; + def warn_stringcompare : Warning< "result of comparison against %select{a string literal|@encode}0 is " "unspecified (use strncmp instead)">; @@ -2956,13 +3060,13 @@ def err_first_argument_to_va_arg_not_of_type_va_list : Error< "first argument to 'va_arg' is of type %0 and not 'va_list'">; def warn_return_missing_expr : Warning< - "non-void %select{function|method}1 %0 should return a value">, + "non-void %select{function|method}1 %0 should return a value">, DefaultError, InGroup<ReturnType>; def ext_return_missing_expr : ExtWarn< - "non-void %select{function|method}1 %0 should return a value">, + "non-void %select{function|method}1 %0 should return a value">, DefaultError, InGroup<ReturnType>; def ext_return_has_expr : ExtWarn< - "void %select{function|method}1 %0 should not return a value">, + "void %select{function|method}1 %0 should not return a value">, DefaultError, InGroup<ReturnType>; def ext_return_has_void_expr : Extension< "void %select{function|method}1 %0 should not return void expression">; @@ -2993,6 +3097,8 @@ def err_vector_incorrect_num_initializers : Error< "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; +def err_invalid_neon_type_code : Error< + "incompatible constant for this __builtin_neon function">; def err_argument_invalid_range : Error< "argument should be a value from %0 to %1">; @@ -3003,7 +3109,9 @@ def err_constant_integer_arg_type : Error< "argument to %0 must be a constant integer">; def ext_mixed_decls_code : Extension< - "ISO C90 forbids mixing declarations and code">; + "ISO C90 forbids mixing declarations and code">, + InGroup<DiagGroup<"declaration-after-statement">>; + def err_non_variable_decl_in_for : Error< "declaration of non-local variable in 'for' loop">; def err_toomany_element_decls : Error< @@ -3094,6 +3202,11 @@ def err_undeclared_protocol_suggest : Error< "cannot find protocol declaration for %0; did you mean %1?">; def note_base_class_specified_here : Note< "base class %0 specified here">; +def err_using_directive_suggest : Error< + "no namespace named %0; did you mean %1?">; +def err_using_directive_member_suggest : Error< + "no namespace named %0 in %1; did you mean %2?">; +def note_namespace_defined_here : Note<"namespace %0 defined here">; } // end of sema category } // end of sema component. diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 582d59c..6b8bcdc 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -89,7 +89,8 @@ public: // The 'this' pointer really points to a // std::pair<IdentifierInfo, const char*>, where internal pointer // points to the external string data. - return ((std::pair<IdentifierInfo, const char*>*) this)->second; + typedef std::pair<IdentifierInfo, const char*> actualtype; + return ((const actualtype*) this)->second; } /// getLength - Efficiently return the length of this identifier info. @@ -101,7 +102,8 @@ public: // The 'this' pointer really points to a // std::pair<IdentifierInfo, const char*>, where internal pointer // points to the external string data. - const char* p = ((std::pair<IdentifierInfo, const char*>*) this)->second-2; + typedef std::pair<IdentifierInfo, const char*> actualtype; + const char* p = ((const actualtype*) this)->second - 2; return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; } diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 1ed86f1..bbcceb7 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -66,9 +66,6 @@ public: unsigned MathErrno : 1; // Math functions must respect errno // (modulo the platform support). - unsigned OverflowChecking : 1; // Extension to call a handler function when - // signed integer arithmetic overflows. - unsigned HeinousExtensions : 1; // Extensions that we really don't like and // may be ripped out at any time. @@ -102,20 +99,21 @@ public: unsigned DumpRecordLayouts : 1; /// Dump the layout of IRgen'd records. unsigned DumpVTableLayouts : 1; /// Dump the layouts of emitted vtables. unsigned NoConstantCFStrings : 1; // Do not do CF strings + unsigned InlineVisibilityHidden : 1; // Whether inline C++ methods have + // hidden visibility by default. + unsigned SpellChecking : 1; // Whether to perform spell-checking for error + // recovery. // FIXME: This is just a temporary option, for testing purposes. unsigned NoBitFieldTypeAlign : 1; private: - unsigned GC : 2; // Objective-C Garbage Collection modes. We - // declare this enum as unsigned because MSVC - // insists on making enums signed. Set/Query - // this value using accessors. + // We declare multibit enums as unsigned because MSVC insists on making enums + // signed. Set/Query these values using accessors. + unsigned GC : 2; // Objective-C Garbage Collection modes. unsigned SymbolVisibility : 3; // Symbol's visibility. - unsigned StackProtector : 2; // Whether stack protectors are on. We declare - // this enum as unsigned because MSVC insists - // on making enums signed. Set/Query this - // value using accessors. + unsigned StackProtector : 2; // Whether stack protectors are on. + unsigned SignedOverflowBehavior : 2; // How to handle signed integer overflow. public: unsigned InstantiationDepth; // Maximum template instantiation depth. @@ -129,13 +127,19 @@ public: Protected, Hidden }; + + enum SignedOverflowBehaviorTy { + SOB_Undefined, // Default C standard behavior. + SOB_Defined, // -fwrapv + SOB_Trapping // -ftrapv + }; LangOptions() { Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0; GNUMode = GNUKeywords = ImplicitInt = Digraphs = 0; HexFloats = 0; GC = ObjC1 = ObjC2 = ObjCNonFragileABI = ObjCNonFragileABI2 = 0; - NoConstantCFStrings = 0; + NoConstantCFStrings = 0; InlineVisibilityHidden = 0; C99 = Microsoft = CPlusPlus = CPlusPlus0x = 0; CXXOperatorNames = PascalStrings = WritableStrings = ConstStrings = 0; Exceptions = SjLjExceptions = Freestanding = NoBuiltin = 0; @@ -146,20 +150,19 @@ public: AltiVec = OpenCL = StackProtector = 0; SymbolVisibility = (unsigned) Default; - + ThreadsafeStatics = 1; POSIXThreads = 0; Blocks = 0; EmitAllDecls = 0; MathErrno = 1; - + SignedOverflowBehavior = SOB_Undefined; + AssumeSaneOperatorNew = 1; - - // FIXME: The default should be 1. - AccessControl = 0; + AccessControl = 1; ElideConstructors = 1; - OverflowChecking = 0; + SignedOverflowBehavior = 0; ObjCGCBitmapPrint = 0; InstantiationDepth = 1024; @@ -178,6 +181,7 @@ public: CatchUndefined = 0; DumpRecordLayouts = 0; DumpVTableLayouts = 0; + SpellChecking = 1; NoBitFieldTypeAlign = 0; } @@ -195,6 +199,13 @@ public: return (VisibilityMode) SymbolVisibility; } void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; } + + SignedOverflowBehaviorTy getSignedOverflowBehavior() const { + return (SignedOverflowBehaviorTy)SignedOverflowBehavior; + } + void setSignedOverflowBehavior(SignedOverflowBehaviorTy V) { + SignedOverflowBehavior = (unsigned)V; + } }; } // end namespace clang diff --git a/include/clang/Basic/Makefile b/include/clang/Basic/Makefile index 48f7f9d..7db3e29 100644 --- a/include/clang/Basic/Makefile +++ b/include/clang/Basic/Makefile @@ -1,16 +1,33 @@ -LEVEL = ../../../../.. -BUILT_SOURCES = DiagnosticAnalysisKinds.inc DiagnosticASTKinds.inc \ +CLANG_LEVEL := ../../.. +BUILT_SOURCES = \ + DiagnosticAnalysisKinds.inc DiagnosticASTKinds.inc \ DiagnosticCommonKinds.inc DiagnosticDriverKinds.inc \ DiagnosticFrontendKinds.inc DiagnosticLexKinds.inc \ DiagnosticParseKinds.inc DiagnosticSemaKinds.inc \ - DiagnosticGroups.inc + DiagnosticGroups.inc AttrList.inc arm_neon.inc \ + Version.inc TABLEGEN_INC_FILES_COMMON = 1 -include $(LEVEL)/Makefile.common +include $(CLANG_LEVEL)/Makefile INPUT_TDS = $(wildcard $(PROJ_SRC_DIR)/Diagnostic*.td) +# Compute the Clang version from the LLVM version, unless specified explicitly. +ifndef CLANG_VERSION +CLANG_VERSION := $(subst svn,,$(LLVMVersion)) +endif + +CLANG_VERSION_COMPONENTS := $(subst ., ,$(CLANG_VERSION)) +CLANG_VERSION_MAJOR := $(word 1,$(CLANG_VERSION_COMPONENTS)) +CLANG_VERSION_MINOR := $(word 2,$(CLANG_VERSION_COMPONENTS)) +CLANG_VERSION_PATCHLEVEL := $(word 3,$(CLANG_VERSION_COMPONENTS)) +ifeq ($(CLANG_VERSION_PATCHLEVEL),) +CLANG_HAS_VERSION_PATCHLEVEL := 0 +else +CLANG_HAS_VERSION_PATCHLEVEL := 1 +endif + $(ObjDir)/Diagnostic%Kinds.inc.tmp : Diagnostic.td Diagnostic%Kinds.td $(TBLGEN) $(ObjDir)/.dir $(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, $@) $< @@ -19,4 +36,20 @@ $(ObjDir)/DiagnosticGroups.inc.tmp : Diagnostic.td DiagnosticGroups.td $(INPUT_T $(Echo) "Building Clang diagnostic groups with tblgen" $(Verb) $(TableGen) -gen-clang-diag-groups -o $(call SYSPATH, $@) $< +$(ObjDir)/AttrList.inc.tmp : Attr.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang attribute list with tblgen" + $(Verb) $(TableGen) -gen-clang-attr-list -o $(call SYSPATH, $@) \ + -I $(PROJ_SRC_DIR)/../.. $< + +$(ObjDir)/arm_neon.inc.tmp : arm_neon.td $(TBLGEN) $(ObjDir)/.dir + $(Echo) "Building Clang arm_neon.inc with tblgen" + $(Verb) $(TableGen) -gen-arm-neon-sema -o $(call SYSPATH, $@) $< +$(ObjDir)/Version.inc.tmp : Version.inc.in Makefile $(LLVM_OBJ_ROOT)/Makefile.config $(ObjDir)/.dir + $(Echo) "Updating Clang version info." + $(Verb)sed -e "s#@CLANG_VERSION@#$(CLANG_VERSION)#g" \ + -e "s#@CLANG_VERSION_MAJOR@#$(CLANG_VERSION_MAJOR)#g" \ + -e "s#@CLANG_VERSION_MINOR@#$(CLANG_VERSION_MINOR)#g" \ + -e "s#@CLANG_VERSION_PATCHLEVEL@#$(CLANG_VERSION_PATCHLEVEL)#g" \ + -e "s#@CLANG_HAS_VERSION_PATCHLEVEL@#$(CLANG_HAS_VERSION_PATCHLEVEL)#g" \ + $< > $@ diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index 89fae87..cd0da97 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -59,7 +59,7 @@ public: /// DiagRanges - The list of ranges added to this diagnostic. It currently /// only support 10 ranges, could easily be extended if needed. - SourceRange DiagRanges[10]; + CharSourceRange DiagRanges[10]; enum { MaxFixItHints = 3 }; @@ -142,7 +142,7 @@ private: DiagStorage = 0; } - void AddSourceRange(const SourceRange &R) const { + void AddSourceRange(const CharSourceRange &R) const { if (!DiagStorage) DiagStorage = getStorage(); @@ -264,10 +264,16 @@ public: friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, const SourceRange &R) { - PD.AddSourceRange(R); + PD.AddSourceRange(CharSourceRange::getTokenRange(R)); return PD; } + friend inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, + const CharSourceRange &R) { + PD.AddSourceRange(R); + return PD; + } + friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, const FixItHint &Hint) { PD.AddFixItHint(Hint); diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index 0bbeffe..35f27fb 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -172,6 +172,56 @@ public: return B != X.B || E != X.E; } }; + +/// CharSourceRange - This class represents a character granular source range. +/// The underlying SourceRange can either specify the starting/ending character +/// of the range, or it can specify the start or the range and the start of the +/// last token of the range (a "token range"). In the token range case, the +/// size of the last token must be measured to determine the actual end of the +/// range. +class CharSourceRange { + SourceRange Range; + bool IsTokenRange; +public: + CharSourceRange() : IsTokenRange(false) {} + CharSourceRange(SourceRange R, bool ITR) : Range(R),IsTokenRange(ITR){} + + static CharSourceRange getTokenRange(SourceRange R) { + CharSourceRange Result; + Result.Range = R; + Result.IsTokenRange = true; + return Result; + } + + static CharSourceRange getCharRange(SourceRange R) { + CharSourceRange Result; + Result.Range = R; + Result.IsTokenRange = false; + return Result; + } + + static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { + return getTokenRange(SourceRange(B, E)); + } + static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) { + return getCharRange(SourceRange(B, E)); + } + + /// isTokenRange - Return true if the end of this range specifies the start of + /// the last token. Return false if the end of this range specifies the last + /// character in the range. + bool isTokenRange() const { return IsTokenRange; } + + SourceLocation getBegin() const { return Range.getBegin(); } + SourceLocation getEnd() const { return Range.getEnd(); } + const SourceRange &getAsRange() const { return Range; } + + void setBegin(SourceLocation b) { Range.setBegin(b); } + void setEnd(SourceLocation e) { Range.setEnd(e); } + + bool isValid() const { return Range.isValid(); } + bool isInvalid() const { return !isValid(); } +}; /// FullSourceLoc - A SourceLocation and its associated SourceManager. Useful /// for argument passing to functions that expect both objects. diff --git a/include/clang/AST/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 60c94a6..a2f6973 100644 --- a/include/clang/AST/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -1,4 +1,6 @@ -class Stmt<bit abstract = 0> { +class AttrSubject; + +class Stmt<bit abstract = 0> : AttrSubject { bit Abstract = abstract; } @@ -93,11 +95,10 @@ def CXXNullPtrLiteralExpr : DStmt<Expr>; def CXXThisExpr : DStmt<Expr>; def CXXThrowExpr : DStmt<Expr>; def CXXDefaultArgExpr : DStmt<Expr>; -def CXXZeroInitValueExpr : DStmt<Expr>; +def CXXScalarValueInitExpr : DStmt<Expr>; def CXXNewExpr : DStmt<Expr>; def CXXDeleteExpr : DStmt<Expr>; def CXXPseudoDestructorExpr : DStmt<Expr>; -def UnresolvedLookupExpr : DStmt<Expr>; def UnaryTypeTraitExpr : DStmt<Expr>; def DependentScopeDeclRefExpr : DStmt<Expr>; def CXXConstructExpr : DStmt<Expr>; @@ -107,7 +108,9 @@ def CXXExprWithTemporaries : DStmt<Expr>; def CXXTemporaryObjectExpr : DStmt<CXXConstructExpr>; def CXXUnresolvedConstructExpr : DStmt<Expr>; def CXXDependentScopeMemberExpr : DStmt<Expr>; -def UnresolvedMemberExpr : DStmt<Expr>; +def OverloadExpr : DStmt<Expr, 1>; +def UnresolvedLookupExpr : DStmt<OverloadExpr>; +def UnresolvedMemberExpr : DStmt<OverloadExpr>; // Obj-C Expressions. def ObjCStringLiteral : DStmt<Expr>; diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 00fd9b9..5763a12 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -51,12 +51,14 @@ protected: unsigned char FloatWidth, FloatAlign; unsigned char DoubleWidth, DoubleAlign; unsigned char LongDoubleWidth, LongDoubleAlign; + unsigned char LargeArrayMinWidth, LargeArrayAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; const char *DescriptionString; const char *UserLabelPrefix; const llvm::fltSemantics *FloatFormat, *DoubleFormat, *LongDoubleFormat; unsigned char RegParmMax, SSERegParmMax; + std::string CXXABI; unsigned HasAlignMac68kSupport : 1; @@ -194,6 +196,11 @@ public: return *LongDoubleFormat; } + // getLargeArrayMinWidth/Align - Return the minimum array size that is + // 'large' and its alignment. + unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; } + unsigned getLargeArrayAlign() const { return LargeArrayAlign; } + /// getIntMaxTWidth - Return the size of intmax_t and uintmax_t for this /// target, in bits. unsigned getIntMaxTWidth() const { @@ -390,6 +397,11 @@ public: return ""; } + /// getCXXABI - Get the C++ ABI in use. + virtual llvm::StringRef getCXXABI() const { + return CXXABI; + } + /// setCPU - Target the specific CPU. /// /// \return - False on error (invalid CPU name). @@ -406,6 +418,16 @@ public: return false; } + /// setCXXABI - Use this specific C++ ABI. + /// + /// \return - False on error (invalid ABI name). + virtual bool setCXXABI(const std::string &Name) { + if (Name != "itanium" && Name != "microsoft") + return false; + CXXABI = Name; + return true; + } + /// setFeatureEnabled - Enable or disable a specific target feature, /// the feature name must be valid. /// @@ -450,7 +472,12 @@ public: return -1; } - + /// getStaticInitSectionSpecifier - Return the section to use for C++ static + /// initialization functions. + virtual const char *getStaticInitSectionSpecifier() const { + return 0; + } + protected: virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return PointerWidth; diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index eeaab15..19b0cbb 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -19,6 +19,10 @@ namespace clang { class TargetOptions { public: + TargetOptions() { + CXXABI = "itanium"; + } + /// If given, the name of the target triple to compile for. If not given the /// target will be selected to match the host. std::string Triple; @@ -29,6 +33,10 @@ public: /// If given, the name of the target ABI to use. std::string ABI; + /// If given, the name of the target C++ ABI to use. If not given, defaults + /// to "itanium". + std::string CXXABI; + /// The list of target specific features to enable or disable -- this should /// be a list of strings starting with by '+' or '-'. std::vector<std::string> Features; diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h index b3b6184..9948677 100644 --- a/include/clang/Basic/Version.h +++ b/include/clang/Basic/Version.h @@ -17,15 +17,7 @@ #include "llvm/ADT/StringRef.h" -/// \brief Clang major version -#define CLANG_VERSION_MAJOR 2 - -// FIXME: Updates to this file must also update CMakeLists.txt and VER. -/// \brief Clang minor version -#define CLANG_VERSION_MINOR 0 - -/// \brief Clang patchlevel version -// #define CLANG_VERSION_PATCHLEVEL 1 +#include "clang/Basic/Version.inc" /// \brief Helper macro for CLANG_VERSION_STRING. #define CLANG_MAKE_VERSION_STRING2(X) #X diff --git a/include/clang/Basic/Version.inc.in b/include/clang/Basic/Version.inc.in new file mode 100644 index 0000000..ccf8430 --- /dev/null +++ b/include/clang/Basic/Version.inc.in @@ -0,0 +1,6 @@ +#define CLANG_VERSION @CLANG_VERSION@ +#define CLANG_VERSION_MAJOR @CLANG_VERSION_MAJOR@ +#define CLANG_VERSION_MINOR @CLANG_VERSION_MINOR@ +#if @CLANG_HAS_VERSION_PATCHLEVEL@ +#define CLANG_VERSION_PATCHLEVEL @CLANG_VERSION_PATCHLEVEL@ +#endif diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td new file mode 100644 index 0000000..b42755c --- /dev/null +++ b/include/clang/Basic/arm_neon.td @@ -0,0 +1,341 @@ +//===--- arm_neon.td - ARM NEON compiler interface ------------------------===// +// +// 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 TableGen definitions from which the ARM NEON header +// file will be generated. See ARM document DUI0348B. +// +//===----------------------------------------------------------------------===// + +class Op; + +def OP_NONE : Op; +def OP_ADD : Op; +def OP_SUB : Op; +def OP_MUL : Op; +def OP_MLA : Op; +def OP_MLS : Op; +def OP_MUL_N : Op; +def OP_MLA_N : Op; +def OP_MLS_N : Op; +def OP_EQ : Op; +def OP_GE : Op; +def OP_LE : Op; +def OP_GT : Op; +def OP_LT : Op; +def OP_NEG : Op; +def OP_NOT : Op; +def OP_AND : Op; +def OP_OR : Op; +def OP_XOR : Op; +def OP_ANDN : Op; +def OP_ORN : Op; +def OP_CAST : Op; +def OP_HI : Op; +def OP_LO : Op; +def OP_CONC : Op; +def OP_DUP : Op; +def OP_SEL : Op; +def OP_REV64 : Op; +def OP_REV32 : Op; +def OP_REV16 : Op; + +class Inst <string p, string t, Op o> { + string Prototype = p; + string Types = t; + Op Operand = o; + bit isShift = 0; +} + +// Used to generate Builtins.def +class SInst<string p, string t> : Inst<p, t, OP_NONE> {} +class IInst<string p, string t> : Inst<p, t, OP_NONE> {} +class WInst<string p, string t> : Inst<p, t, OP_NONE> {} + +// prototype: return (arg, arg, ...) +// v: void +// t: best-fit integer (int/poly args) +// x: signed integer (int/float args) +// u: unsigned integer (int/float args) +// f: float (int args) +// d: default +// w: double width elements, same num elts +// n: double width elements, half num elts +// h: half width elements, double num elts +// e: half width elements, double num elts, unsigned +// i: constant int +// l: constant uint64 +// s: scalar of element type +// a: scalar of element type (splat to vector type) +// k: default elt width, double num elts +// #: array of default vectors +// p: pointer type +// c: const pointer type + +// sizes: +// c: char +// s: short +// i: int +// l: long +// f: float +// h: half-float + +// size modifiers: +// U: unsigned +// Q: 128b +// P: polynomial + +//////////////////////////////////////////////////////////////////////////////// +// E.3.1 Addition +def VADD : Inst<"ddd", "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_ADD>; +def VADDL : SInst<"wdd", "csiUcUsUi">; +def VADDW : SInst<"wwd", "csiUcUsUi">; +def VHADD : SInst<"ddd", "csiUcUsUiQcQsQiQUcQUsQUi">; +def VRHADD : SInst<"ddd", "csiUcUsUiQcQsQiQUcQUsQUi">; +def VQADD : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VADDHN : IInst<"dww", "csiUcUsUi">; +def VRADDHN : IInst<"dww", "csiUcUsUi">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.2 Multiplication +def VMUL : Inst<"ddd", "csifUcUsUiPcQcQsQiQfQUcQUsQUiQPc", OP_MUL>; +def VMLA : Inst<"dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLA>; +def VMLAL : SInst<"wwdd", "csiUcUsUi">; +def VMLS : Inst<"dddd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_MLS>; +def VMLSL : SInst<"wwdd", "csiUcUsUi">; +def VQDMULH : SInst<"ddd", "siQsQi">; +def VQRDMULH : SInst<"ddd", "siQsQi">; +def VQDMLAL : SInst<"wwdd", "si">; +def VQDMLSL : SInst<"wwdd", "si">; +def VMULL : SInst<"wdd", "csiUcUsUiPc">; +def VQDMULL : SInst<"wdd", "si">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.3 Subtraction +def VSUB : Inst<"ddd", "csilfUcUsUiUlQcQsQiQlQfQUcQUsQUiQUl", OP_SUB>; +def VSUBL : SInst<"wdd", "csiUcUsUi">; +def VSUBW : SInst<"wwd", "csiUcUsUi">; +def VQSUB : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VHSUB : SInst<"ddd", "csiUcUsUiQcQsQiQUcQUsQUi">; +def VSUBHN : IInst<"dww", "csiUcUsUi">; +def VRSUBHN : IInst<"dww", "csiUcUsUi">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.4 Comparison +def VCEQ : Inst<"udd", "csifUcUsUiPcQcQsQiQfQUcQUsQUiQPc", OP_EQ>; +def VCGE : Inst<"udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GE>; +def VCLE : Inst<"udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LE>; +def VCGT : Inst<"udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_GT>; +def VCLT : Inst<"udd", "csifUcUsUiQcQsQiQfQUcQUsQUi", OP_LT>; +def VCAGE : IInst<"udd", "fQf">; +def VCALE : IInst<"udd", "fQf">; +def VCAGT : IInst<"udd", "fQf">; +def VCALT : IInst<"udd", "fQf">; +def VTST : WInst<"udd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.5 Absolute Difference +def VABD : SInst<"ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">; +def VABDL : SInst<"wdd", "csiUcUsUi">; +def VABA : SInst<"dddd", "csiUcUsUiQcQsQiQUcQUsQUi">; +def VABAL : SInst<"wwdd", "csiUcUsUi">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.6 Max/Min +def VMAX : SInst<"ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">; +def VMIN : SInst<"ddd", "csiUcUsUifQcQsQiQUcQUsQUiQf">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.7 Pairdise Addition +def VPADD : IInst<"ddd", "csiUcUsUif">; +def VPADDL : SInst<"nd", "csiUcUsUiQcQsQiQUcQUsQUi">; +def VPADAL : SInst<"nnd", "csiUcUsUiQcQsQiQUcQUsQUi">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.8-9 Folding Max/Min +def VPMAX : SInst<"ddd", "csiUcUsUif">; +def VPMIN : SInst<"ddd", "csiUcUsUif">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.10 Reciprocal/Sqrt +def VRECPS : IInst<"ddd", "fQf">; +def VRSQRTS : IInst<"ddd", "fQf">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.11 Shifts by signed variable +def VSHL : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VQSHL : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VRSHL : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VQRSHL : SInst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.12 Shifts by constant +let isShift = 1 in { +def VSHR_N : SInst<"ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VSHL_N : IInst<"ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VRSHR_N : SInst<"ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VSRA_N : SInst<"dddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VRSRA_N : SInst<"dddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VQSHL_N : SInst<"ddi", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl">; +def VQSHLU_N : SInst<"udi", "csilQcQsQiQl">; +def VSHRN_N : IInst<"hki", "silUsUiUl">; +def VQSHRUN_N : SInst<"eki", "sil">; +def VQRSHRUN_N : SInst<"eki", "sil">; +def VQSHRN_N : SInst<"hki", "silUsUiUl">; +def VRSHRN_N : IInst<"hki", "silUsUiUl">; +def VQRSHRN_N : SInst<"hki", "silUsUiUl">; +def VSHLL_N : SInst<"wdi", "csiUcUsUi">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.13 Shifts with insert +def VSRI_N : WInst<"dddi", "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPs">; +def VSLI_N : WInst<"dddi", "csilUcUsUiUlPcPsQcQsQiQlQUcQUsQUiQUlQPcQPs">; +} + +//////////////////////////////////////////////////////////////////////////////// +// E.3.14 Loads and stores of a single vector +def VLD1 : WInst<"dc", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VLD1_LANE : WInst<"dcdi", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VLD1_DUP : WInst<"dc", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VST1 : WInst<"vpd", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VST1_LANE : WInst<"vpdi", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.15 Loads and stores of an N-element structure +def VLD2 : WInst<"2c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VLD3 : WInst<"3c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VLD4 : WInst<"4c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VLD2_DUP : WInst<"2c", "UcUsUiUlcsilhfPcPs">; +def VLD3_DUP : WInst<"3c", "UcUsUiUlcsilhfPcPs">; +def VLD4_DUP : WInst<"4c", "UcUsUiUlcsilhfPcPs">; +def VLD2_LANE : WInst<"2c2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; +def VLD3_LANE : WInst<"3c3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; +def VLD4_LANE : WInst<"4c4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; +def VST2 : WInst<"vp2", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VST3 : WInst<"vp3", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VST4 : WInst<"vp4", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VST2_LANE : WInst<"vp2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; +def VST3_LANE : WInst<"vp3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; +def VST4_LANE : WInst<"vp4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.16 Extract lanes from a vector +def VGET_LANE : IInst<"sdi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.17 Set lanes within a vector +def VSET_LANE : IInst<"dsdi", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.18 Initialize a vector from bit pattern +def VCREATE: Inst<"dl", "csihfUcUsUiUlPcPsl", OP_CAST>; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.19 Set all lanes to same value +def VDUP_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; +def VMOV_N : Inst<"ds", "UcUsUicsiPcPsfQUcQUsQUiQcQsQiQPcQPsQflUlQlQUl", OP_DUP>; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.20 Combining vectors +def VCOMBINE : Inst<"kdd", "csilhfUcUsUiUlPcPs", OP_CONC>; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.21 Splitting vectors +def VGET_HIGH : Inst<"dk", "csilhfUcUsUiUlPcPs", OP_HI>; +def VGET_LOW : Inst<"dk", "csilhfUcUsUiUlPcPs", OP_LO>; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.22 Converting vectors +def VCVT_S32 : SInst<"xd", "fQf">; +def VCVT_U32 : SInst<"ud", "fQf">; +def VCVT_F16 : SInst<"hk", "f">; +def VCVT_N_S32 : SInst<"xdi", "fQf">; +def VCVT_N_U32 : SInst<"udi", "fQf">; +def VCVT_F32 : SInst<"fd", "iUiQiQUi">; +def VCVT_F32_F16 : SInst<"kh", "f">; +def VCVT_N_F32 : SInst<"fdi", "iUiQiQUi">; +def VMOVN : IInst<"hk", "silUsUiUl">; +def VMOVL : SInst<"wd", "csiUcUsUi">; +def VQMOVN : SInst<"hk", "silUsUiUl">; +def VQMOVUN : SInst<"ek", "sil">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.23-24 Table lookup, Extended table lookup +def VTBL1 : WInst<"ddt", "UccPc">; +def VTBL2 : WInst<"d2t", "UccPc">; +def VTBL3 : WInst<"d3t", "UccPc">; +def VTBL4 : WInst<"d4t", "UccPc">; +def VTBX1 : WInst<"dddt", "UccPc">; +def VTBX2 : WInst<"dd2t", "UccPc">; +def VTBX3 : WInst<"dd3t", "UccPc">; +def VTBX4 : WInst<"dd4t", "UccPc">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.25 Operations with a scalar value +def VMLA_LANE : IInst<"ddddi", "siUsUifQsQiQUsQUiQf">; +def VMLAL_LANE : SInst<"wwddi", "siUsUi">; +def VQDMLAL_LANE : SInst<"wwddi", "si">; +def VMLS_LANE : IInst<"ddddi", "siUsUifQsQiQUsQUiQf">; +def VMLSL_LANE : SInst<"wwddi", "siUsUi">; +def VQDMLSL_LANE : SInst<"wwddi", "si">; +def VMUL_N : Inst<"dds", "sifUsUiQsQiQfQUsQUi", OP_MUL_N>; +def VMULL_N : SInst<"wda", "siUsUi">; +def VMULL_LANE : SInst<"wddi", "siUsUi">; +def VQDMULL_N : SInst<"wda", "si">; +def VQDMULL_LANE : SInst<"wddi", "si">; +def VQDMULH_N : SInst<"dda", "siQsQi">; +def VQDMULH_LANE : SInst<"dddi", "siQsQi">; +def VQRDMULH_N : SInst<"dda", "siQsQi">; +def VQRDMULH_LANE : SInst<"dddi", "siQsQi">; +def VMLA_N : Inst<"ddda", "siUsUifQsQiQUsQUiQf", OP_MLA_N>; +def VMLAL_N : SInst<"wwda", "siUsUi">; +def VQDMLAL_N : SInst<"wwda", "si">; +def VMLS_N : Inst<"ddds", "siUsUifQsQiQUsQUiQf", OP_MLS_N>; +def VMLSL_N : SInst<"wwda", "siUsUi">; +def VQDMLSL_N : SInst<"wwda", "si">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.26 Vector Extract +def VEXT : WInst<"dddi", "cUcPcsUsPsiUilUlQcQUcQPcQsQUsQPsQiQUiQlQUl">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.27 Reverse vector elements (sdap endianness) +def VREV64 : Inst<"dd", "csiUcUsUiPcPsfQcQsQiQUcQUsQUiQPcQPsQf", OP_REV64>; +def VREV32 : Inst<"dd", "csUcUsPcQcQsQUcQUsQPc", OP_REV32>; +def VREV16 : Inst<"dd", "cUcPcQcQUcQPc", OP_REV16>; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.28 Other single operand arithmetic +def VABS : SInst<"dd", "csifQcQsQiQf">; +def VQABS : SInst<"dd", "csiQcQsQi">; +def VNEG : Inst<"dd", "csifQcQsQiQf", OP_NEG>; +def VQNEG : SInst<"dd", "csiQcQsQi">; +def VCLS : SInst<"dd", "csiQcQsQi">; +def VCLZ : IInst<"dd", "csiUcUsUiQcQsQiQUcQUsQUi">; +def VCNT : WInst<"dd", "UccPcQUcQcQPc">; +def VRECPE : SInst<"dd", "fUiQfQUi">; +def VRSQRTE : SInst<"dd", "fUiQfQUi">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.29 Logical operations +def VMVN : Inst<"dd", "csiUcUsUiPcQcQsQiQUcQUsQUiQPc", OP_NOT>; +def VAND : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_AND>; +def VORR : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_OR>; +def VEOR : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_XOR>; +def VBIC : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ANDN>; +def VORN : Inst<"ddd", "csilUcUsUiUlQcQsQiQlQUcQUsQUiQUl", OP_ORN>; +def VBSL : Inst<"dudd", "csilUcUsUiUlfPcPsQcQsQiQlQUcQUsQUiQUlQfQPcQPs", OP_SEL>; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.30 Transposition operations +def VTRN: WInst<"2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">; +def VZIP: WInst<"2dd", "csUcUsfPcPsQcQsQiQUcQUsQUiQfQPcQPs">; +def VUZP: WInst<"2dd", "csiUcUsUifPcPsQcQsQiQUcQUsQUiQfQPcQPs">; + +//////////////////////////////////////////////////////////////////////////////// +// E.3.31 Vector reinterpret cast operations diff --git a/include/clang/Checker/AnalysisConsumer.h b/include/clang/Checker/AnalysisConsumer.h new file mode 100644 index 0000000..c236766 --- /dev/null +++ b/include/clang/Checker/AnalysisConsumer.h @@ -0,0 +1,35 @@ +//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains the functions necessary for a front-end to run various +// analyses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CHECKER_ANALYSISCONSUMER_H +#define LLVM_CLANG_CHECKER_ANALYSISCONSUMER_H + +#include <string> + +namespace clang { + +class AnalyzerOptions; +class ASTConsumer; +class Preprocessor; + +/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code +/// analysis passes. (The set of analyses run is controlled by command-line +/// options.) +ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp, + const std::string &output, + const AnalyzerOptions& Opts); + +} + +#endif diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h index 5b65d52..3749b43 100644 --- a/include/clang/Checker/BugReporter/BugReporter.h +++ b/include/clang/Checker/BugReporter/BugReporter.h @@ -70,6 +70,7 @@ protected: virtual void Profile(llvm::FoldingSetNodeID& hash) const { hash.AddInteger(getLocation().getRawEncoding()); + hash.AddString(Description); } public: diff --git a/include/clang/Checker/FrontendActions.h b/include/clang/Checker/FrontendActions.h new file mode 100644 index 0000000..1c0bbb7 --- /dev/null +++ b/include/clang/Checker/FrontendActions.h @@ -0,0 +1,29 @@ +//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_CHECKER_FRONTENDACTIONS_H +#define LLVM_CLANG_CHECKER_FRONTENDACTIONS_H + +#include "clang/Frontend/FrontendAction.h" + +namespace clang { + +//===----------------------------------------------------------------------===// +// AST Consumer Actions +//===----------------------------------------------------------------------===// + +class AnalysisAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Frontend/PathDiagnosticClients.h b/include/clang/Checker/PathDiagnosticClients.h index f8d2eeb..d3aa3b2 100644 --- a/include/clang/Frontend/PathDiagnosticClients.h +++ b/include/clang/Checker/PathDiagnosticClients.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLIENTS_H -#define LLVM_CLANG_FRONTEND_PATH_DIAGNOSTIC_CLiENTS_H +#ifndef LLVM_CLANG_CHECKER_PATH_DIAGNOSTIC_CLIENTS_H +#define LLVM_CLANG_CHECKER_PATH_DIAGNOSTIC_CLiENTS_H #include <string> diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h index 8cb9cc8..49dc3fa 100644 --- a/include/clang/Checker/PathSensitive/Checker.h +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -38,16 +38,20 @@ class CheckerContext { const unsigned size; bool DoneEvaluating; // FIXME: This is not a permanent API change. public: + bool *respondsToCallback; +public: CheckerContext(ExplodedNodeSet &dst, GRStmtNodeBuilder &builder, GRExprEngine &eng, ExplodedNode *pred, const void *tag, ProgramPoint::Kind K, + bool *respondsToCB = 0, const Stmt *stmt = 0, const GRState *st = 0) : Dst(dst), B(builder), Eng(eng), Pred(pred), OldSink(B.BuildSinks), OldTag(B.Tag, tag), OldPointKind(B.PointKind, K), OldHasGen(B.HasGeneratedNode), - ST(st), statement(stmt), size(Dst.size()) {} + ST(st), statement(stmt), size(Dst.size()), + respondsToCallback(respondsToCB) {} ~CheckerContext(); @@ -144,6 +148,7 @@ public: // If the 'state' is not new, we need to check if the cached state 'ST' // is new. if (state != getState() || (ST && ST != B.GetState(Pred))) + // state is new or equals to ST. GenerateNode(state, true); else Dst.Add(Pred); @@ -188,10 +193,11 @@ private: GRStmtNodeBuilder &Builder, GRExprEngine &Eng, const Stmt *S, - ExplodedNode *Pred, void *tag, bool isPrevisit) { + ExplodedNode *Pred, void *tag, bool isPrevisit, + bool& respondsToCallback) { CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind, S); + ProgramPoint::PostStmtKind, &respondsToCallback, S); if (isPrevisit) _PreVisit(C, S); else @@ -202,7 +208,7 @@ private: GRExprEngine &Eng, const ObjCMessageExpr *ME, ExplodedNode *Pred, const GRState *state, void *tag) { CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, - ME, state); + 0, ME, state); return EvalNilReceiver(C, ME); } @@ -210,7 +216,7 @@ private: GRExprEngine &Eng, const CallExpr *CE, ExplodedNode *Pred, void *tag) { CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, - CE); + 0, CE); return EvalCallExpr(C, CE); } @@ -223,7 +229,7 @@ private: bool isPrevisit) { CheckerContext C(Dst, Builder, Eng, Pred, tag, isPrevisit ? ProgramPoint::PreStmtKind : - ProgramPoint::PostStmtKind, StoreE); + ProgramPoint::PostStmtKind, 0, StoreE); assert(isPrevisit && "Only previsit supported for now."); PreVisitBind(C, AssignE, StoreE, location, val); } @@ -238,7 +244,7 @@ private: void *tag, bool isLoad) { CheckerContext C(Dst, Builder, Eng, Pred, tag, isLoad ? ProgramPoint::PreLoadKind : - ProgramPoint::PreStoreKind, S, state); + ProgramPoint::PreStoreKind, 0, S, state); VisitLocation(C, S, location); } @@ -246,8 +252,8 @@ private: GRExprEngine &Eng, const Stmt *S, ExplodedNode *Pred, SymbolReaper &SymReaper, void *tag) { CheckerContext C(Dst, Builder, Eng, Pred, tag, - ProgramPoint::PostPurgeDeadSymbolsKind, S); - EvalDeadSymbols(C, S, SymReaper); + ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); + EvalDeadSymbols(C, SymReaper); } public: @@ -257,8 +263,7 @@ public: virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {} virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE, const Stmt *StoreE, SVal location, SVal val) {} - virtual void EvalDeadSymbols(CheckerContext &C, const Stmt *S, - SymbolReaper &SymReaper) {} + virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {} virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag, GRExprEngine &Eng) {} @@ -278,6 +283,9 @@ public: bool Assumption) { return state; } + + virtual void VisitEndAnalysis(ExplodedGraph &G, BugReporter &B, + bool hasWorkRemaining) {} }; } // end clang namespace diff --git a/include/clang/Checker/PathSensitive/CheckerVisitor.h b/include/clang/Checker/PathSensitive/CheckerVisitor.h index 72f0ae1..e2ba89b 100644 --- a/include/clang/Checker/PathSensitive/CheckerVisitor.h +++ b/include/clang/Checker/PathSensitive/CheckerVisitor.h @@ -79,8 +79,13 @@ break; } } - void PreVisitStmt(CheckerContext &C, const Stmt *S) {} - void PostVisitStmt(CheckerContext &C, const Stmt *S) {} + 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); diff --git a/include/clang/Checker/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h index b9bbebc..2981731 100644 --- a/include/clang/Checker/PathSensitive/Environment.h +++ b/include/clang/Checker/PathSensitive/Environment.h @@ -86,7 +86,7 @@ public: Environment BindExpr(Environment Env, const Stmt *S, SVal V, bool Invalidate); - Environment RemoveDeadBindings(Environment Env, const Stmt *S, + Environment RemoveDeadBindings(Environment Env, SymbolReaper &SymReaper, const GRState *ST, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots); }; diff --git a/include/clang/Checker/PathSensitive/ExplodedGraph.h b/include/clang/Checker/PathSensitive/ExplodedGraph.h index c09c893..c875a23 100644 --- a/include/clang/Checker/PathSensitive/ExplodedGraph.h +++ b/include/clang/Checker/PathSensitive/ExplodedGraph.h @@ -36,7 +36,6 @@ namespace clang { class GRState; class CFG; -class ASTContext; class ExplodedGraph; //===----------------------------------------------------------------------===// @@ -240,9 +239,6 @@ protected: /// and successor groups. BumpVectorContext BVC; - /// Ctx - The ASTContext used to "interpret" CodeDecl. - ASTContext& Ctx; - /// NumNodes - The number of nodes in the graph. unsigned NumNodes; @@ -256,7 +252,7 @@ public: bool* IsNew = 0); ExplodedGraph* MakeEmptyGraph() const { - return new ExplodedGraph(Ctx); + return new ExplodedGraph(); } /// addRoot - Add an untyped node to the set of roots. @@ -271,7 +267,7 @@ public: return V; } - ExplodedGraph(ASTContext& ctx) : Ctx(ctx), NumNodes(0) {} + ExplodedGraph() : NumNodes(0) {} ~ExplodedGraph() {} @@ -318,8 +314,6 @@ public: llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); } BumpVectorContext &getNodeAllocator() { return BVC; } - ASTContext& getContext() { return Ctx; } - typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap; std::pair<ExplodedGraph*, InterExplodedGraphMap*> diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index 2d8afee..7f101dc 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -57,6 +57,10 @@ class GRCoreEngine { /// These are used to record for key nodes in the ExplodedGraph the /// number of times different CFGBlocks have been visited along a path. GRBlockCounter::Factory BCounterFactory; + + /// A flag that indicates whether paths were halted because + /// ProcessBlockEntrace returned false. + bool BlockAborted; void GenerateNode(const ProgramPoint& Loc, const GRState* State, ExplodedNode* Pred); @@ -105,17 +109,19 @@ private: public: /// Construct a GRCoreEngine object to analyze the provided CFG using /// a DFS exploration of the exploded graph. - GRCoreEngine(ASTContext& ctx, GRSubEngine& subengine) - : SubEngine(subengine), G(new ExplodedGraph(ctx)), + GRCoreEngine(GRSubEngine& subengine) + : SubEngine(subengine), G(new ExplodedGraph()), WList(GRWorkList::MakeBFS()), - BCounterFactory(G->getAllocator()) {} + BCounterFactory(G->getAllocator()), + BlockAborted(false) {} /// Construct a GRCoreEngine object to analyze the provided CFG and to /// use the provided worklist object to execute the worklist algorithm. /// The GRCoreEngine object assumes ownership of 'wlist'. - GRCoreEngine(ASTContext& ctx, GRWorkList* wlist, GRSubEngine& subengine) - : SubEngine(subengine), G(new ExplodedGraph(ctx)), WList(wlist), - BCounterFactory(G->getAllocator()) {} + GRCoreEngine(GRWorkList* wlist, GRSubEngine& subengine) + : SubEngine(subengine), G(new ExplodedGraph()), WList(wlist), + BCounterFactory(G->getAllocator()), + BlockAborted(false) {} ~GRCoreEngine() { delete WList; diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index ac407f6..8eaf3f4 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -16,6 +16,7 @@ #ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE #define LLVM_CLANG_ANALYSIS_GREXPRENGINE +#include "clang/Checker/PathSensitive/AnalysisManager.h" #include "clang/Checker/PathSensitive/GRSubEngine.h" #include "clang/Checker/PathSensitive/GRCoreEngine.h" #include "clang/Checker/PathSensitive/GRState.h" @@ -75,14 +76,25 @@ class GRExprEngine : public GRSubEngine { llvm::OwningPtr<GRSimpleAPICheck> BatchAuditor; typedef llvm::DenseMap<void *, unsigned> CheckerMap; - CheckerMap CheckerM; - typedef std::vector<std::pair<void *, Checker*> > CheckersOrdered; + typedef llvm::DenseMap<std::pair<unsigned, unsigned>, 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; - /// BR - 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 GRExprEngine is destroyed. + /// A map used for caching the checkers that respond to the callback for + /// a particular statement and visitation order. + 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 GRExprEngine is destroyed. GRBugReporter BR; llvm::OwningPtr<GRTransferFuncs> TF; @@ -106,7 +118,7 @@ public: } /// getContext - Return the ASTContext associated with this analysis. - ASTContext& getContext() const { return G.getContext(); } + ASTContext& getContext() const { return AMgr.getASTContext(); } AnalysisManager &getAnalysisManager() const { return AMgr; } @@ -178,12 +190,15 @@ public: /// nodes when the control reaches the end of a function. void ProcessEndPath(GREndPathNodeBuilder& builder); - // Generate the entry node of the callee. + /// Generate the entry node of the callee. void ProcessCallEnter(GRCallEnterNodeBuilder &builder); - // Generate the first post callsite node. + /// Generate the first post callsite node. void ProcessCallExit(GRCallExitNodeBuilder &builder); + /// Called by GRCoreEngine when the analysis worklist has terminated. + void ProcessEndWorklist(bool hasWorkRemaining); + /// EvalAssume - Callback function invoked by the ConstraintManager when /// making assumptions about state values. const GRState *ProcessAssume(const GRState *state, SVal cond, bool assumption); diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h index 25ba1f8..67a2caf 100644 --- a/include/clang/Checker/PathSensitive/GRState.h +++ b/include/clang/Checker/PathSensitive/GRState.h @@ -211,16 +211,18 @@ public: const GRState *bindLoc(SVal location, SVal V) const; + const GRState *bindDefault(SVal loc, SVal V) const; + const GRState *unbindLoc(Loc LV) const; /// Get the lvalue for a variable reference. - SVal getLValue(const VarDecl *D, const LocationContext *LC) const; + Loc getLValue(const VarDecl *D, const LocationContext *LC) const; /// Get the lvalue for a StringLiteral. - SVal getLValue(const StringLiteral *literal) const; + Loc getLValue(const StringLiteral *literal) const; - SVal getLValue(const CompoundLiteralExpr *literal, - const LocationContext *LC) const; + Loc getLValue(const CompoundLiteralExpr *literal, + const LocationContext *LC) const; /// Get the lvalue for an ivar reference. SVal getLValue(const ObjCIvarDecl *decl, SVal base) const; @@ -446,7 +448,7 @@ public: StoreManager& getStoreManager() { return *StoreMgr; } ConstraintManager& getConstraintManager() { return *ConstraintMgr; } - const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc, + const GRState* RemoveDeadBindings(const GRState* St, const StackFrameContext *LCtx, SymbolReaper& SymReaper); @@ -468,9 +470,6 @@ public: const GRState* getPersistentState(GRState& Impl); - bool isEqual(const GRState* state, const Expr* Ex, const llvm::APSInt& V); - bool isEqual(const GRState* state, const Expr* Ex, uint64_t); - //==---------------------------------------------------------------------==// // Generic Data Map methods. //==---------------------------------------------------------------------==// @@ -620,16 +619,22 @@ inline const GRState *GRState::bindLoc(SVal LV, SVal V) const { return !isa<Loc>(LV) ? this : bindLoc(cast<Loc>(LV), V); } -inline SVal GRState::getLValue(const VarDecl* VD, +inline const GRState *GRState::bindDefault(SVal loc, SVal V) const { + const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion(); + Store new_store = getStateManager().StoreMgr->BindDefault(St, R, V); + return makeWithStore(new_store); +} + +inline Loc GRState::getLValue(const VarDecl* VD, const LocationContext *LC) const { return getStateManager().StoreMgr->getLValueVar(VD, LC); } -inline SVal GRState::getLValue(const StringLiteral *literal) const { +inline Loc GRState::getLValue(const StringLiteral *literal) const { return getStateManager().StoreMgr->getLValueString(literal); } -inline SVal GRState::getLValue(const CompoundLiteralExpr *literal, +inline Loc GRState::getLValue(const CompoundLiteralExpr *literal, const LocationContext *LC) const { return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC); } diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index d2e7457..90a41d7 100644 --- a/include/clang/Checker/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -41,27 +41,27 @@ public: virtual GRStateManager& getStateManager() = 0; - /// ProcessStmt - Called by GRCoreEngine. Used to generate new successor - /// nodes by processing the 'effects' of a block-level statement. + /// Called by GRCoreEngine. Used to generate new successor + /// nodes by processing the 'effects' of a block-level statement. virtual void ProcessStmt(CFGElement E, GRStmtNodeBuilder& builder) = 0; - /// ProcessBlockEntrance - Called by GRCoreEngine when start processing - /// a CFGBlock. This method returns true if the analysis should continue - /// exploring the given path, and false otherwise. + /// Called by GRCoreEngine when start processing + /// a CFGBlock. This method returns true if the analysis should continue + /// exploring the given path, and false otherwise. virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred, GRBlockCounter BC) = 0; - /// ProcessBranch - Called by GRCoreEngine. Used to generate successor + /// Called by GRCoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. virtual void ProcessBranch(Stmt* Condition, Stmt* Term, GRBranchNodeBuilder& builder) = 0; - /// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor - /// nodes by processing the 'effects' of a computed goto jump. + /// Called by GRCoreEngine. Used to generate successor + /// nodes by processing the 'effects' of a computed goto jump. virtual void ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) = 0; - /// ProcessSwitch - Called by GRCoreEngine. Used to generate successor - /// nodes by processing the 'effects' of a switch statement. + /// Called by GRCoreEngine. Used to generate successor + /// nodes by processing the 'effects' of a switch statement. virtual void ProcessSwitch(GRSwitchNodeBuilder& builder) = 0; /// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path @@ -74,10 +74,14 @@ public: // Generate the first post callsite node. virtual void ProcessCallExit(GRCallExitNodeBuilder &builder) = 0; - /// EvalAssume - Called by ConstraintManager. Used to call checker-specific - /// logic for handling assumptions on symbolic values. + /// Called by ConstraintManager. Used to call checker-specific + /// logic for handling assumptions on symbolic values. virtual const GRState* ProcessAssume(const GRState *state, SVal cond, bool assumption) = 0; + + /// Called by GRCoreEngine when the analysis worklist is either empty or the + // maximum number of analysis steps have been reached. + virtual void ProcessEndWorklist(bool hasWorkRemaining) = 0; }; } diff --git a/include/clang/Checker/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h index 13325ed..374f998 100644 --- a/include/clang/Checker/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Checker/PathSensitive/GRTransferFuncs.h @@ -66,7 +66,7 @@ public: GRExprEngine& Engine, GRStmtNodeBuilder& Builder, ExplodedNode* Pred, - Stmt* S, const GRState* state, + const GRState* state, SymbolReaper& SymReaper) {} // Return statements. diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index 2ab3b42..feb4b72 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -34,7 +34,9 @@ class MemRegionManager; class MemSpaceRegion; class LocationContext; class StackFrameContext; +class ValueManager; class VarRegion; +class CodeTextRegion; //===----------------------------------------------------------------------===// // Base region classes. @@ -46,14 +48,17 @@ class MemRegion : public llvm::FoldingSetNode { public: enum Kind { // Memory spaces. - BEG_MEMSPACES, - GenericMemSpaceRegionKind = BEG_MEMSPACES, + GenericMemSpaceRegionKind, StackLocalsSpaceRegionKind, StackArgumentsSpaceRegionKind, HeapSpaceRegionKind, UnknownSpaceRegionKind, - GlobalsSpaceRegionKind, - END_MEMSPACES = GlobalsSpaceRegionKind, + NonStaticGlobalSpaceRegionKind, + StaticGlobalSpaceRegionKind, + BEG_GLOBAL_MEMSPACES = NonStaticGlobalSpaceRegionKind, + END_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind, + BEG_MEMSPACES = GenericMemSpaceRegionKind, + END_MEMSPACES = StaticGlobalSpaceRegionKind, // Untyped regions. SymbolicRegionKind, AllocaRegionKind, @@ -146,13 +151,48 @@ public: }; class GlobalsSpaceRegion : public MemSpaceRegion { +protected: + GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) + : MemSpaceRegion(mgr, k) {} +public: + static bool classof(const MemRegion *R) { + Kind k = R->getKind(); + return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES; + } +}; + +class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { friend class MemRegionManager; - GlobalsSpaceRegion(MemRegionManager *mgr) - : MemSpaceRegion(mgr, GlobalsSpaceRegionKind) {} + const CodeTextRegion *CR; + + StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr) + : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {} + +public: + void Profile(llvm::FoldingSetNodeID &ID) const; + + void dumpToStream(llvm::raw_ostream& os) const; + + const CodeTextRegion *getCodeRegion() const { return CR; } + + static bool classof(const MemRegion *R) { + return R->getKind() == StaticGlobalSpaceRegionKind; + } +}; + +class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { + friend class MemRegionManager; + + NonStaticGlobalSpaceRegion(MemRegionManager *mgr) + : GlobalsSpaceRegion(mgr, NonStaticGlobalSpaceRegionKind) {} + public: + + void dumpToStream(llvm::raw_ostream& os) const; + static bool classof(const MemRegion *R) { - return R->getKind() == GlobalsSpaceRegionKind; + return R->getKind() == NonStaticGlobalSpaceRegionKind; } }; @@ -232,6 +272,11 @@ public: return superRegion; } + /// getExtent - Returns the size of the region in bytes. + virtual DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const { + return UnknownVal(); + } + MemRegionManager* getMemRegionManager() const; bool isSubRegionOf(const MemRegion* R) const; @@ -288,6 +333,8 @@ public: bool isBoundable() const { return true; } + DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; + void Profile(llvm::FoldingSetNodeID& ID) const; static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr* Ex, @@ -502,6 +549,8 @@ public: bool isBoundable() const { return true; } + DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; + void Profile(llvm::FoldingSetNodeID& ID) const; static void ProfileRegion(llvm::FoldingSetNodeID& ID, @@ -536,6 +585,8 @@ public: return Str->getType(); } + DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; + bool isBoundable() const { return false; } void Profile(llvm::FoldingSetNodeID& ID) const { @@ -595,6 +646,8 @@ public: const Decl* getDecl() const { return D; } void Profile(llvm::FoldingSetNodeID& ID) const; + DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; + static bool classof(const MemRegion* R) { unsigned k = R->getKind(); return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS; @@ -679,6 +732,8 @@ public: return C.getCanonicalType(getDecl()->getType()); } + DefinedOrUnknownSVal getExtent(ValueManager& ValMgr) const; + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl* FD, const MemRegion* superRegion) { DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind); @@ -793,12 +848,14 @@ class MemRegionManager { llvm::BumpPtrAllocator& A; llvm::FoldingSet<MemRegion> Regions; - GlobalsSpaceRegion *globals; + NonStaticGlobalSpaceRegion *globals; llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *> StackLocalsSpaceRegions; llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *> StackArgumentsSpaceRegions; + llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *> + StaticsGlobalSpaceRegions; HeapSpaceRegion *heap; UnknownSpaceRegion *unknown; @@ -825,8 +882,8 @@ public: getStackArgumentsRegion(const StackFrameContext *STC); /// getGlobalsRegion - Retrieve the memory region associated with - /// all global variables. - const GlobalsSpaceRegion *getGlobalsRegion(); + /// global variables. + const GlobalsSpaceRegion *getGlobalsRegion(const CodeTextRegion *R = 0); /// getHeapRegion - Retrieve the memory region associated with the /// generic "heap". diff --git a/include/clang/Checker/PathSensitive/SVals.h b/include/clang/Checker/PathSensitive/SVals.h index 040db83..55fd3ea 100644 --- a/include/clang/Checker/PathSensitive/SVals.h +++ b/include/clang/Checker/PathSensitive/SVals.h @@ -98,6 +98,8 @@ public: bool isConstant() const; + bool isConstant(int I) const; + bool isZeroConstant() const; /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true; @@ -109,7 +111,7 @@ public: const FunctionDecl* getAsFunctionDecl() const; /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and - /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolData* + /// wraps a symbol, return that SymbolRef. Otherwise return NULL. SymbolRef getAsLocSymbol() const; /// Get the symbol in the SVal or its base region. diff --git a/include/clang/Checker/PathSensitive/SValuator.h b/include/clang/Checker/PathSensitive/SValuator.h index 9beb8cb..9192ca7 100644 --- a/include/clang/Checker/PathSensitive/SValuator.h +++ b/include/clang/Checker/PathSensitive/SValuator.h @@ -47,11 +47,15 @@ public: virtual SVal EvalBinOpNN(const GRState *state, BinaryOperator::Opcode Op, NonLoc lhs, NonLoc rhs, QualType resultTy) = 0; - virtual SVal EvalBinOpLL(BinaryOperator::Opcode Op, Loc lhs, Loc rhs, - QualType resultTy) = 0; + 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, 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; SVal EvalBinOp(const GRState *ST, BinaryOperator::Opcode Op, SVal L, SVal R, QualType T); diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index f3155b9..7a60ebb 100644 --- a/include/clang/Checker/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -64,6 +64,10 @@ public: /// to the location given for \c loc. virtual Store Bind(Store store, Loc loc, SVal val) = 0; + virtual Store BindDefault(Store store, const MemRegion *R, SVal V) { + return store; + } + virtual Store Remove(Store St, Loc L) = 0; /// BindCompoundLiteral - Return the store that has the bindings currently @@ -87,16 +91,16 @@ public: // caller's responsibility to 'delete' the returned map. virtual SubRegionMap *getSubRegionMap(Store store) = 0; - virtual SVal getLValueVar(const VarDecl *VD, const LocationContext *LC) { + virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) { return ValMgr.makeLoc(MRMgr.getVarRegion(VD, LC)); } - virtual SVal getLValueString(const StringLiteral* S) { + virtual Loc getLValueString(const StringLiteral* S) { return ValMgr.makeLoc(MRMgr.getStringRegion(S)); } - SVal getLValueCompoundLiteral(const CompoundLiteralExpr* CL, - const LocationContext *LC) { + Loc getLValueCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC) { return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)); } @@ -110,7 +114,8 @@ public: virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base); - // FIXME: Make out-of-line. + // FIXME: This should soon be eliminated altogether; clients should deal with + // region extents directly. virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, const MemRegion *region, QualType EleTy) { @@ -144,7 +149,7 @@ public: return UnknownVal(); } - virtual const GRState *RemoveDeadBindings(GRState &state, Stmt* Loc, + virtual const GRState *RemoveDeadBindings(GRState &state, const StackFrameContext *LCtx, SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) = 0; @@ -164,18 +169,8 @@ public: const MemRegion * const *Begin, const MemRegion * const *End, const Expr *E, unsigned Count, - InvalidatedSymbols *IS); - - // FIXME: Make out-of-line. - virtual const GRState *setExtent(const GRState *state, - const MemRegion *region, SVal extent) { - return state; - } - - virtual llvm::Optional<SVal> getExtent(const GRState *state, - const MemRegion *R) { - return llvm::Optional<SVal>(); - } + InvalidatedSymbols *IS, + bool invalidateGlobals) = 0; /// EnterStackFrame - Let the StoreManager to do something when execution /// engine is about to execute into a callee. diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h index dea877c..ffbd289 100644 --- a/include/clang/Checker/PathSensitive/SymbolManager.h +++ b/include/clang/Checker/PathSensitive/SymbolManager.h @@ -31,6 +31,7 @@ namespace clang { class ASTContext; class BasicValueFactory; class MemRegion; + class SubRegion; class TypedRegion; class VarRegion; class StackFrameContext; @@ -38,7 +39,7 @@ namespace clang { class SymExpr : public llvm::FoldingSetNode { public: enum Kind { BEGIN_SYMBOLS, - RegionValueKind, ConjuredKind, DerivedKind, + RegionValueKind, ConjuredKind, DerivedKind, ExtentKind, END_SYMBOLS, SymIntKind, SymSymKind }; private: @@ -189,6 +190,34 @@ public: } }; +class SymbolExtent : public SymbolData { + const SubRegion *R; + +public: + SymbolExtent(SymbolID sym, const SubRegion *r) + : SymbolData(ExtentKind, sym), R(r) {} + + const SubRegion *getRegion() const { return R; } + + QualType getType(ASTContext&) const; + + void dumpToStream(llvm::raw_ostream &os) const; + + static void Profile(llvm::FoldingSetNodeID& profile, const SubRegion *R) { + profile.AddInteger((unsigned) ExtentKind); + profile.AddPointer(R); + } + + virtual void Profile(llvm::FoldingSetNodeID& profile) { + Profile(profile, R); + } + + // Implement isa<T> support. + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == ExtentKind; + } +}; + // SymIntExpr - Represents symbolic expression like 'x' + 3. class SymIntExpr : public SymExpr { const SymExpr *LHS; @@ -305,6 +334,8 @@ public: const SymbolDerived *getDerivedSymbol(SymbolRef parentSymbol, const TypedRegion *R); + const SymbolExtent *getExtentSymbol(const SubRegion *R); + const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType t); @@ -330,21 +361,23 @@ class SymbolReaper { SetTy TheLiving; SetTy TheDead; const LocationContext *LCtx; + const Stmt *Loc; SymbolManager& SymMgr; public: - SymbolReaper(const LocationContext *ctx, SymbolManager& symmgr) - : LCtx(ctx), SymMgr(symmgr) {} + SymbolReaper(const LocationContext *ctx, const Stmt *s, SymbolManager& symmgr) + : LCtx(ctx), Loc(s), SymMgr(symmgr) {} ~SymbolReaper() {} const LocationContext *getLocationContext() const { return LCtx; } + const Stmt *getCurrentStatement() const { return Loc; } bool isLive(SymbolRef sym); - bool isLive(const Stmt* Loc, const Stmt* ExprVal) const; + bool isLive(const Stmt *ExprVal) const; - bool isLive(const Stmt* Loc, const VarRegion *VR) const; + bool isLive(const VarRegion *VR) const; void markLive(SymbolRef sym); bool maybeDead(SymbolRef sym); diff --git a/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h new file mode 100644 index 0000000..abcef81 --- /dev/null +++ b/include/clang/CodeGen/BackendUtil.h @@ -0,0 +1,37 @@ +//===--- BackendUtil.h - LLVM Backend Utilities -----------------*- 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_CODEGEN_BACKEND_UTIL_H +#define LLVM_CLANG_CODEGEN_BACKEND_UTIL_H + +namespace llvm { + class Module; + class raw_ostream; +} + +namespace clang { + class Diagnostic; + class CodeGenOptions; + class TargetOptions; + + enum BackendAction { + Backend_EmitAssembly, ///< Emit native assembly files + Backend_EmitBC, ///< Emit LLVM bitcode files + Backend_EmitLL, ///< Emit human-readable LLVM assembly + Backend_EmitNothing, ///< Don't emit anything (benchmarking mode) + Backend_EmitMCNull, ///< Run CodeGen, but don't emit anything + Backend_EmitObj ///< Emit native object files + }; + + void EmitBackendOutput(Diagnostic &Diags, const CodeGenOptions &CGOpts, + const TargetOptions &TOpts, llvm::Module *M, + BackendAction Action, llvm::raw_ostream *OS); +} + +#endif diff --git a/include/clang/Frontend/CodeGenAction.h b/include/clang/CodeGen/CodeGenAction.h index dfc117a..cecfcda 100644 --- a/include/clang/Frontend/CodeGenAction.h +++ b/include/clang/CodeGen/CodeGenAction.h @@ -7,6 +7,9 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_CODEGEN_CODE_GEN_ACTION_H +#define LLVM_CLANG_CODEGEN_CODE_GEN_ACTION_H + #include "clang/Frontend/FrontendAction.h" #include "llvm/ADT/OwningPtr.h" @@ -24,9 +27,13 @@ private: protected: CodeGenAction(unsigned _Act); + virtual bool hasIRSupport() const; + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile); + virtual void ExecuteAction(); + virtual void EndSourceFileAction(); public: @@ -68,3 +75,5 @@ public: }; } + +#endif diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index 2a3aa6a..c45ad08 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -33,6 +33,9 @@ namespace clang { virtual llvm::Module* ReleaseModule() = 0; }; + /// CreateLLVMCodeGen - Create a CodeGenerator instance. + /// It is the responsibility of the caller to call delete on + /// the allocated CodeGenerator instance. CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags, const std::string &ModuleName, const CodeGenOptions &CGO, diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index ab3162a..4b45c98 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -51,9 +51,10 @@ public: AssembleJobClass, LinkJobClass, LipoJobClass, + DsymutilJobClass, JobClassFirst=PreprocessJobClass, - JobClassLast=LipoJobClass + JobClassLast=DsymutilJobClass }; static const char *getClassName(ActionClass AC); @@ -211,6 +212,16 @@ public: static bool classof(const LipoJobAction *) { return true; } }; +class DsymutilJobAction : public JobAction { +public: + DsymutilJobAction(ActionList &Inputs, types::ID Type); + + static bool classof(const Action *A) { + return A->getKind() == DsymutilJobClass; + } + static bool classof(const DsymutilJobAction *) { return true; } +}; + } // end namespace driver } // end namespace clang diff --git a/include/clang/Driver/Arg.h b/include/clang/Driver/Arg.h index ebf40d4..a52789e 100644 --- a/include/clang/Driver/Arg.h +++ b/include/clang/Driver/Arg.h @@ -10,14 +10,9 @@ #ifndef CLANG_DRIVER_ARG_H_ #define CLANG_DRIVER_ARG_H_ -#include "llvm/Support/Casting.h" -using llvm::isa; -using llvm::cast; -using llvm::cast_or_null; -using llvm::dyn_cast; -using llvm::dyn_cast_or_null; - #include "Util.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include <vector> #include <string> @@ -34,19 +29,10 @@ namespace driver { /// ArgList to provide efficient iteration over all instances of a /// particular option. class Arg { - public: - enum ArgClass { - FlagClass = 0, - PositionalClass, - JoinedClass, - SeparateClass, - CommaJoinedClass, - JoinedAndSeparateClass - }; + Arg(const Arg &); // DO NOT IMPLEMENT + void operator=(const Arg &); // DO NOT IMPLEMENT private: - ArgClass Kind; - /// The option this argument is an instance of. const Option *Opt; @@ -58,20 +44,24 @@ namespace driver { /// ArgList. unsigned Index; - /// Flag indicating whether this argument was used to effect - /// compilation; used for generating "argument unused" - /// diagnostics. - mutable bool Claimed; + /// Was this argument used to effect compilation; used for generating + /// "argument unused" diagnostics. + mutable unsigned Claimed : 1; + + /// Does this argument own its values. + mutable unsigned OwnsValues : 1; - protected: - Arg(ArgClass Kind, const Option *Opt, unsigned Index, - const Arg *BaseArg = 0); + /// The argument values, as C strings. + llvm::SmallVector<const char *, 2> Values; public: - Arg(const Arg &); - virtual ~Arg(); + Arg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); + Arg(const Option *Opt, unsigned Index, + const char *Value0, const Arg *BaseArg = 0); + Arg(const Option *Opt, unsigned Index, + const char *Value0, const char *Value1, const Arg *BaseArg = 0); + ~Arg(); - ArgClass getKind() const { return Kind; } const Option &getOption() const { return *Opt; } unsigned getIndex() const { return Index; } @@ -85,19 +75,32 @@ namespace driver { BaseArg = _BaseArg; } + bool getOwnsValues() const { return OwnsValues; } + void setOwnsValues(bool Value) const { OwnsValues = Value; } + bool isClaimed() const { return getBaseArg().Claimed; } /// claim - Set the Arg claimed bit. - - // FIXME: We need to deal with derived arguments and set the bit - // in the original argument; not the derived one. void claim() const { getBaseArg().Claimed = true; } - virtual unsigned getNumValues() const = 0; - virtual const char *getValue(const ArgList &Args, unsigned N=0) const = 0; + unsigned getNumValues() const { return Values.size(); } + const char *getValue(const ArgList &Args, unsigned N=0) const { + return Values[N]; + } + + llvm::SmallVectorImpl<const char*> &getValues() { + return Values; + } + + bool containsValue(llvm::StringRef Value) const { + for (unsigned i = 0, e = getNumValues(); i != e; ++i) + if (Values[i] == Value) + return true; + return false; + } /// render - Append the argument onto the given array as strings. - virtual void render(const ArgList &Args, ArgStringList &Output) const = 0; + void render(const ArgList &Args, ArgStringList &Output) const; /// renderAsInput - Append the argument, render as an input, onto /// the given array as strings. The distinction is that some @@ -114,116 +117,6 @@ namespace driver { std::string getAsString(const ArgList &Args) const; }; - /// FlagArg - An argument with no value. - class FlagArg : public Arg { - public: - FlagArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); - - virtual void render(const ArgList &Args, ArgStringList &Output) const; - - virtual unsigned getNumValues() const { return 0; } - virtual const char *getValue(const ArgList &Args, unsigned N=0) const; - - static bool classof(const Arg *A) { - return A->getKind() == Arg::FlagClass; - } - static bool classof(const FlagArg *) { return true; } - }; - - /// PositionalArg - A simple positional argument. - class PositionalArg : public Arg { - public: - PositionalArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); - - virtual void render(const ArgList &Args, ArgStringList &Output) const; - - virtual unsigned getNumValues() const { return 1; } - virtual const char *getValue(const ArgList &Args, unsigned N=0) const; - - static bool classof(const Arg *A) { - return A->getKind() == Arg::PositionalClass; - } - static bool classof(const PositionalArg *) { return true; } - }; - - /// JoinedArg - A single value argument where the value is joined - /// (suffixed) to the option. - class JoinedArg : public Arg { - public: - JoinedArg(const Option *Opt, unsigned Index, const Arg *BaseArg = 0); - - virtual void render(const ArgList &Args, ArgStringList &Output) const; - - virtual unsigned getNumValues() const { return 1; } - virtual const char *getValue(const ArgList &Args, unsigned N=0) const; - - static bool classof(const Arg *A) { - return A->getKind() == Arg::JoinedClass; - } - static bool classof(const JoinedArg *) { return true; } - }; - - /// SeparateArg - An argument where one or more values follow the - /// option specifier immediately in the argument vector. - class SeparateArg : public Arg { - unsigned NumValues; - - public: - SeparateArg(const Option *Opt, unsigned Index, unsigned NumValues, - const Arg *BaseArg = 0); - - virtual void render(const ArgList &Args, ArgStringList &Output) const; - - virtual unsigned getNumValues() const { return NumValues; } - virtual const char *getValue(const ArgList &Args, unsigned N=0) const; - - static bool classof(const Arg *A) { - return A->getKind() == Arg::SeparateClass; - } - static bool classof(const SeparateArg *) { return true; } - }; - - /// CommaJoinedArg - An argument with multiple values joined by - /// commas and joined (suffixed) to the option specifier. - /// - /// The key point of this arg is that it renders its values into - /// separate arguments, which allows it to be used as a generic - /// mechanism for passing arguments through to tools. - class CommaJoinedArg : public Arg { - std::vector<std::string> Values; - - public: - CommaJoinedArg(const Option *Opt, unsigned Index, const char *Str, - const Arg *BaseArg = 0); - - virtual void render(const ArgList &Args, ArgStringList &Output) const; - - virtual unsigned getNumValues() const { return Values.size(); } - virtual const char *getValue(const ArgList &Args, unsigned N=0) const; - - static bool classof(const Arg *A) { - return A->getKind() == Arg::CommaJoinedClass; - } - static bool classof(const CommaJoinedArg *) { return true; } - }; - - /// JoinedAndSeparateArg - An argument with both joined and separate - /// values. - class JoinedAndSeparateArg : public Arg { - public: - JoinedAndSeparateArg(const Option *Opt, unsigned Index, - const Arg *BaseArg = 0); - - virtual void render(const ArgList &Args, ArgStringList &Output) const; - - virtual unsigned getNumValues() const { return 2; } - virtual const char *getValue(const ArgList &Args, unsigned N=0) const; - - static bool classof(const Arg *A) { - return A->getKind() == Arg::JoinedAndSeparateClass; - } - static bool classof(const JoinedAndSeparateArg *) { return true; } - }; } // end namespace driver } // end namespace clang diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 7a14ae8..16396da 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -52,9 +52,9 @@ namespace driver { void SkipToNextArg(); public: - typedef const Arg* value_type; - typedef const Arg* reference; - typedef const Arg* pointer; + typedef Arg * const * value_type; + typedef Arg * const & reference; + typedef Arg * const * pointer; typedef std::forward_iterator_tag iterator_category; typedef std::ptrdiff_t difference_type; @@ -67,7 +67,7 @@ namespace driver { operator const Arg*() { return *Current; } reference operator*() const { return *Current; } - pointer operator->() const { return *Current; } + pointer operator->() const { return Current; } arg_iterator &operator++() { ++Current; @@ -96,6 +96,10 @@ namespace driver { /// check for the presence of Arg instances for a particular Option /// and to iterate over groups of arguments. class ArgList { + private: + ArgList(const ArgList &); // DO NOT IMPLEMENT + void operator=(const ArgList &); // DO NOT IMPLEMENT + public: typedef llvm::SmallVector<Arg*, 16> arglist_type; typedef arglist_type::iterator iterator; @@ -104,11 +108,11 @@ namespace driver { typedef arglist_type::const_reverse_iterator const_reverse_iterator; private: - /// The full list of arguments. - arglist_type &Args; + /// The internal list of arguments. + arglist_type Args; protected: - ArgList(arglist_type &Args); + ArgList(); public: virtual ~ArgList(); @@ -179,6 +183,11 @@ namespace driver { /// getArgString - Return the input argument string at \arg Index. virtual const char *getArgString(unsigned Index) const = 0; + /// getNumInputArgStrings - Return the number of original argument strings, + /// which are guaranteed to be the first strings in the argument string + /// list. + virtual unsigned getNumInputArgStrings() const = 0; + /// @} /// @name Argument Lookup Utilities /// @{ @@ -249,14 +258,16 @@ namespace driver { } const char *MakeArgString(const llvm::Twine &Str) const; + /// \brief Create an arg string for (\arg LHS + \arg RHS), reusing the + /// string at \arg Index if possible. + const char *GetOrMakeJoinedArgString(unsigned Index, llvm::StringRef LHS, + llvm::StringRef RHS) const; + /// @} }; class InputArgList : public ArgList { private: - /// The internal list of arguments. - arglist_type ActualArgs; - /// List of argument strings used by the contained Args. /// /// This is mutable since we treat the ArgList as being the list @@ -276,16 +287,15 @@ namespace driver { public: InputArgList(const char **ArgBegin, const char **ArgEnd); - InputArgList(const ArgList &); ~InputArgList(); virtual const char *getArgString(unsigned Index) const { return ArgStrings[Index]; } - /// getNumInputArgStrings - Return the number of original input - /// argument strings. - unsigned getNumInputArgStrings() const { return NumInputArgStrings; } + virtual unsigned getNumInputArgStrings() const { + return NumInputArgStrings; + } /// @name Arg Synthesis /// @{ @@ -303,34 +313,71 @@ namespace driver { /// DerivedArgList - An ordered collection of driver arguments, /// whose storage may be in another argument list. class DerivedArgList : public ArgList { - InputArgList &BaseArgs; - - /// The internal list of arguments. - arglist_type ActualArgs; + const InputArgList &BaseArgs; /// The list of arguments we synthesized. mutable arglist_type SynthesizedArgs; - /// Is this only a proxy for the base ArgList? - bool OnlyProxy; - public: /// Construct a new derived arg list from \arg BaseArgs. - /// - /// \param OnlyProxy - If true, this is only a proxy for the base - /// list (to adapt the type), and it's Args list is unused. - DerivedArgList(InputArgList &BaseArgs, bool OnlyProxy); + DerivedArgList(const InputArgList &BaseArgs); ~DerivedArgList(); virtual const char *getArgString(unsigned Index) const { return BaseArgs.getArgString(Index); } + virtual unsigned getNumInputArgStrings() const { + return BaseArgs.getNumInputArgStrings(); + } + + const InputArgList &getBaseArgs() const { + return BaseArgs; + } + /// @name Arg Synthesis /// @{ + /// AddSynthesizedArg - Add a argument to the list of synthesized arguments + /// (to be freed). + void AddSynthesizedArg(Arg *A) { + SynthesizedArgs.push_back(A); + } + virtual const char *MakeArgString(llvm::StringRef Str) const; + /// AddFlagArg - Construct a new FlagArg for the given option \arg Id and + /// append it to the argument list. + void AddFlagArg(const Arg *BaseArg, const Option *Opt) { + append(MakeFlagArg(BaseArg, Opt)); + } + + /// AddPositionalArg - Construct a new Positional arg for the given option + /// \arg Id, with the provided \arg Value and append it to the argument + /// list. + void AddPositionalArg(const Arg *BaseArg, const Option *Opt, + llvm::StringRef Value) { + append(MakePositionalArg(BaseArg, Opt, Value)); + } + + + /// AddSeparateArg - Construct a new Positional arg for the given option + /// \arg Id, with the provided \arg Value and append it to the argument + /// list. + void AddSeparateArg(const Arg *BaseArg, const Option *Opt, + llvm::StringRef Value) { + append(MakeSeparateArg(BaseArg, Opt, Value)); + } + + + /// AddJoinedArg - Construct a new Positional arg for the given option \arg + /// Id, with the provided \arg Value and append it to the argument list. + void AddJoinedArg(const Arg *BaseArg, const Option *Opt, + llvm::StringRef Value) { + append(MakeJoinedArg(BaseArg, Opt, Value)); + } + + /// MakeFlagArg - Construct a new FlagArg for the given option /// \arg Id. Arg *MakeFlagArg(const Arg *BaseArg, const Option *Opt) const; diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index fd8322b..7076f30 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -18,6 +18,8 @@ include "OptParser.td" // Target Options //===----------------------------------------------------------------------===// +def cxx_abi : Separate<"-cxx-abi">, + HelpText<"Target a particular C++ ABI type">; def target_abi : Separate<"-target-abi">, HelpText<"Target a particular ABI type">; def target_cpu : Separate<"-target-cpu">, @@ -79,6 +81,8 @@ 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 analyzer_idempotent_operation : Flag<"-analyzer-idempotent-operation">, + HelpText<"Use experimental path-sensitive idempotent operation checker">; def analyzer_experimental_internal_checks : Flag<"-analyzer-experimental-internal-checks">, HelpText<"Use new default path-sensitive checks currently in testing">; @@ -121,6 +125,8 @@ def fno_common : Flag<"-fno-common">, HelpText<"Compile common globals like normal definitions">; def no_implicit_float : Flag<"-no-implicit-float">, HelpText<"Don't generate implicit floating point instructions (x86-only)">; +def finstrument_functions : Flag<"-finstrument-functions">, + HelpText<"Generate calls to instrument function entry and exit">; def fno_merge_all_constants : Flag<"-fno-merge-all-constants">, HelpText<"Disallow merging of constants.">; def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, @@ -145,6 +151,8 @@ def mlimit_float_precision : Separate<"-mlimit-float-precision">, HelpText<"Limit float precision to the given value">; def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">, HelpText<"Do not put zero initialized data in the BSS">; +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 mrelax_all : Flag<"-mrelax-all">, @@ -182,6 +190,9 @@ 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">, HelpText<"Do not include source location information with diagnostics">; +def fshow_overloads_EQ : Joined<"-fshow-overloads=">, + HelpText<"Which overload candidates to show when overload resolution fails: " + "best|all; defaults to all">; 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">, @@ -259,8 +270,11 @@ def cxx_inheritance_view : Separate<"-cxx-inheritance-view">, def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">; def load : Separate<"-load">, MetaVarName<"<dsopath>">, HelpText<"Load the named plugin (dynamic shared object)">; -def plugin : Separate<"-plugin">, +def plugin : Separate<"-plugin">, MetaVarName<"<name>">, HelpText<"Use the named plugin action (use \"help\" to list available options)">; +def plugin_arg : JoinedAndSeparate<"-plugin-arg-">, + MetaVarName<"<name> <arg>">, + HelpText<"Pass <arg> to plugin <name>">; def resource_dir : Separate<"-resource-dir">, HelpText<"The directory which holds the compiler resource files">; def version : Flag<"-version">, @@ -333,6 +347,8 @@ def rewrite_macros : Flag<"-rewrite-macros">, def relocatable_pch : Flag<"-relocatable-pch">, HelpText<"Whether to build a relocatable precompiled header">; +def chained_pch : Flag<"-chained-pch">, + HelpText<"Whether to chain the new precompiled header to the old one.">; def print_stats : Flag<"-print-stats">, HelpText<"Print performance metrics and statistics">; def ftime_report : Flag<"-ftime-report">, @@ -395,6 +411,8 @@ def fno_operator_names : Flag<"-fno-operator-names">, HelpText<"Do not treat C++ operator name keywords as synonyms for operators">; def fno_signed_char : Flag<"-fno-signed-char">, HelpText<"Char is unsigned">; +def fno_spell_checking : Flag<"-fno-spell-checking">, + HelpText<"Disable spell-checking">; def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">, HelpText<"Don't use __cxa_atexit for calling destructors">; def fconstant_string_class : Separate<"-fconstant-string-class">, @@ -416,6 +434,8 @@ def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">, HelpText<"enable objective-c's enhanced nonfragile abi">; def ftrapv : Flag<"-ftrapv">, HelpText<"Trap on integer overflow">; +def fwrapv : Flag<"-fwrapv">, + HelpText<"Treat signed integer overflow as two's complement">; def pic_level : Separate<"-pic-level">, HelpText<"Value for __PIC__">; def pthread : Flag<"-pthread">, @@ -432,6 +452,8 @@ def stack_protector : Separate<"-stack-protector">, HelpText<"Enable stack protectors">; def fvisibility : Separate<"-fvisibility">, HelpText<"Default symbol visibility">; +def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, + HelpText<"Give inline C++ member functions default visibility by default">; def ftemplate_depth : Separate<"-ftemplate-depth">, HelpText<"Maximum depth of recursive template instantiation">; def trigraphs : Flag<"-trigraphs">, diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 56786a7..5f062a1 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -40,13 +40,18 @@ class Compilation { /// The original (untranslated) input argument list. InputArgList *Args; + /// The driver translated arguments. Note that toolchains may perform their + /// own argument translation. + DerivedArgList *TranslatedArgs; + /// The list of actions. ActionList Actions; /// The root list of jobs. JobList Jobs; - /// Cache of translated arguments for a particular tool chain. + /// Cache of translated arguments for a particular tool chain and bound + /// architecture. llvm::DenseMap<std::pair<const ToolChain*, const char*>, DerivedArgList*> TCArgs; @@ -58,14 +63,16 @@ class Compilation { public: Compilation(const Driver &D, const ToolChain &DefaultToolChain, - InputArgList *Args); + InputArgList *Args, DerivedArgList *TranslatedArgs); ~Compilation(); const Driver &getDriver() const { return TheDriver; } const ToolChain &getDefaultToolChain() const { return DefaultToolChain; } - const InputArgList &getArgs() const { return *Args; } + const InputArgList &getInputArgs() const { return *Args; } + + const DerivedArgList &getArgs() const { return *TranslatedArgs; } ActionList &getActions() { return Actions; } const ActionList &getActions() const { return Actions; } diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 90c3a0d..153981f 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -31,6 +31,7 @@ namespace driver { class Action; class ArgList; class Compilation; + class DerivedArgList; class HostInfo; class InputArgList; class InputInfo; @@ -135,6 +136,11 @@ private: std::list<std::string> TempFiles; std::list<std::string> ResultFiles; +private: + /// TranslateInputArgs - Create a new derived argument list from the input + /// arguments, after applying the standard argument translations. + DerivedArgList *TranslateInputArgs(const InputArgList &Args) const; + public: Driver(llvm::StringRef _Name, llvm::StringRef _Dir, llvm::StringRef _DefaultHostTriple, diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h index ca1ee9a..1b99a44 100644 --- a/include/clang/Driver/HostInfo.h +++ b/include/clang/Driver/HostInfo.h @@ -76,6 +76,8 @@ const HostInfo *createOpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple); const HostInfo *createFreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple); +const HostInfo *createMinixHostInfo(const Driver &D, + const llvm::Triple& Triple); const HostInfo *createDragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple); const HostInfo *createLinuxHostInfo(const Driver &D, diff --git a/include/clang/Driver/Makefile b/include/clang/Driver/Makefile index b462aaa..d829166 100644 --- a/include/clang/Driver/Makefile +++ b/include/clang/Driver/Makefile @@ -1,9 +1,9 @@ -LEVEL = ../../../../.. +CLANG_LEVEL := ../../.. BUILT_SOURCES = Options.inc CC1Options.inc CC1AsOptions.inc TABLEGEN_INC_FILES_COMMON = 1 -include $(LEVEL)/Makefile.common +include $(CLANG_LEVEL)/Makefile $(ObjDir)/Options.inc.tmp : Options.td OptParser.td $(TBLGEN) $(ObjDir)/.dir $(Echo) "Building Clang Driver Option tables with tblgen" diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h index edae75c..e4a2eba 100644 --- a/include/clang/Driver/OptTable.h +++ b/include/clang/Driver/OptTable.h @@ -33,6 +33,7 @@ namespace options { } class Arg; + class ArgList; class InputArgList; class Option; @@ -150,7 +151,7 @@ namespace options { /// \return - The parsed argument, or 0 if the argument is missing values /// (in which case Index still points at the conceptual next argument string /// to parse). - Arg *ParseOneArg(const InputArgList &Args, unsigned &Index) const; + Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const; /// ParseArgs - Parse an list of arguments into an InputArgList. /// diff --git a/include/clang/Driver/Option.h b/include/clang/Driver/Option.h index 08b94b1..0864382 100644 --- a/include/clang/Driver/Option.h +++ b/include/clang/Driver/Option.h @@ -21,7 +21,7 @@ using llvm::dyn_cast_or_null; namespace clang { namespace driver { class Arg; - class InputArgList; + class ArgList; class OptionGroup; /// Option - Abstract representation for a single form of driver @@ -50,6 +50,13 @@ namespace driver { JoinedAndSeparateClass }; + enum RenderStyleKind { + RenderCommaJoinedStyle, + RenderJoinedStyle, + RenderSeparateStyle, + RenderValuesStyle + }; + private: OptionClass Kind; @@ -65,7 +72,7 @@ namespace driver { /// Option that this is an alias for, if any. const Option *Alias; - /// Unsupported options will not be rejected. + /// Unsupported options will be rejected. bool Unsupported : 1; /// Treat this option like a linker input? @@ -76,11 +83,8 @@ namespace driver { // FIXME: We should ditch the render/renderAsInput distinction. bool NoOptAsInput : 1; - /// Always render this option as separate form its value. - bool ForceSeparateRender : 1; - - /// Always render this option joined with its value. - bool ForceJoinedRender : 1; + /// The style to using when rendering arguments parsed by this option. + unsigned RenderStyle : 2; /// This option is only consumed by the driver. bool DriverOption : 1; @@ -109,11 +113,10 @@ namespace driver { bool hasNoOptAsInput() const { return NoOptAsInput; } void setNoOptAsInput(bool Value) { NoOptAsInput = Value; } - bool hasForceSeparateRender() const { return ForceSeparateRender; } - void setForceSeparateRender(bool Value) { ForceSeparateRender = Value; } - - bool hasForceJoinedRender() const { return ForceJoinedRender; } - void setForceJoinedRender(bool Value) { ForceJoinedRender = Value; } + RenderStyleKind getRenderStyle() const { + return RenderStyleKind(RenderStyle); + } + void setRenderStyle(RenderStyleKind Value) { RenderStyle = Value; } bool isDriverOption() const { return DriverOption; } void setDriverOption(bool Value) { DriverOption = Value; } @@ -151,7 +154,7 @@ namespace driver { /// If the option accepts the current argument, accept() sets /// Index to the position where argument parsing should resume /// (even if the argument is missing values). - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const = 0; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const = 0; void dump() const; @@ -164,7 +167,7 @@ namespace driver { public: OptionGroup(OptSpecifier ID, const char *Name, const OptionGroup *Group); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::GroupClass; @@ -179,7 +182,7 @@ namespace driver { public: InputOption(OptSpecifier ID); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::InputClass; @@ -192,7 +195,7 @@ namespace driver { public: UnknownOption(OptSpecifier ID); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::UnknownClass; @@ -207,7 +210,7 @@ namespace driver { FlagOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::FlagClass; @@ -220,7 +223,7 @@ namespace driver { JoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::JoinedClass; @@ -233,7 +236,7 @@ namespace driver { SeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::SeparateClass; @@ -246,7 +249,7 @@ namespace driver { CommaJoinedOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::CommaJoinedClass; @@ -267,7 +270,7 @@ namespace driver { unsigned getNumArgs() const { return NumArgs; } - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::MultiArgClass; @@ -282,7 +285,7 @@ namespace driver { JoinedOrSeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::JoinedOrSeparateClass; @@ -297,7 +300,7 @@ namespace driver { JoinedAndSeparateOption(OptSpecifier ID, const char *Name, const OptionGroup *Group, const Option *Alias); - virtual Arg *accept(const InputArgList &Args, unsigned &Index) const; + virtual Arg *accept(const ArgList &Args, unsigned &Index) const; static bool classof(const Option *O) { return O->getKind() == Option::JoinedAndSeparateClass; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index a9a52c0..96ec122 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -124,11 +124,11 @@ def C : Flag<"-C">; def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>; def E : Flag<"-E">, Flags<[DriverOption]>, HelpText<"Only run the preprocessor">; -def F : JoinedOrSeparate<"-F">; +def F : JoinedOrSeparate<"-F">, Flags<[RenderJoined]>; def H : Flag<"-H">; def I_ : Flag<"-I-">, Group<I_Group>; def I : JoinedOrSeparate<"-I">, Group<I_Group>; -def L : JoinedOrSeparate<"-L">; +def L : JoinedOrSeparate<"-L">, Flags<[RenderJoined]>; def MD : Flag<"-MD">, Group<M_Group>; def MF : JoinedOrSeparate<"-MF">, Group<M_Group>; def MG : Flag<"-MG">, Group<M_Group>; @@ -244,6 +244,7 @@ def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>; def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>; def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>; def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>; +def fcaret_diagnostics : Flag<"-fcaret-diagnostics">, Group<f_Group>; def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">; def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>; @@ -267,6 +268,8 @@ def fencoding_EQ : Joined<"-fencoding=">, 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>; +def ffast_math : Flag<"-ffast-math">, Group<clang_ignored_f_Group>; +def ffinite_math_only : Flag<"-ffinite-math-only">, Group<clang_ignored_f_Group>; def ffreestanding : Flag<"-ffreestanding">, Group<f_Group>; def fgnu_keywords : Flag<"-fgnu-keywords">, Group<f_Group>; def fgnu_runtime : Flag<"-fgnu-runtime">, Group<f_Group>; @@ -275,6 +278,7 @@ def filelist : Separate<"-filelist">, Flags<[LinkerInput]>; def findirect_virtual_calls : Flag<"-findirect-virtual-calls">, Group<f_Group>; def finline_functions : Flag<"-finline-functions">, Group<clang_ignored_f_Group>; def finline : Flag<"-finline">, Group<clang_ignored_f_Group>; +def finstrument_functions : Flag<"-finstrument-functions">, Group<f_Group>; def fkeep_inline_functions : Flag<"-fkeep-inline-functions">, Group<clang_ignored_f_Group>; def flat__namespace : Flag<"-flat_namespace">; def flax_vector_conversions : Flag<"-flax-vector-conversions">, Group<f_Group>; @@ -307,6 +311,7 @@ def fno_diagnostics_show_option : Flag<"-fno-diagnostics-show-option">, Group<f_ def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">, Group<f_Group>; def fno_eliminate_unused_debug_symbols : Flag<"-fno-eliminate-unused-debug-symbols">, Group<f_Group>; def fno_exceptions : Flag<"-fno-exceptions">, Group<f_Group>; +def fno_finite_math_only : Flag<"-fno-finite-math-only">, Group<clang_ignored_f_Group>; def fno_gnu_keywords : Flag<"-fno-gnu-keywords">, Group<f_Group>; def fno_inline_functions : Flag<"-fno-inline-functions">, Group<clang_ignored_f_Group>; def fno_inline : Flag<"-fno-inline">, Group<clang_ignored_f_Group>; @@ -321,6 +326,7 @@ def fno_pascal_strings : Flag<"-fno-pascal-strings">, Group<f_Group>; def fno_rtti : Flag<"-fno-rtti">, Group<f_Group>; def fno_show_column : Flag<"-fno-show-column">, Group<f_Group>; 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<clang_ignored_f_Group>; def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">, Group<f_Group>; @@ -358,7 +364,9 @@ def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group> def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>; def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>; def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>; +def fshow_overloads_EQ : Joined<"-fshow-overloads=">, Group<f_Group>; def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>; +def fspell_checking : Flag<"-fspell-checking">, Group<f_Group>; def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>; def fsigned_char : Flag<"-fsigned-char">, Group<f_Group>; def fstack_protector_all : Flag<"-fstack-protector-all">, Group<f_Group>; @@ -381,6 +389,8 @@ def funwind_tables : Flag<"-funwind-tables">, Group<f_Group>; def fuse_cxa_atexit : Flag<"-fuse-cxa-atexit">, Group<f_Group>; def fverbose_asm : Flag<"-fverbose-asm">, Group<f_Group>; def fvisibility_EQ : Joined<"-fvisibility=">, Group<f_Group>; +def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">, Group<f_Group>; +def fwrapv : Flag<"-fwrapv">, Group<f_Group>; def fwritable_strings : Flag<"-fwritable-strings">, Group<f_Group>; def fzero_initialized_in_bss : Flag<"-fzero-initialized-in-bss">, Group<f_Group>; def ffunction_sections: Flag <"-ffunction-sections">, Group<f_Group>; @@ -427,6 +437,7 @@ def mfloat_abi_EQ : Joined<"-mfloat-abi=">, Group<m_Group>; 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>, Flags<[DriverOption]>; +def mios_version_min_EQ : Joined<"-mios-version-min=">, Alias<miphoneos_version_min_EQ>; def mkernel : Flag<"-mkernel">, Group<m_Group>; def mllvm : Separate<"-mllvm">; def mmacosx_version_min_EQ : Joined<"-mmacosx-version-min=">, Group<m_Group>, Flags<[DriverOption]>; @@ -453,6 +464,8 @@ def mno_thumb : Flag<"-mno-thumb">, Group<m_Group>; def marm : Flag<"-marm">, Alias<mno_thumb>; def mno_warn_nonportable_cfstrings : Flag<"-mno-warn-nonportable-cfstrings">, Group<m_Group>; +def mno_omit_leaf_frame_pointer : Flag<"-mno-omit-leaf-frame-pointer">, Group<f_Group>; +def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">, Group<f_Group>; def mpascal_strings : Flag<"-mpascal-strings">, Group<m_Group>; def mred_zone : Flag<"-mred-zone">, Group<m_Group>; def mrelax_all : Flag<"-mrelax-all">, Group<m_Group>; @@ -585,7 +598,7 @@ def y : Joined<"-y">; // options. def _CLASSPATH_EQ : Joined<"--CLASSPATH=">, Alias<fclasspath_EQ>; -def _CLASSPATH : Separate<"--CLASSPATH">, Alias<fclasspath_EQ>, Flags<[RenderJoined]>; +def _CLASSPATH : Separate<"--CLASSPATH">, Alias<fclasspath_EQ>; def _all_warnings : Flag<"--all-warnings">, Alias<Wall>; def _analyze_auto : Flag<"--analyze-auto">, Flags<[DriverOption]>; def _analyzer_no_default_checks : Flag<"--analyzer-no-default-checks">, Flags<[DriverOption]>; @@ -594,80 +607,80 @@ def _analyze : Flag<"--analyze">, Flags<[DriverOption]>, HelpText<"Run the static analyzer">; def _ansi : Flag<"--ansi">, Alias<ansi>; def _assemble : Flag<"--assemble">, Alias<S>; -def _assert_EQ : Joined<"--assert=">, Alias<A>, Flags<[RenderSeparate]>; +def _assert_EQ : Joined<"--assert=">, Alias<A>; def _assert : Separate<"--assert">, Alias<A>; def _bootclasspath_EQ : Joined<"--bootclasspath=">, Alias<fbootclasspath_EQ>; -def _bootclasspath : Separate<"--bootclasspath">, Alias<fbootclasspath_EQ>, Flags<[RenderJoined]>; +def _bootclasspath : Separate<"--bootclasspath">, Alias<fbootclasspath_EQ>; def _classpath_EQ : Joined<"--classpath=">, Alias<fclasspath_EQ>; -def _classpath : Separate<"--classpath">, Alias<fclasspath_EQ>, Flags<[RenderJoined]>; -def _combine : Flag<"--combine">, Alias<combine>, Flags<[Unsupported]>; +def _classpath : Separate<"--classpath">, Alias<fclasspath_EQ>; +def _combine : Flag<"--combine">, Alias<combine>; def _comments_in_macros : Flag<"--comments-in-macros">, Alias<CC>; def _comments : Flag<"--comments">, Alias<C>; def _compile : Flag<"--compile">, Alias<c>; def _constant_cfstrings : Flag<"--constant-cfstrings">; def _coverage : Flag<"--coverage">, Alias<coverage>; -def _debug_EQ : Joined<"--debug=">, Alias<g_Flag>, Flags<[Unsupported]>; -def _debug : Flag<"--debug">, Alias<g_Flag>, Flags<[Unsupported]>; +def _debug_EQ : Joined<"--debug=">, Alias<g_Flag>; +def _debug : Flag<"--debug">, Alias<g_Flag>; def _define_macro_EQ : Joined<"--define-macro=">, Alias<D>; -def _define_macro : Separate<"--define-macro">, Alias<D>, Flags<[RenderJoined]>; +def _define_macro : Separate<"--define-macro">, Alias<D>; def _dependencies : Flag<"--dependencies">, Alias<M>; def _encoding_EQ : Joined<"--encoding=">, Alias<fencoding_EQ>; -def _encoding : Separate<"--encoding">, Alias<fencoding_EQ>, Flags<[RenderJoined]>; +def _encoding : Separate<"--encoding">, Alias<fencoding_EQ>; def _entry : Flag<"--entry">, Alias<e>; def _extdirs_EQ : Joined<"--extdirs=">, Alias<fextdirs_EQ>; -def _extdirs : Separate<"--extdirs">, Alias<fextdirs_EQ>, Flags<[RenderJoined]>; +def _extdirs : Separate<"--extdirs">, Alias<fextdirs_EQ>; def _extra_warnings : Flag<"--extra-warnings">, Alias<W_Joined>; -def _for_linker_EQ : Joined<"--for-linker=">, Alias<Xlinker>, Flags<[LinkerInput, RenderAsInput, RenderSeparate]>; -def _for_linker : Separate<"--for-linker">, Alias<Xlinker>, Flags<[LinkerInput, RenderAsInput]>; -def _force_link_EQ : Joined<"--force-link=">, Alias<u>, Flags<[RenderSeparate]>; +def _for_linker_EQ : Joined<"--for-linker=">, Alias<Xlinker>; +def _for_linker : Separate<"--for-linker">, Alias<Xlinker>; +def _force_link_EQ : Joined<"--force-link=">, Alias<u>; def _force_link : Separate<"--force-link">, Alias<u>; def _help_hidden : Flag<"--help-hidden">; def _help : Flag<"--help">, HelpText<"Display available options">; -def _imacros_EQ : Joined<"--imacros=">, Alias<imacros>, Flags<[RenderSeparate]>; +def _imacros_EQ : Joined<"--imacros=">, Alias<imacros>; def _imacros : Separate<"--imacros">, Alias<imacros>; def _include_barrier : Flag<"--include-barrier">, Alias<I_>; -def _include_directory_after_EQ : Joined<"--include-directory-after=">, Alias<idirafter>, Flags<[RenderSeparate]>; +def _include_directory_after_EQ : Joined<"--include-directory-after=">, Alias<idirafter>; def _include_directory_after : Separate<"--include-directory-after">, Alias<idirafter>; def _include_directory_EQ : Joined<"--include-directory=">, Alias<I>; -def _include_directory : Separate<"--include-directory">, Alias<I>, Flags<[RenderJoined]>; -def _include_prefix_EQ : Joined<"--include-prefix=">, Alias<iprefix>, Flags<[RenderSeparate]>; +def _include_directory : Separate<"--include-directory">, Alias<I>; +def _include_prefix_EQ : Joined<"--include-prefix=">, Alias<iprefix>; def _include_prefix : Separate<"--include-prefix">, Alias<iprefix>; -def _include_with_prefix_after_EQ : Joined<"--include-with-prefix-after=">, Alias<iwithprefix>, Flags<[RenderSeparate]>; +def _include_with_prefix_after_EQ : Joined<"--include-with-prefix-after=">, Alias<iwithprefix>; def _include_with_prefix_after : Separate<"--include-with-prefix-after">, Alias<iwithprefix>; -def _include_with_prefix_before_EQ : Joined<"--include-with-prefix-before=">, Alias<iwithprefixbefore>, Flags<[RenderSeparate]>; +def _include_with_prefix_before_EQ : Joined<"--include-with-prefix-before=">, Alias<iwithprefixbefore>; def _include_with_prefix_before : Separate<"--include-with-prefix-before">, Alias<iwithprefixbefore>; -def _include_with_prefix_EQ : Joined<"--include-with-prefix=">, Alias<iwithprefix>, Flags<[RenderSeparate]>; +def _include_with_prefix_EQ : Joined<"--include-with-prefix=">, Alias<iwithprefix>; def _include_with_prefix : Separate<"--include-with-prefix">, Alias<iwithprefix>; -def _include_EQ : Joined<"--include=">, Alias<include_>, Flags<[RenderSeparate]>; +def _include_EQ : Joined<"--include=">, Alias<include_>; def _include : Separate<"--include">, Alias<include_>; -def _language_EQ : Joined<"--language=">, Alias<x>, Flags<[RenderSeparate]>; +def _language_EQ : Joined<"--language=">, Alias<x>; def _language : Separate<"--language">, Alias<x>; -def _library_directory_EQ : Joined<"--library-directory=">, Alias<L>, Flags<[RenderSeparate]>; +def _library_directory_EQ : Joined<"--library-directory=">, Alias<L>; def _library_directory : Separate<"--library-directory">, Alias<L>; -def _machine__EQ : Joined<"--machine-=">, Alias<m_Joined>, Flags<[Unsupported]>; -def _machine_ : Joined<"--machine-">, Alias<m_Joined>, Flags<[Unsupported]>; +def _machine__EQ : Joined<"--machine-=">, Alias<m_Joined>; +def _machine_ : Joined<"--machine-">, Alias<m_Joined>; def _machine_EQ : Joined<"--machine=">, Alias<m_Joined>; -def _machine : Separate<"--machine">, Alias<m_Joined>, Flags<[RenderJoined]>; +def _machine : Separate<"--machine">, Alias<m_Joined>; def _no_integrated_cpp : Flag<"--no-integrated-cpp">, Alias<no_integrated_cpp>; def _no_line_commands : Flag<"--no-line-commands">, Alias<P>; def _no_standard_includes : Flag<"--no-standard-includes">, Alias<nostdinc>; def _no_standard_libraries : Flag<"--no-standard-libraries">, Alias<nostdlib>; def _no_undefined : Flag<"--no-undefined">, Flags<[LinkerInput]>; def _no_warnings : Flag<"--no-warnings">, Alias<w>; -def _optimize_EQ : Joined<"--optimize=">, Alias<O>, Flags<[Unsupported]>; -def _optimize : Flag<"--optimize">, Alias<O>, Flags<[Unsupported]>; +def _optimize_EQ : Joined<"--optimize=">, Alias<O>; +def _optimize : Flag<"--optimize">, Alias<O>; def _output_class_directory_EQ : Joined<"--output-class-directory=">, Alias<foutput_class_dir_EQ>; -def _output_class_directory : Separate<"--output-class-directory">, Alias<foutput_class_dir_EQ>, Flags<[RenderJoined]>; -def _output_EQ : Joined<"--output=">, Alias<o>, Flags<[RenderSeparate]>; +def _output_class_directory : Separate<"--output-class-directory">, Alias<foutput_class_dir_EQ>; +def _output_EQ : Joined<"--output=">, Alias<o>; def _output : Separate<"--output">, Alias<o>; def _param : Separate<"--param">; -def _param_EQ : Joined<"--param=">, Alias<_param>, Flags<[RenderSeparate]>; +def _param_EQ : Joined<"--param=">, Alias<_param>; def _pass_exit_codes : Flag<"--pass-exit-codes">, Alias<pass_exit_codes>; def _pedantic_errors : Flag<"--pedantic-errors">, Alias<pedantic_errors>; def _pedantic : Flag<"--pedantic">, Alias<pedantic>; -def _pipe : Flag<"--pipe">, Alias<pipe>, Flags<[DriverOption]>; -def _prefix_EQ : Joined<"--prefix=">, Alias<B>, Flags<[RenderSeparate]>; +def _pipe : Flag<"--pipe">, Alias<pipe>; +def _prefix_EQ : Joined<"--prefix=">, Alias<B>; def _prefix : Separate<"--prefix">, Alias<B>; def _preprocess : Flag<"--preprocess">, Alias<E>; def _print_diagnostic_categories : Flag<"--print-diagnostic-categories">; @@ -686,30 +699,33 @@ def _profile : Flag<"--profile">, Alias<p>; def _relocatable_pch : Flag<"--relocatable-pch">, HelpText<"Build a relocatable precompiled header">; def _resource_EQ : Joined<"--resource=">, Alias<fcompile_resource_EQ>; -def _resource : Separate<"--resource">, Alias<fcompile_resource_EQ>, Flags<[RenderJoined]>; +def _resource : Separate<"--resource">, Alias<fcompile_resource_EQ>; def _save_temps : Flag<"--save-temps">, Alias<save_temps>; def _shared : Flag<"--shared">, Alias<shared>; def _signed_char : Flag<"--signed-char">, Alias<fsigned_char>; -def _specs_EQ : Joined<"--specs=">, Alias<specs_EQ>, Flags<[Unsupported]>; -def _specs : Separate<"--specs">, Alias<specs_EQ>, Flags<[RenderJoined, Unsupported]>; +def _specs_EQ : Joined<"--specs=">, Alias<specs_EQ>; +def _specs : Separate<"--specs">, Alias<specs_EQ>; def _static : Flag<"--static">, Alias<static>; def _std_EQ : Joined<"--std=">, Alias<std_EQ>; -def _std : Separate<"--std">, Alias<std_EQ>, Flags<[RenderJoined]>; +def _std : Separate<"--std">, Alias<std_EQ>; def _sysroot_EQ : Joined<"--sysroot=">; -def _sysroot : Separate<"--sysroot">, Alias<_sysroot_EQ>, Flags<[RenderJoined]>; +def _sysroot : Separate<"--sysroot">, Alias<_sysroot_EQ>; def _target_help : Flag<"--target-help">; def _trace_includes : Flag<"--trace-includes">, Alias<H>; def _traditional_cpp : Flag<"--traditional-cpp">, Alias<traditional_cpp>; def _traditional : Flag<"--traditional">, Alias<traditional>; def _trigraphs : Flag<"--trigraphs">, Alias<trigraphs>; def _undefine_macro_EQ : Joined<"--undefine-macro=">, Alias<U>; -def _undefine_macro : Separate<"--undefine-macro">, Alias<U>, Flags<[RenderJoined]>; +def _undefine_macro : Separate<"--undefine-macro">, Alias<U>; def _unsigned_char : Flag<"--unsigned-char">, Alias<funsigned_char>; def _user_dependencies : Flag<"--user-dependencies">, Alias<MM>; def _verbose : Flag<"--verbose">, Alias<v>; def _version : Flag<"--version">; -def _warn__EQ : Joined<"--warn-=">, Alias<W_Joined>, Flags<[Unsupported]>; -def _warn_ : Joined<"--warn-">, Alias<W_Joined>, Flags<[Unsupported]>; +def _warn__EQ : Joined<"--warn-=">, Alias<W_Joined>; +def _warn_ : Joined<"--warn-">, Alias<W_Joined>; def _write_dependencies : Flag<"--write-dependencies">, Alias<MD>; def _write_user_dependencies : Flag<"--write-user-dependencies">, Alias<MMD>; -def _ : Joined<"--">, Alias<f>, Flags<[Unsupported]>; +def _ : Joined<"--">, Flags<[Unsupported]>; + +// Special internal option to handle -Xlinker --no-demangle. +def Z_Xlinker__no_demangle : Flag<"-Z-Xlinker-no-demangle">, Flags<[Unsupported]>; diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 1a8ae77..2cec22a 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -70,11 +70,14 @@ public: // Tool access. /// TranslateArgs - Create a new derived argument list for any argument - /// translations this ToolChain may wish to perform. + /// translations this ToolChain may wish to perform, or 0 if no tool chain + /// specific translations are needed. /// /// \param BoundArch - The bound architecture name, or 0. - virtual DerivedArgList *TranslateArgs(InputArgList &Args, - const char *BoundArch) const = 0; + virtual DerivedArgList *TranslateArgs(const DerivedArgList &Args, + const char *BoundArch) const { + 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; diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def index 61a5043..d3a3d29 100644 --- a/include/clang/Driver/Types.def +++ b/include/clang/Driver/Types.def @@ -67,15 +67,21 @@ TYPE("f95", PP_Fortran, INVALID, 0, "u") TYPE("f95-cpp-input", Fortran, PP_Fortran, 0, "u") TYPE("java", Java, INVALID, 0, "u") +// LLVM IR/LTO types. We define separate types for IR and LTO because LTO +// outputs should use the standard suffixes. +TYPE("ir", LLVM_IR, INVALID, "ll", "") +TYPE("ir", LLVM_BC, INVALID, "bc", "") +TYPE("lto-ir", LTO_IR, INVALID, "s", "") +TYPE("lto-bc", LTO_BC, INVALID, "o", "") + // Misc. TYPE("ast", AST, INVALID, "ast", "u") -TYPE("llvm-asm", LLVMAsm, INVALID, "s", "") -TYPE("llvm-bc", LLVMBC, INVALID, "o", "") TYPE("plist", Plist, INVALID, "plist", "") TYPE("rewritten-objc", RewrittenObjC,INVALID, "cpp", "") TYPE("precompiled-header", PCH, INVALID, "gch", "A") TYPE("object", Object, INVALID, "o", "") TYPE("treelang", Treelang, INVALID, 0, "u") TYPE("image", Image, INVALID, "out", "") +TYPE("dSYM", dSYM, INVALID, "dSYM", "A") TYPE("dependencies", Dependencies, INVALID, "d", "") TYPE("none", Nothing, INVALID, 0, "u") diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index d933230..9187529 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -59,6 +59,10 @@ namespace types { /// isAcceptedByClang - Can clang handle this input type. bool isAcceptedByClang(ID Id); + /// isOnlyAcceptedByClang - Is clang the only compiler that can handle this + /// input type. + bool isOnlyAcceptedByClang(ID Id); + /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers). bool isCXX(ID Id); diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 9163a20..5718979 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -29,6 +29,7 @@ class CodeGenOptions; class Diagnostic; class FileManager; class LangOptions; +class PCHReader; class Preprocessor; class TargetOptions; @@ -57,25 +58,12 @@ ASTConsumer *CreateASTViewer(); // to stderr; this is intended for debugging. ASTConsumer *CreateDeclContextPrinter(); -// ObjC rewriter: attempts tp rewrite ObjC constructs into pure C code. -// This is considered experimental, and only works with Apple's ObjC runtime. -ASTConsumer *CreateObjCRewriter(const std::string &InFile, - llvm::raw_ostream *OS, - Diagnostic &Diags, - const LangOptions &LOpts, - bool SilenceRewriteMacroWarning); - -/// CreateHTMLPrinter - Create an AST consumer which rewrites source code to -/// HTML with syntax highlighting suitable for viewing in a web-browser. -ASTConsumer *CreateHTMLPrinter(llvm::raw_ostream *OS, Preprocessor &PP, - bool SyntaxHighlight = true, - bool HighlightMacros = true); - // PCH generator: generates a precompiled header file; this file can be used // later with the PCHReader (clang -cc1 option -include-pch) to speed up compile // times. ASTConsumer *CreatePCHGenerator(const Preprocessor &PP, llvm::raw_ostream *OS, + const PCHReader *Chain, const char *isysroot = 0); // Inheritance viewer: for C++ code, creates a graph of the inheritance diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalyzerOptions.h index 2cbdf36..ab4aed9 100644 --- a/include/clang/Frontend/AnalysisConsumer.h +++ b/include/clang/Frontend/AnalyzerOptions.h @@ -1,4 +1,4 @@ -//===--- AnalysisConsumer.h - Front-end Analysis Engine Hooks ---*- C++ -*-===// +//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,13 +7,13 @@ // //===----------------------------------------------------------------------===// // -// This header contains the functions necessary for a front-end to run various -// analyses. +// This header contains the structures necessary for a front-end to specify +// various analyses. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H -#define LLVM_CLANG_FRONTEND_ANALYSISCONSUMER_H +#ifndef LLVM_CLANG_FRONTEND_ANALYZEROPTIONS_H +#define LLVM_CLANG_FRONTEND_ANALYZEROPTIONS_H #include <string> #include <vector> @@ -72,6 +72,7 @@ public: unsigned VisualizeEGUbi : 1; unsigned EnableExperimentalChecks : 1; unsigned EnableExperimentalInternalChecks : 1; + unsigned EnableIdempotentOperationChecker : 1; unsigned InlineCall : 1; public: @@ -92,13 +93,6 @@ public: } }; -/// CreateAnalysisConsumer - Creates an ASTConsumer to run various code -/// analysis passes. (The set of analyses run is controlled by command-line -/// options.) -ASTConsumer* CreateAnalysisConsumer(const Preprocessor &pp, - const std::string &output, - const AnalyzerOptions& Opts); - } #endif diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 6241230..2918f4e 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H -#define LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H +#ifndef LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H +#define LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H #include <string> @@ -39,7 +39,7 @@ public: unsigned CXXCtorDtorAliases: 1; /// Emit complete ctors/dtors as linker /// aliases to base ctors when possible. unsigned DataSections : 1; /// Set when -fdata-sections is enabled - unsigned DebugInfo : 1; /// Should generate deubg info (-g). + unsigned DebugInfo : 1; /// Should generate debug info (-g). unsigned DisableFPElim : 1; /// Set when -fomit-frame-pointer is enabled. unsigned DisableLLVMOpts : 1; /// Don't run any optimizations, for use in /// getting .bc files that correspond to the @@ -47,14 +47,18 @@ public: /// done. unsigned DisableRedZone : 1; /// Set when -mno-red-zone is enabled. unsigned FunctionSections : 1; /// Set when -ffunction-sections is enabled + unsigned InstrumentFunctions : 1; /// Set when -finstrument-functions is enabled unsigned MergeAllConstants : 1; /// Merge identical constants. unsigned NoCommon : 1; /// Set when -fno-common or C++ is enabled. unsigned NoImplicitFloat : 1; /// Set when -mno-implicit-float is enabled. unsigned NoZeroInitializedInBSS : 1; /// -fno-zero-initialized-in-bss unsigned ObjCDispatchMethod : 2; /// Method of Objective-C dispatch to use. + 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 RelaxAll : 1; /// Relax all machine code instructions. + unsigned SimplifyLibCalls : 1; /// Set when -fbuiltin is enabled. unsigned SoftFloat : 1; /// -soft-float. unsigned TimePasses : 1; /// Set when -ftime-report is enabled. unsigned UnitAtATime : 1; /// Unused. For mirroring GCC optimization @@ -63,6 +67,9 @@ public: unsigned UnwindTables : 1; /// Emit unwind tables. unsigned VerifyModule : 1; /// Control whether the module should be run /// through the LLVM Verifier. + unsigned EmitDeclMetadata : 1; /// Emit special metadata indicating what Decl* + /// various IR entities came from. Only useful + /// when running CodeGen as a subroutine. /// The code model to use (-mcmodel). std::string CodeModel; @@ -107,15 +114,18 @@ public: NoImplicitFloat = 0; NoZeroInitializedInBSS = 0; ObjCDispatchMethod = Legacy; + OmitLeafFramePointer = 0; OptimizationLevel = 0; OptimizeSize = 0; RelaxAll = 0; + SimplifyLibCalls = 1; SoftFloat = 0; TimePasses = 0; UnitAtATime = 1; UnrollLoops = 0; UnwindTables = 0; VerifyModule = 1; + EmitDeclMetadata = 0; Inlining = NoInlining; RelocationModel = "pic"; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 06dc800..54ce8bf 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -34,6 +34,7 @@ class DiagnosticClient; class ExternalASTSource; class FileManager; class FrontendAction; +class PCHReader; class Preprocessor; class SourceManager; class TargetInfo; @@ -96,6 +97,9 @@ class CompilerInstance { /// The list of active output files. std::list< std::pair<std::string, llvm::raw_ostream*> > OutputFiles; + /// The PCH reader. Not owned; the ASTContext owns this. + PCHReader *Reader; + void operator=(const CompilerInstance &); // DO NOT IMPLEMENT CompilerInstance(const CompilerInstance&); // DO NOT IMPLEMENT public: @@ -507,6 +511,9 @@ public: createPCHExternalASTSource(llvm::StringRef Path, const std::string &Sysroot, Preprocessor &PP, ASTContext &Context); + /// Get the PCH reader, if any. + PCHReader *getPCHReader() { return Reader; } + /// Create a code completion consumer using the invocation; note that this /// will cause the source manager to truncate the input source file at the /// completion point. diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index f5a9053..d558ad3 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -12,8 +12,8 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/TargetOptions.h" -#include "clang/CodeGen/CodeGenOptions.h" -#include "clang/Frontend/AnalysisConsumer.h" +#include "clang/Frontend/AnalyzerOptions.h" +#include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/DependencyOutputOptions.h" #include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/FrontendOptions.h" diff --git a/include/clang/Frontend/DiagnosticOptions.h b/include/clang/Frontend/DiagnosticOptions.h index 8eb66e5..516dc67 100644 --- a/include/clang/Frontend/DiagnosticOptions.h +++ b/include/clang/Frontend/DiagnosticOptions.h @@ -10,6 +10,8 @@ #ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H #define LLVM_CLANG_FRONTEND_DIAGNOSTICOPTIONS_H +#include "clang/Basic/Diagnostic.h" + #include <string> #include <vector> @@ -33,6 +35,8 @@ public: unsigned ShowCategories : 2; /// Show categories: 0 -> none, 1 -> Number, /// 2 -> Full Name. unsigned ShowColors : 1; /// Show diagnostics with ANSI color sequences. + unsigned ShowOverloads : 1; /// Overload candidates to show. Values from + /// Diagnostic::OverloadsShown unsigned VerifyDiagnostics: 1; /// Check that diagnostics match the expected /// diagnostics, indicated by markers in the /// input source file. @@ -72,6 +76,7 @@ public: PedanticErrors = 0; ShowCarets = 1; ShowColors = 0; + ShowOverloads = Diagnostic::Ovl_All; ShowColumn = 1; ShowFixits = 1; ShowLocation = 1; diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index 7b7db37..f6a68bf 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -13,17 +13,40 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" #include <string> +#include <vector> + +namespace llvm { + class raw_ostream; +} namespace clang { -class ASTUnit; class ASTConsumer; -class CompilerInstance; class ASTMergeAction; +class ASTUnit; +class CompilerInstance; + +enum InputKind { + IK_None, + IK_Asm, + IK_C, + IK_CXX, + IK_ObjC, + IK_ObjCXX, + IK_PreprocessedC, + IK_PreprocessedCXX, + IK_PreprocessedObjC, + IK_PreprocessedObjCXX, + IK_OpenCL, + IK_AST, + IK_LLVM_IR +}; + /// FrontendAction - Abstract base class for actions which can be performed by /// the frontend. class FrontendAction { std::string CurrentFile; + InputKind CurrentFileKind; llvm::OwningPtr<ASTUnit> CurrentASTUnit; CompilerInstance *Instance; friend class ASTMergeAction; @@ -101,6 +124,11 @@ public: return CurrentFile; } + InputKind getCurrentFileKind() const { + assert(!CurrentFile.empty() && "No current file!"); + return CurrentFileKind; + } + ASTUnit &getCurrentASTUnit() const { assert(!CurrentASTUnit && "No current AST unit!"); return *CurrentASTUnit; @@ -110,7 +138,7 @@ public: return CurrentASTUnit.take(); } - void setCurrentFile(llvm::StringRef Value, ASTUnit *AST = 0); + void setCurrentFile(llvm::StringRef Value, InputKind Kind, ASTUnit *AST = 0); /// @} /// @name Supported Modes @@ -128,8 +156,11 @@ public: /// hasPCHSupport - Does this action support use with PCH? virtual bool hasPCHSupport() const { return !usesPreprocessorOnly(); } - /// hasASTSupport - Does this action support use with AST files? - virtual bool hasASTSupport() const { return !usesPreprocessorOnly(); } + /// hasASTFileSupport - Does this action support use with AST files? + virtual bool hasASTFileSupport() const { return !usesPreprocessorOnly(); } + + /// hasIRSupport - Does this action support use with IR files? + virtual bool hasIRSupport() const { return false; } /// hasCodeCompletionSupport - Does this action support use with code /// completion? @@ -150,17 +181,18 @@ public: /// \param Filename - The input filename, which will be made available to /// clients via \see getCurrentFile(). /// - /// \param IsAST - Indicates whether this is an AST input. AST inputs require - /// special handling, since the AST file itself contains several objects which - /// would normally be owned by the CompilerInstance. When processing AST input - /// files, these objects should generally not be initialized in the - /// CompilerInstance -- they will automatically be shared with the AST file in - /// between \see BeginSourceFile() and \see EndSourceFile(). + /// \param InputKind - The type of input. Some input kinds are handled + /// specially, for example AST inputs, since the AST file itself contains + /// several objects which would normally be owned by the + /// CompilerInstance. When processing AST input files, these objects should + /// generally not be initialized in the CompilerInstance -- they will + /// automatically be shared with the AST file in between \see + /// BeginSourceFile() and \see EndSourceFile(). /// /// \return True on success; the compilation of this file should be aborted /// and neither Execute nor EndSourceFile should be called. bool BeginSourceFile(CompilerInstance &CI, llvm::StringRef Filename, - bool IsAST = false); + InputKind Kind); /// Execute - Set the source managers main input file, and run the action. void Execute(); @@ -175,6 +207,7 @@ public: /// ASTFrontendAction - Abstract base class to use for AST consumer based /// frontend actions. class ASTFrontendAction : public FrontendAction { +protected: /// ExecuteAction - Implement the ExecuteAction interface by running Sema on /// the already initialized AST consumer. /// @@ -186,6 +219,16 @@ public: virtual bool usesPreprocessorOnly() const { return false; } }; +class PluginASTAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile) = 0; + +public: + virtual bool ParseArgs(const std::vector<std::string>& arg) = 0; + virtual void PrintHelp(llvm::raw_ostream&) = 0; +}; + /// PreprocessorFrontendAction - Abstract base class to use for preprocessor /// based frontend actions. class PreprocessorFrontendAction : public FrontendAction { diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index cee1c1d..26262cf 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -15,8 +15,6 @@ #include <vector> namespace clang { -class FixItRewriter; -class FixItPathRewriter; //===----------------------------------------------------------------------===// // Custom Consumer Actions @@ -38,12 +36,6 @@ public: // AST Consumer Actions //===----------------------------------------------------------------------===// -class AnalysisAction : public ASTFrontendAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); -}; - class ASTPrintAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, @@ -74,26 +66,6 @@ protected: llvm::StringRef InFile); }; -class FixItAction : public ASTFrontendAction { -protected: - llvm::OwningPtr<FixItRewriter> Rewriter; - llvm::OwningPtr<FixItPathRewriter> PathRewriter; - - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); - - virtual bool BeginSourceFileAction(CompilerInstance &CI, - llvm::StringRef Filename); - - virtual void EndSourceFileAction(); - - virtual bool hasASTSupport() const { return false; } - -public: - FixItAction(); - ~FixItAction(); -}; - class GeneratePCHAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, @@ -101,13 +73,7 @@ protected: virtual bool usesCompleteTranslationUnit() { return false; } - virtual bool hasASTSupport() const { return false; } -}; - -class HTMLPrintAction : public ASTFrontendAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); + virtual bool hasASTFileSupport() const { return false; } }; class InheritanceViewAction : public ASTFrontendAction { @@ -116,12 +82,6 @@ protected: llvm::StringRef InFile); }; -class RewriteObjCAction : public ASTFrontendAction { -protected: - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - llvm::StringRef InFile); -}; - class SyntaxOnlyAction : public ASTFrontendAction { protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, @@ -170,7 +130,7 @@ public: virtual bool usesPreprocessorOnly() const; virtual bool usesCompleteTranslationUnit(); virtual bool hasPCHSupport() const; - virtual bool hasASTSupport() const; + virtual bool hasASTFileSupport() const; virtual bool hasCodeCompletionSupport() const; }; @@ -215,16 +175,6 @@ protected: virtual bool hasPCHSupport() const { return true; } }; -class RewriteMacrosAction : public PreprocessorFrontendAction { -protected: - void ExecuteAction(); -}; - -class RewriteTestAction : public PreprocessorFrontendAction { -protected: - void ExecuteAction(); -}; - } // end namespace clang #endif diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index c43e680..4010ea6 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H #include "clang/Frontend/CommandLineSourceLoc.h" +#include "clang/Frontend/FrontendAction.h" #include "llvm/ADT/StringRef.h" #include <string> #include <vector> @@ -55,27 +56,15 @@ namespace frontend { /// FrontendOptions - Options for controlling the behavior of the frontend. class FrontendOptions { public: - enum InputKind { - IK_None, - IK_Asm, - IK_C, - IK_CXX, - IK_ObjC, - IK_ObjCXX, - IK_PreprocessedC, - IK_PreprocessedCXX, - IK_PreprocessedObjC, - IK_PreprocessedObjCXX, - IK_OpenCL, - IK_AST - }; - unsigned DebugCodeCompletionPrinter : 1; ///< Use the debug printer for code /// completion results. unsigned DisableFree : 1; ///< Disable memory freeing on exit. unsigned RelocatablePCH : 1; ///< When generating PCH files, /// instruct the PCH writer to create /// relocatable PCH files. + unsigned ChainedPCH : 1; ///< When generating PCH files, + /// instruct the PCH writer to create + /// chained PCH files. unsigned ShowHelp : 1; ///< Show the -help text. unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion /// results. @@ -108,6 +97,9 @@ public: /// The name of the action to run when using a plugin action. std::string ActionName; + /// Arg to pass to the plugin + std::vector<std::string> PluginArgs; + /// The list of plugins to load. std::vector<std::string> Plugins; @@ -125,6 +117,7 @@ public: ProgramAction = frontend::ParseSyntaxOnly; ActionName = ""; RelocatablePCH = 0; + ChainedPCH = 0; ShowHelp = 0; ShowMacrosInCodeCompletion = 0; ShowCodePatternsInCodeCompletion = 0; diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h index 8341492..ec925ad 100644 --- a/include/clang/Frontend/FrontendPluginRegistry.h +++ b/include/clang/Frontend/FrontendPluginRegistry.h @@ -16,7 +16,7 @@ namespace clang { /// The frontend plugin registry. -typedef llvm::Registry<FrontendAction> FrontendPluginRegistry; +typedef llvm::Registry<PluginASTAction> FrontendPluginRegistry; } // end namespace clang diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 2493cfd..27a2b7d 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -30,10 +30,10 @@ namespace clang { /// designed for the previous version could not support reading /// the new version), this number should be increased. /// - /// Version 3 of PCH files also requires that the version control branch and + /// Version 4 of PCH files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// PCH files at this time. - const unsigned VERSION_MAJOR = 3; + const unsigned VERSION_MAJOR = 4; /// \brief PCH minor version number supported by this version of /// Clang. @@ -47,7 +47,7 @@ namespace clang { /// \brief An ID number that refers to a declaration in a PCH file. /// - /// The ID numbers of types are consecutive (in order of + /// The ID numbers of declarations are consecutive (in order of /// discovery) and start at 2. 0 is reserved for NULL, and 1 is /// reserved for the translation unit declaration. typedef uint32_t DeclID; @@ -226,7 +226,18 @@ namespace clang { /// \brief Record code for the table of offsets to macro definition /// entries in the preprocessing record. - MACRO_DEFINITION_OFFSETS = 23 + MACRO_DEFINITION_OFFSETS = 23, + + /// \brief Record code for the array of VTable uses. + VTABLE_USES = 24, + + /// \brief Record code for the array of dynamic classes. + DYNAMIC_CLASSES = 25, + + /// \brief Record code for the chained PCH metadata, including the + /// PCH version and the name of the PCH this is chained to. + CHAINED_METADATA = 26 + }; /// \brief Record types used within a source manager block. @@ -417,7 +428,17 @@ namespace clang { /// \brief An InjectedClassNameType record. TYPE_INJECTED_CLASS_NAME = 27, /// \brief An ObjCObjectType record. - TYPE_OBJC_OBJECT = 28 + TYPE_OBJC_OBJECT = 28, + /// \brief An TemplateTypeParmType record. + TYPE_TEMPLATE_TYPE_PARM = 29, + /// \brief An TemplateSpecializationType record. + TYPE_TEMPLATE_SPECIALIZATION = 30, + /// \brief A DependentNameType record. + TYPE_DEPENDENT_NAME = 31, + /// \brief A DependentTemplateSpecializationType record. + TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32, + /// \brief A DependentSizedArrayType record. + TYPE_DEPENDENT_SIZED_ARRAY = 33 }; /// \brief The type IDs for special types constructed by semantic @@ -457,7 +478,9 @@ namespace clang { /// \brief Objective-C "SEL" redefinition type SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 14, /// \brief NSConstantString type - SPECIAL_TYPE_NS_CONSTANT_STRING = 15 + SPECIAL_TYPE_NS_CONSTANT_STRING = 15, + /// \brief Whether __[u]int128_t identifier is installed. + SPECIAL_TYPE_INT128_INSTALLED = 16 }; /// \brief Record codes for each kind of declaration. @@ -562,12 +585,13 @@ namespace clang { DECL_CXX_DESTRUCTOR, /// \brief A CXXConversionDecl record. DECL_CXX_CONVERSION, + /// \brief An AccessSpecDecl record. + DECL_ACCESS_SPEC, // FIXME: Implement serialization for these decl types. This just // allocates the order in which DECL_FRIEND, DECL_FRIEND_TEMPLATE, - DECL_TEMPLATE, DECL_CLASS_TEMPLATE, DECL_CLASS_TEMPLATE_SPECIALIZATION, DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, @@ -641,6 +665,8 @@ namespace clang { EXPR_CHARACTER_LITERAL, /// \brief A ParenExpr record. EXPR_PAREN, + /// \brief A ParenListExpr record. + EXPR_PAREN_LIST, /// \brief A UnaryOperator record. EXPR_UNARY_OPERATOR, /// \brief An OffsetOfExpr record. @@ -736,6 +762,8 @@ namespace clang { EXPR_CXX_MEMBER_CALL, /// \brief A CXXConstructExpr record. EXPR_CXX_CONSTRUCT, + /// \brief A CXXTemporaryObjectExpr record. + EXPR_CXX_TEMPORARY_OBJECT, // \brief A CXXStaticCastExpr record. EXPR_CXX_STATIC_CAST, // \brief A CXXDynamicCastExpr record. @@ -755,11 +783,22 @@ namespace clang { EXPR_CXX_THROW, // CXXThrowExpr EXPR_CXX_DEFAULT_ARG, // CXXDefaultArgExpr EXPR_CXX_BIND_TEMPORARY, // CXXBindTemporaryExpr - // - EXPR_CXX_ZERO_INIT_VALUE, // CXXZeroInitValueExpr + EXPR_CXX_BIND_REFERENCE, // CXXBindReferenceExpr + + EXPR_CXX_SCALAR_VALUE_INIT, // CXXScalarValueInitExpr EXPR_CXX_NEW, // CXXNewExpr + EXPR_CXX_DELETE, // CXXDeleteExpr + EXPR_CXX_PSEUDO_DESTRUCTOR, // CXXPseudoDestructorExpr + + EXPR_CXX_EXPR_WITH_TEMPORARIES, // CXXExprWithTemporaries - EXPR_CXX_EXPR_WITH_TEMPORARIES // CXXExprWithTemporaries + EXPR_CXX_DEPENDENT_SCOPE_MEMBER, // CXXDependentScopeMemberExpr + EXPR_CXX_DEPENDENT_SCOPE_DECL_REF, // DependentScopeDeclRefExpr + EXPR_CXX_UNRESOLVED_CONSTRUCT, // CXXUnresolvedConstructExpr + EXPR_CXX_UNRESOLVED_MEMBER, // UnresolvedMemberExpr + EXPR_CXX_UNRESOLVED_LOOKUP, // UnresolvedLookupExpr + + EXPR_CXX_UNARY_TYPE_TRAIT // UnaryTypeTraitExpr }; /// \brief The kinds of designators that can occur in a diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index e144738..38402732 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -321,7 +321,7 @@ private: /// file. llvm::SmallVector<uint64_t, 16> TentativeDefinitions; - /// \brief The set of tentative definitions stored in the the PCH + /// \brief The set of unused static functions stored in the the PCH /// file. llvm::SmallVector<uint64_t, 16> UnusedStaticFuncs; @@ -333,6 +333,12 @@ private: /// PCH file. llvm::SmallVector<uint64_t, 4> ExtVectorDecls; + /// \brief The set of VTable uses of CXXRecordDecls stored in the PCH file. + llvm::SmallVector<uint64_t, 64> VTableUses; + + /// \brief The set of dynamic CXXRecord declarations stored in the PCH file. + llvm::SmallVector<uint64_t, 16> DynamicClasses; + /// \brief The set of Objective-C category definitions stored in the /// the PCH file. llvm::SmallVector<uint64_t, 4> ObjCCategoryImpls; @@ -447,7 +453,35 @@ private: /// "Interesting" declarations are those that have data that may /// need to be emitted, such as inline function definitions or /// Objective-C protocols. - llvm::SmallVector<Decl *, 16> InterestingDecls; + std::deque<Decl *> InterestingDecls; + + /// \brief When reading a Stmt tree, Stmt operands are placed in this stack. + llvm::SmallVector<Stmt *, 16> StmtStack; + + /// \brief What kind of records we are reading. + enum ReadingKind { + Read_Decl, Read_Type, Read_Stmt + }; + + /// \brief What kind of records we are reading. + ReadingKind ReadingKind; + + /// \brief RAII object to change the reading kind. + class ReadingKindTracker { + PCHReader &Reader; + enum ReadingKind PrevKind; + + ReadingKindTracker(const ReadingKindTracker&); // do not implement + ReadingKindTracker &operator=(const ReadingKindTracker&);// do not implement + + public: + ReadingKindTracker(enum ReadingKind newKind, PCHReader &reader) + : Reader(reader), PrevKind(Reader.ReadingKind) { + Reader.ReadingKind = newKind; + } + + ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; } + }; /// \brief The file ID for the predefines buffer in the PCH file. FileID PCHPredefinesBufferID; @@ -469,6 +503,9 @@ private: /// predefines buffer may contain additional definitions. std::string SuggestedPredefines; + /// \brief Reads a statement from the specified cursor. + Stmt *ReadStmtFromStream(llvm::BitstreamCursor &Cursor); + void MaybeAddSystemRootToFilename(std::string &Filename); PCHReadResult ReadPCHBlock(); @@ -482,6 +519,8 @@ private: void LoadedDecl(unsigned Index, Decl *D); Decl *ReadDeclRecord(uint64_t Offset, unsigned Index); + void PassInterestingDeclsToConsumer(); + /// \brief Produce an error diagnostic and return true. /// /// This routine should only be used for fatal errors that have to @@ -544,7 +583,7 @@ public: void InitializeContext(ASTContext &Context); /// \brief Retrieve the name of the PCH file - const std::string &getFileName() { return FileName; } + const std::string &getFileName() const { return FileName; } /// \brief Retrieve the name of the original source file name const std::string &getOriginalSourceFile() { return OriginalFileName; } @@ -569,30 +608,45 @@ public: GetTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, const RecordData &Record, unsigned &Idx); + /// \brief Reads a TemplateArgumentLoc. + TemplateArgumentLoc ReadTemplateArgumentLoc(const RecordData &Record, + unsigned &Idx); + /// \brief Reads a declarator info from the given record. - virtual TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record, - unsigned &Idx); + TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record, + unsigned &Idx); + + /// \brief Resolve and return the translation unit declaration. + TranslationUnitDecl *GetTranslationUnitDecl(); /// \brief Resolve a type ID into a type, potentially building a new /// type. - virtual QualType GetType(pch::TypeID ID); + QualType GetType(pch::TypeID ID); /// \brief Resolve a declaration ID into a declaration, potentially /// building a new declaration. - virtual Decl *GetDecl(pch::DeclID ID); + Decl *GetDecl(pch::DeclID ID); + virtual Decl *GetExternalDecl(uint32_t ID); /// \brief Resolve the offset of a statement into a statement. /// /// This operation will read a new statement from the external /// source each time it is called, and is meant to be used via a /// LazyOffsetPtr (which is used by Decls for the body of functions, etc). - virtual Stmt *GetDeclStmt(uint64_t Offset); + virtual Stmt *GetExternalDeclStmt(uint64_t Offset); /// ReadBlockAbbrevs - Enter a subblock of the specified BlockID with the /// specified cursor. Read the abbreviations that are at the top of the block /// and then leave the cursor pointing into the block. bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID); + /// \brief Finds all the visible declarations with a given name. + /// The current implementation of this method just loads the entire + /// lookup table as unmaterialized references. + virtual DeclContext::lookup_result + FindExternalVisibleDeclsByName(const DeclContext *DC, + DeclarationName Name); + /// \brief Read all of the declarations lexically stored in a /// declaration context. /// @@ -606,27 +660,8 @@ public: /// /// \returns true if there was an error while reading the /// declarations for this declaration context. - virtual bool ReadDeclsLexicallyInContext(DeclContext *DC, - llvm::SmallVectorImpl<pch::DeclID> &Decls); - - /// \brief Read all of the declarations visible from a declaration - /// context. - /// - /// \param DC The declaration context whose visible declarations - /// will be read. - /// - /// \param Decls A vector of visible declaration structures, - /// providing the mapping from each name visible in the declaration - /// context to the declaration IDs of declarations with that name. - /// - /// \returns true if there was an error while reading the - /// declarations for this declaration context. - /// - /// FIXME: Using this intermediate data structure results in an - /// extraneous copying of the data. Could we pass in a reference to - /// the StoredDeclsMap instead? - virtual bool ReadDeclsVisibleInContext(DeclContext *DC, - llvm::SmallVectorImpl<VisibleDeclaration> & Decls); + virtual bool FindExternalLexicalDecls(const DeclContext *DC, + llvm::SmallVectorImpl<Decl*> &Decls); /// \brief Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. @@ -691,8 +726,8 @@ public: Selector DecodeSelector(unsigned Idx); - virtual Selector GetSelector(uint32_t ID); - virtual uint32_t GetNumKnownSelectors(); + virtual Selector GetExternalSelector(uint32_t ID); + uint32_t GetNumExternalSelectors(); Selector GetSelector(const RecordData &Record, unsigned &Idx) { return DecodeSelector(Record[Idx++]); @@ -704,6 +739,28 @@ public: NestedNameSpecifier *ReadNestedNameSpecifier(const RecordData &Record, unsigned &Idx); + /// \brief Read a template name. + TemplateName ReadTemplateName(const RecordData &Record, unsigned &Idx); + + /// \brief Read a template argument. + TemplateArgument ReadTemplateArgument(const RecordData &Record,unsigned &Idx); + + /// \brief Read a template parameter list. + TemplateParameterList *ReadTemplateParameterList(const RecordData &Record, + unsigned &Idx); + + /// \brief Read a template argument array. + void + ReadTemplateArgumentList(llvm::SmallVector<TemplateArgument, 8> &TemplArgs, + const RecordData &Record, unsigned &Idx); + + /// \brief Read a UnresolvedSet structure. + void ReadUnresolvedSet(UnresolvedSetImpl &Set, + const RecordData &Record, unsigned &Idx); + + /// \brief Read a C++ base specifier. + CXXBaseSpecifier ReadCXXBaseSpecifier(const RecordData &Record,unsigned &Idx); + /// \brief Read a source location. SourceLocation ReadSourceLocation(const RecordData &Record, unsigned& Idx) { return SourceLocation::getFromRawEncoding(Record[Idx++]); @@ -729,20 +786,25 @@ public: /// \brief Reads attributes from the current stream position. Attr *ReadAttributes(); - /// \brief ReadDeclExpr - Reads an expression from the current decl cursor. - Expr *ReadDeclExpr(); - - /// \brief ReadTypeExpr - Reads an expression from the current type cursor. - Expr *ReadTypeExpr(); + /// \brief Reads a statement. + Stmt *ReadStmt(); - /// \brief Reads a statement from the specified cursor. - Stmt *ReadStmt(llvm::BitstreamCursor &Cursor); + /// \brief Reads an expression. + Expr *ReadExpr(); - /// \brief Read a statement from the current DeclCursor. - Stmt *ReadDeclStmt() { - return ReadStmt(DeclsCursor); + /// \brief Reads a sub-statement operand during statement reading. + Stmt *ReadSubStmt() { + assert(ReadingKind == Read_Stmt && + "Should be called only during statement reading!"); + // Subexpressions are stored from last to first, so the next Stmt we need + // is at the back of the stack. + assert(!StmtStack.empty() && "Read too many sub statements!"); + return StmtStack.pop_back_val(); } + /// \brief Reads a sub-expression operand during statement reading. + Expr *ReadSubExpr(); + /// \brief Reads the macro record located at the given offset. void ReadMacroRecord(uint64_t Offset); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 85f53b9..860ef56 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/TemplateBase.h" #include "clang/Frontend/PCHBitCodes.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" @@ -38,6 +39,7 @@ class CXXBaseOrMemberInitializer; class LabelStmt; class MacroDefinition; class MemorizeStatCalls; +class PCHReader; class Preprocessor; class Sema; class SourceManager; @@ -188,7 +190,11 @@ private: /// \brief Statements that we've encountered while serializing a /// declaration or type. - llvm::SmallVector<Stmt *, 8> StmtsToEmit; + llvm::SmallVector<Stmt *, 16> StmtsToEmit; + + /// \brief Statements collection to use for PCHWriter::AddStmt(). + /// It will point to StmtsToEmit unless it is overriden. + llvm::SmallVector<Stmt *, 16> *CollectedStmts; /// \brief Mapping from SwitchCase statements to IDs. std::map<SwitchCase *, unsigned> SwitchCaseIDs; @@ -210,10 +216,13 @@ private: /// file. unsigned NumVisibleDeclContexts; + /// \brief Write the given subexpression to the bitstream. + void WriteSubStmt(Stmt *S); + void WriteBlockInfoBlock(); - void WriteMetadata(ASTContext &Context, const char *isysroot); + void WriteMetadata(ASTContext &Context, const PCHReader *Chain, const char *isysroot); void WriteLanguageOptions(const LangOptions &LangOpts); - void WriteStatCache(MemorizeStatCalls &StatCalls, const char* isysroot); + void WriteStatCache(MemorizeStatCalls &StatCalls); void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP, const char* isysroot); @@ -229,6 +238,11 @@ private: unsigned ParmVarDeclAbbrev; void WriteDeclsBlockAbbrevs(); void WriteDecl(ASTContext &Context, Decl *D); + + void WritePCHCore(Sema &SemaRef, MemorizeStatCalls *StatCalls, + const char* isysroot); + void WritePCHChain(Sema &SemaRef, MemorizeStatCalls *StatCalls, + const PCHReader *Chain, const char* isysroot); public: /// \brief Create a new precompiled header writer that outputs to @@ -249,7 +263,7 @@ public: /// \param PPRec Record of the preprocessing actions that occurred while /// preprocessing this file, e.g., macro instantiations void WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls, - const char* isysroot); + const PCHReader *Chain, const char* isysroot); /// \brief Emit a source location. void AddSourceLocation(SourceLocation Loc, RecordData &Record); @@ -299,6 +313,11 @@ public: /// \brief Emits a reference to a declarator info. void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record); + /// \brief Emits a template argument location info. + void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, + const TemplateArgumentLocInfo &Arg, + RecordData &Record); + /// \brief Emits a template argument location. void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, RecordData &Record); @@ -315,6 +334,26 @@ public: /// \brief Emit a nested name specifier. void AddNestedNameSpecifier(NestedNameSpecifier *NNS, RecordData &Record); + + /// \brief Emit a template name. + void AddTemplateName(TemplateName Name, RecordData &Record); + + /// \brief Emit a template argument. + void AddTemplateArgument(const TemplateArgument &Arg, RecordData &Record); + + /// \brief Emit a template parameter list. + void AddTemplateParameterList(const TemplateParameterList *TemplateParams, + RecordData &Record); + + /// \brief Emit a template argument list. + void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs, + RecordData &Record); + + /// \brief Emit a UnresolvedSet structure. + void AddUnresolvedSet(const UnresolvedSetImpl &Set, RecordData &Record); + + /// brief Emit a C++ base specifier. + void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base, RecordData &Record); /// \brief Add a string to the given record. void AddString(const std::string &Str, RecordData &Record); @@ -335,10 +374,9 @@ public: /// type or declaration has been written, call FlushStmts() to write /// the corresponding statements just after the type or /// declaration. - void AddStmt(Stmt *S) { StmtsToEmit.push_back(S); } - - /// \brief Write the given subexpression to the bitstream. - void WriteSubStmt(Stmt *S); + void AddStmt(Stmt *S) { + CollectedStmts->push_back(S); + } /// \brief Flush all of the statements and expressions that have /// been added to the queue via AddStmt(). diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index ec4392f..f530294 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -18,14 +18,9 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" -namespace llvm { - class raw_ostream; -} - namespace clang { class DiagnosticOptions; class LangOptions; -class SourceManager; class TextDiagnosticPrinter : public DiagnosticClient { llvm::raw_ostream &OS; @@ -60,14 +55,14 @@ public: void PrintIncludeStack(SourceLocation Loc, const SourceManager &SM); - void HighlightRange(const SourceRange &R, + void HighlightRange(const CharSourceRange &R, const SourceManager &SrcMgr, unsigned LineNo, FileID FID, std::string &CaretLine, const std::string &SourceLine); void EmitCaretDiagnostic(SourceLocation Loc, - SourceRange *Ranges, unsigned NumRanges, + CharSourceRange *Ranges, unsigned NumRanges, const SourceManager &SM, const FixItHint *Hints, unsigned NumHints, diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def index 069d718..e8cb4a6 100644 --- a/include/clang/Frontend/TypeXML.def +++ b/include/clang/Frontend/TypeXML.def @@ -253,6 +253,11 @@ 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 diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index c1d4831..f37cc01 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -65,12 +65,6 @@ void ProcessWarningOptions(Diagnostic &Diags, const DiagnosticOptions &Opts); void DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream* OS, const PreprocessorOutputOptions &Opts); -/// RewriteMacrosInInput - Implement -rewrite-macros mode. -void RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream* OS); - -/// RewriteMacrosInInput - A simple test for the TokenRewriter class. -void DoRewriteTest(Preprocessor &PP, llvm::raw_ostream* OS); - /// CreatePrintParserActionsAction - Return the actions implementation that /// implements the -parse-print-callbacks option. MinimalAction *CreatePrintParserActionsAction(Preprocessor &PP, diff --git a/include/clang/Index/CallGraph.h b/include/clang/Index/CallGraph.h index 5edfe6f..336bf47 100644 --- a/include/clang/Index/CallGraph.h +++ b/include/clang/Index/CallGraph.h @@ -54,7 +54,7 @@ public: class CallGraph { /// Program manages all Entities. - idx::Program Prog; + idx::Program &Prog; typedef std::map<idx::Entity, CallGraphNode *> FunctionMapTy; @@ -71,7 +71,7 @@ class CallGraph { CallGraphNode *ExternalCallingNode; public: - CallGraph(); + CallGraph(idx::Program &P); ~CallGraph(); typedef FunctionMapTy::iterator iterator; diff --git a/include/clang/Index/Entity.h b/include/clang/Index/Entity.h index c2aab62..9863963 100644 --- a/include/clang/Index/Entity.h +++ b/include/clang/Index/Entity.h @@ -17,6 +17,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" #include <string> namespace clang { @@ -71,6 +72,9 @@ public: /// \returns invalid Entity if an Entity cannot refer to this Decl. static Entity get(Decl *D, Program &Prog); + /// \brief Get an Entity associated with a name in the global namespace. + static Entity get(llvm::StringRef Name, Program &Prog); + /// \brief true if the Entity is not visible outside the trasnlation unit. bool isInternalToTU() const { assert(isValid() && "This Entity is not valid!"); diff --git a/include/clang/Index/Indexer.h b/include/clang/Index/Indexer.h index 361e729..96c585d 100644 --- a/include/clang/Index/Indexer.h +++ b/include/clang/Index/Indexer.h @@ -23,6 +23,7 @@ namespace clang { class ASTContext; + class FunctionDecl; namespace idx { class Program; @@ -35,6 +36,7 @@ public: typedef llvm::DenseMap<ASTContext *, TranslationUnit *> CtxTUMapTy; typedef std::map<Entity, TUSetTy> MapTy; typedef std::map<GlobalSelector, TUSetTy> SelMapTy; + typedef std::map<Entity, std::pair<FunctionDecl*,TranslationUnit*> > DefMapTy; explicit Indexer(Program &prog) : Prog(prog) { } @@ -49,10 +51,15 @@ public: virtual void GetTranslationUnitsFor(GlobalSelector Sel, TranslationUnitHandler &Handler); + std::pair<FunctionDecl*, TranslationUnit*> getDefinitionFor(Entity Ent); + private: Program &Prog; MapTy Map; + // Map a function Entity to the its definition. + DefMapTy DefMap; + CtxTUMapTy CtxTUMap; SelMapTy SelMap; }; diff --git a/include/clang/Index/TranslationUnit.h b/include/clang/Index/TranslationUnit.h index bf9e78f..b86ba3e 100644 --- a/include/clang/Index/TranslationUnit.h +++ b/include/clang/Index/TranslationUnit.h @@ -16,6 +16,7 @@ namespace clang { class ASTContext; + class Preprocessor; namespace idx { class DeclReferenceMap; @@ -26,6 +27,7 @@ class TranslationUnit { public: virtual ~TranslationUnit(); virtual ASTContext &getASTContext() = 0; + virtual Preprocessor &getPreprocessor() = 0; virtual DeclReferenceMap &getDeclReferenceMap() = 0; virtual SelectorMap &getSelectorMap() = 0; }; diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index d74124e..99fe29b 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -16,6 +16,7 @@ #include "clang/Lex/DirectoryLookup.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/StringRef.h" #include <string> namespace clang { @@ -70,6 +71,12 @@ public: const std::string &Str) { } + /// PragmaMessage - This callback is invoked when a #pragma message directive + /// is read. + /// + virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) { + } + /// MacroExpands - This is called by /// Preprocessor::HandleMacroExpandedIdentifier when a macro invocation is /// found. @@ -127,6 +134,11 @@ public: Second->PragmaComment(Loc, Kind, Str); } + virtual void PragmaMessage(SourceLocation Loc, llvm::StringRef Str) { + First->PragmaMessage(Loc, Str); + Second->PragmaMessage(Loc, Str); + } + virtual void MacroExpands(const Token &Id, const MacroInfo* MI) { First->MacroExpands(Id, MI); Second->MacroExpands(Id, MI); diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index ef367fe..c68555b 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -14,6 +14,8 @@ #ifndef LLVM_CLANG_PRAGMA_H #define LLVM_CLANG_PRAGMA_H +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include <cassert> #include <vector> @@ -33,12 +35,13 @@ namespace clang { /// we treat "#pragma STDC" and "#pragma GCC" as namespaces that contain other /// pragmas. class PragmaHandler { - const IdentifierInfo *Name; + std::string Name; public: - PragmaHandler(const IdentifierInfo *name) : Name(name) {} + explicit PragmaHandler(llvm::StringRef name) : Name(name) {} + PragmaHandler() {} virtual ~PragmaHandler(); - const IdentifierInfo *getName() const { return Name; } + llvm::StringRef getName() const { return Name; } virtual void HandlePragma(Preprocessor &PP, Token &FirstToken) = 0; /// getIfNamespace - If this is a namespace, return it. This is equivalent to @@ -46,30 +49,38 @@ public: virtual PragmaNamespace *getIfNamespace() { return 0; } }; +/// EmptyPragmaHandler - A pragma handler which takes no action, which can be +/// used to ignore particular pragmas. +class EmptyPragmaHandler : public PragmaHandler { +public: + EmptyPragmaHandler(); + + virtual void HandlePragma(Preprocessor &PP, Token &FirstToken); +}; + /// PragmaNamespace - This PragmaHandler subdivides the namespace of pragmas, /// allowing hierarchical pragmas to be defined. Common examples of namespaces /// are "#pragma GCC", "#pragma STDC", and "#pragma omp", but any namespaces may /// be (potentially recursively) defined. class PragmaNamespace : public PragmaHandler { - /// Handlers - This is the list of handlers in this namespace. + /// Handlers - This is a map of the handlers in this namespace with their name + /// as key. /// - std::vector<PragmaHandler*> Handlers; + llvm::StringMap<PragmaHandler*> Handlers; public: - PragmaNamespace(const IdentifierInfo *Name) : PragmaHandler(Name) {} + explicit PragmaNamespace(llvm::StringRef Name) : PragmaHandler(Name) {} virtual ~PragmaNamespace(); /// FindHandler - Check to see if there is already a handler for the - /// specified name. If not, return the handler for the null identifier if it + /// specified name. If not, return the handler for the null name if it /// exists, otherwise return null. If IgnoreNull is true (the default) then /// the null handler isn't returned on failure to match. - PragmaHandler *FindHandler(const IdentifierInfo *Name, + PragmaHandler *FindHandler(llvm::StringRef Name, bool IgnoreNull = true) const; /// AddPragma - Add a pragma to this namespace. /// - void AddPragma(PragmaHandler *Handler) { - Handlers.push_back(Handler); - } + void AddPragma(PragmaHandler *Handler); /// RemovePragmaHandler - Remove the given handler from the /// namespace. diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index f01b3af..1ee4bb6 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -340,13 +340,19 @@ public: /// AddPragmaHandler - Add the specified pragma handler to the preprocessor. /// If 'Namespace' is non-null, then it is a token required to exist on the /// pragma line before the pragma string starts, e.g. "STDC" or "GCC". - void AddPragmaHandler(const char *Namespace, PragmaHandler *Handler); + void AddPragmaHandler(llvm::StringRef Namespace, PragmaHandler *Handler); + void AddPragmaHandler(PragmaHandler *Handler) { + AddPragmaHandler(llvm::StringRef(), Handler); + } /// RemovePragmaHandler - Remove the specific pragma handler from /// the preprocessor. If \arg Namespace is non-null, then it should /// be the namespace that \arg Handler was added to. It is an error /// to remove a handler that has not been registered. - void RemovePragmaHandler(const char *Namespace, PragmaHandler *Handler); + void RemovePragmaHandler(llvm::StringRef Namespace, PragmaHandler *Handler); + void RemovePragmaHandler(PragmaHandler *Handler) { + RemovePragmaHandler(llvm::StringRef(), Handler); + } /// \brief Add the specified comment handler to the preprocessor. void AddCommentHandler(CommentHandler *Handler); @@ -871,7 +877,11 @@ private: //===--------------------------------------------------------------------===// // Caching stuff. void CachingLex(Token &Result); - bool InCachingLexMode() const { return CurPPLexer == 0 && CurTokenLexer == 0;} + bool InCachingLexMode() const { + // If the Lexer pointers are 0 and IncludeMacroStack is empty, it means + // that we are past EOF, not that we are in CachingLex mode. + return CurPPLexer == 0 && CurTokenLexer == 0 && !IncludeMacroStack.empty(); + } void EnterCachingLexMode(); void ExitCachingLexMode() { if (InCachingLexMode()) @@ -918,6 +928,7 @@ public: void HandlePragmaSystemHeader(Token &SysHeaderTok); void HandlePragmaDependency(Token &DependencyTok); void HandlePragmaComment(Token &CommentTok); + void HandlePragmaMessage(Token &MessageTok); // Return true and store the first token only if any CommentHandler // has inserted some tokens and getCommentRetentionState() is false. bool HandleComment(Token &Token, SourceRange Comment); diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index b5dde9a..bd9b468 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -148,6 +148,7 @@ public: Kind = tok::unknown; Flags = 0; PtrData = 0; + UintData = 0; Loc = SourceLocation(); } @@ -169,7 +170,7 @@ public: } void setLiteralData(const char *Ptr) { assert(isLiteral() && "Cannot set literal data of non-literal"); - PtrData = (void*)Ptr; + PtrData = const_cast<char*>(Ptr); } void *getAnnotationValue() const { @@ -254,4 +255,9 @@ struct PPConditionalInfo { } // end namespace clang +namespace llvm { + template <> + struct isPodLike<clang::Token> { static const bool value = true; }; +} // end namespace llvm + #endif diff --git a/include/clang/Makefile b/include/clang/Makefile index 6abe375..e366e4e 100644 --- a/include/clang/Makefile +++ b/include/clang/Makefile @@ -1,7 +1,7 @@ -LEVEL = ../../../.. +CLANG_LEVEL := ../.. DIRS := AST Basic Driver -include $(LEVEL)/Makefile.common +include $(CLANG_LEVEL)/Makefile install-local:: $(Echo) Installing Clang include files diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index e21da81..9cb47aa 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -64,7 +64,21 @@ namespace clang { /// parse to complete accurately. The MinimalAction class does this /// bare-minimum of tracking to implement this functionality. class Action : public ActionBase { + /// \brief The parser's current scope. + /// + /// The parser maintains this state here so that is accessible to \c Action + /// subclasses via \c getCurScope(). + Scope *CurScope; + +protected: + friend class Parser; + + /// \brief Retrieve the parser's current scope. + Scope *getCurScope() const { return CurScope; } + public: + Action() : CurScope(0) { } + /// Out-of-line virtual destructor to provide home for this class. virtual ~Action(); @@ -1637,16 +1651,39 @@ public: return move(SubExpr); } - /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the - /// new was qualified (::new). In a full new like - /// @code new (p1, p2) type(c1, c2) @endcode - /// the p1 and p2 expressions will be in PlacementArgs and the c1 and c2 - /// expressions in ConstructorArgs. The type is passed as a declarator. + /// \brief Parsed a C++ 'new' expression. + /// + /// \param StartLoc The start of the new expression, which is either the + /// "new" keyword or the "::" preceding it, depending on \p UseGlobal. + /// + /// \param UseGlobal True if the "new" was qualified with "::". + /// + /// \param PlacementLParen The location of the opening parenthesis ('(') for + /// the placement arguments, if any. + /// + /// \param PlacementArgs The placement arguments, if any. + /// + /// \param PlacementRParen The location of the closing parenthesis (')') for + /// the placement arguments, if any. + /// + /// \param TypeIdParens If the type was expressed as a type-id in parentheses, + /// the source range covering the parenthesized type-id. + /// + /// \param D The parsed declarator, which may include an array size (for + /// array new) as the first declarator. + /// + /// \param ConstructorLParen The location of the opening parenthesis ('(') for + /// the constructor arguments, if any. + /// + /// \param ConstructorArgs The constructor arguments, if any. + /// + /// \param ConstructorRParen The location of the closing parenthesis (')') for + /// the constructor arguments, if any. virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, SourceLocation PlacementLParen, MultiExprArg PlacementArgs, SourceLocation PlacementRParen, - bool ParenTypeId, Declarator &D, + SourceRange TypeIdParens, Declarator &D, SourceLocation ConstructorLParen, MultiExprArg ConstructorArgs, SourceLocation ConstructorRParen) { @@ -1769,6 +1806,15 @@ public: unsigned NumBases) { } + /// ActOnAccessSpecifier - This is invoked when an access specifier + /// (and the colon following it) is found during the parsing of a + /// C++ class member declarator. + virtual DeclPtrTy ActOnAccessSpecifier(AccessSpecifier AS, + SourceLocation ASLoc, + SourceLocation ColonLoc) { + return DeclPtrTy(); + } + /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member /// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth' /// specifies the bitfield width if there is one and 'Init' specifies the @@ -1824,46 +1870,87 @@ public: //===---------------------------C++ Templates----------------------------===// - /// ActOnTypeParameter - Called when a C++ template type parameter - /// (e.g., "typename T") has been parsed. Typename specifies whether - /// the keyword "typename" was used to declare the type parameter - /// (otherwise, "class" was used), ellipsis specifies whether this is a - /// C++0x parameter pack, EllipsisLoc specifies the start of the ellipsis, - /// and KeyLoc is the location of the "class" or "typename" keyword. - // ParamName is the name of the parameter (NULL indicates an unnamed template - // parameter) and ParamNameLoc is the location of the parameter name (if any) - /// If the type parameter has a default argument, it will be added - /// later via ActOnTypeParameterDefault. Depth and Position provide - /// the number of enclosing templates (see - /// ActOnTemplateParameterList) and the number of previous - /// parameters within this template parameter list. + /// \brief Called when a C++ template type parameter(e.g., "typename T") has + /// been parsed. + /// + /// Given + /// + /// \code + /// template<typename T, typename U = T> struct pair; + /// \endcode + /// + /// this callback will be invoked twice: once for the type parameter \c T + /// with \p Depth=0 and \p Position=0, and once for the type parameter \c U + /// with \p Depth=0 and \p Position=1. + /// + /// \param Typename Specifies whether the keyword "typename" was used to + /// declare the type parameter (otherwise, "class" was used). + /// + /// \param Ellipsis Specifies whether this is a C++0x parameter pack. + /// + /// \param EllipsisLoc Specifies the start of the ellipsis. + /// + /// \param KeyLoc The location of the "class" or "typename" keyword. + /// + /// \param ParamName The name of the parameter, where NULL indicates an + /// unnamed template parameter. + /// + /// \param ParamNameLoc The location of the parameter name (if any). + /// + /// \param Depth The depth of this template parameter, e.g., the number of + /// template parameter lists that occurred outside the template parameter + /// list in which this template type parameter occurs. + /// + /// \param Position The zero-based position of this template parameter within + /// its template parameter list, which is also the number of template + /// parameters that precede this parameter in the template parameter list. + /// + /// \param EqualLoc The location of the '=' sign for the default template + /// argument, if any. + /// + /// \param DefaultArg The default argument, if provided. virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, bool Ellipsis, SourceLocation EllipsisLoc, SourceLocation KeyLoc, IdentifierInfo *ParamName, SourceLocation ParamNameLoc, - unsigned Depth, unsigned Position) { + unsigned Depth, unsigned Position, + SourceLocation EqualLoc, + TypeTy *DefaultArg) { return DeclPtrTy(); } - /// ActOnTypeParameterDefault - Adds a default argument (the type - /// Default) to the given template type parameter (TypeParam). - virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam, - SourceLocation EqualLoc, - SourceLocation DefaultLoc, - TypeTy *Default) { - } - - /// ActOnNonTypeTemplateParameter - Called when a C++ non-type - /// template parameter (e.g., "int Size" in "template<int Size> - /// class Array") has been parsed. S is the current scope and D is - /// the parsed declarator. Depth and Position provide the number of - /// enclosing templates (see - /// ActOnTemplateParameterList) and the number of previous - /// parameters within this template parameter list. + /// \brief Called when a C++ non-type template parameter has been parsed. + /// + /// Given + /// + /// \code + /// template<int Size> class Array; + /// \endcode + /// + /// This callback will be invoked for the 'Size' non-type template parameter. + /// + /// \param S The current scope. + /// + /// \param D The parsed declarator. + /// + /// \param Depth The depth of this template parameter, e.g., the number of + /// template parameter lists that occurred outside the template parameter + /// list in which this template type parameter occurs. + /// + /// \param Position The zero-based position of this template parameter within + /// its template parameter list, which is also the number of template + /// parameters that precede this parameter in the template parameter list. + /// + /// \param EqualLoc The location of the '=' sign for the default template + /// argument, if any. + /// + /// \param DefaultArg The default argument, if provided. virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, unsigned Depth, - unsigned Position) { + unsigned Position, + SourceLocation EqualLoc, + ExprArg DefaultArg) { return DeclPtrTy(); } @@ -1874,29 +1961,50 @@ public: ExprArg Default) { } - /// ActOnTemplateTemplateParameter - Called when a C++ template template - /// parameter (e.g., "int T" in "template<template <typename> class T> class - /// Array") has been parsed. TmpLoc is the location of the "template" keyword, - /// TemplateParams is the sequence of parameters required by the template, - /// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc - /// is the source location of the identifier (if given). + /// \brief Called when a C++ template template parameter has been parsed. + /// + /// Given + /// + /// \code + /// template<template <typename> class T> class X; + /// \endcode + /// + /// this callback will be invoked for the template template parameter \c T. + /// + /// \param S The scope in which this template template parameter occurs. + /// + /// \param TmpLoc The location of the "template" keyword. + /// + /// \param TemplateParams The template parameters required by the template. + /// + /// \param ParamName The name of the parameter, or NULL if unnamed. + /// + /// \param ParamNameLoc The source location of the parameter name (if given). + /// + /// \param Depth The depth of this template parameter, e.g., the number of + /// template parameter lists that occurred outside the template parameter + /// list in which this template parameter occurs. + /// + /// \param Position The zero-based position of this template parameter within + /// its template parameter list, which is also the number of template + /// parameters that precede this parameter in the template parameter list. + /// + /// \param EqualLoc The location of the '=' sign for the default template + /// argument, if any. + /// + /// \param DefaultArg The default argument, if provided. virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S, SourceLocation TmpLoc, TemplateParamsTy *Params, IdentifierInfo *ParamName, SourceLocation ParamNameLoc, unsigned Depth, - unsigned Position) { + unsigned Position, + SourceLocation EqualLoc, + const ParsedTemplateArgument &DefaultArg) { return DeclPtrTy(); } - /// \brief Adds a default argument to the given template template - /// parameter. - virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, - SourceLocation EqualLoc, - const ParsedTemplateArgument &Default) { - } - /// ActOnTemplateParameterList - Called when a complete template /// parameter list has been parsed, e.g., /// @@ -1980,6 +2088,8 @@ public: /// SS will be "MetaFun::", \p TemplateKWLoc contains the location /// of the "template" keyword, and "apply" is the \p Name. /// + /// \param S The scope in which the dependent template name was parsed. + /// /// \param TemplateKWLoc the location of the "template" keyword (if any). /// /// \param SS the nested-name-specifier that precedes the "template" keyword @@ -1995,12 +2105,21 @@ public: /// /// \param EnteringContext whether we are entering the context of this /// template. - virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, + /// + /// \param Template Will be set to the dependent template name, on success. + /// + /// \returns The kind of template name that was produced. Generally, this will + /// be \c TNK_Dependent_template_name. However, if the nested-name-specifier + /// is not dependent, or refers to the current instantiation, then we may + /// be able to resolve the template kind more specifically. + virtual TemplateNameKind ActOnDependentTemplateName(Scope *S, + SourceLocation TemplateKWLoc, CXXScopeSpec &SS, UnqualifiedId &Name, TypeTy *ObjectType, - bool EnteringContext) { - return TemplateTy(); + bool EnteringContext, + TemplateTy &Template) { + return TNK_Non_template; } /// \brief Process the declaration or definition of an explicit @@ -2237,8 +2356,9 @@ public: /// \param II the identifier we're retrieving (e.g., 'type' in the example). /// \param IdLoc the location of the identifier. virtual TypeResult - ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, - const IdentifierInfo &II, SourceLocation IdLoc) { + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, const IdentifierInfo &II, + SourceLocation IdLoc) { return TypeResult(); } @@ -2251,11 +2371,22 @@ public: /// \param TemplateLoc the location of the 'template' keyword, if any. /// \param Ty the type that the typename specifier refers to. virtual TypeResult - ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, - SourceLocation TemplateLoc, TypeTy *Ty) { + ActOnTypenameType(Scope *S, SourceLocation TypenameLoc, + const CXXScopeSpec &SS, SourceLocation TemplateLoc, + TypeTy *Ty) { return TypeResult(); } + /// \brief Called when the parser begins parsing a construct which should not + /// have access control applied to it. + virtual void ActOnStartSuppressingAccessChecks() { + } + + /// \brief Called when the parser finishes parsing a construct which should + /// not have access control applied to it. + virtual void ActOnStopSuppressingAccessChecks() { + } + //===----------------------- Obj-C Declarations -------------------------===// // ActOnStartClassInterface - this action is called immediately after parsing @@ -2565,7 +2696,9 @@ public: //===---------------------------- Pragmas -------------------------------===// enum PragmaOptionsAlignKind { + POAK_Native, // #pragma options align=native POAK_Natural, // #pragma options align=natural + POAK_Packed, // #pragma options align=packed POAK_Power, // #pragma options align=power POAK_Mac68k, // #pragma options align=mac68k POAK_Reset // #pragma options align=reset @@ -2727,7 +2860,27 @@ public: /// \param NumArgs the number of arguments in \p Args. virtual void CodeCompleteCall(Scope *S, ExprTy *Fn, ExprTy **Args, unsigned NumArgs) { } - + + /// \brief Code completion for the initializer of a variable declaration. + /// + /// \param S The scope in which the initializer occurs. + /// + /// \param D The declaration being initialized. + virtual void CodeCompleteInitializer(Scope *S, DeclPtrTy D) { } + + /// \brief Code completion after the "return" keyword within a function. + /// + /// \param S The scope in which the return statement occurs. + virtual void CodeCompleteReturn(Scope *S) { } + + /// \brief Code completion for the right-hand side of an assignment or + /// compound assignment operator. + /// + /// \param S The scope in which the assignment occurs. + /// + /// \param LHS The left-hand side of the assignment expression. + virtual void CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) { } + /// \brief Code completion for a C++ nested-name-specifier that precedes a /// qualified-id of some form. /// @@ -2851,6 +3004,14 @@ public: unsigned NumMethods) { } + /// \brief Code completion for the receiver in an Objective-C message send. + /// + /// This code completion action is invoked when we see a '[' that indicates + /// the start of an Objective-C message send. + /// + /// \param S The scope in which the Objective-C message send occurs. + virtual void CodeCompleteObjCMessageReceiver(Scope *S) { } + /// \brief Code completion for an ObjC message expression that sends /// a message to the superclass. /// @@ -2905,7 +3066,7 @@ public: /// parsed. virtual void CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols, unsigned NumProtocols) { } - + /// \brief Code completion for a protocol declaration or definition, after /// the @protocol but before any identifier. /// @@ -2995,6 +3156,32 @@ public: TypeTy *ReturnType, DeclPtrTy IDecl) { } + + /// \brief Code completion for a selector identifier or argument name within + /// an Objective-C method declaration. + /// + /// \param S The scope in which this code completion occurs. + /// + /// \param IsInstanceMethod Whether we are parsing an instance method (or, + /// if false, a class method). + /// + /// \param AtParameterName Whether the actual code completion point is at the + /// argument name. + /// + /// \param ReturnType If non-NULL, the specified return type of the method + /// being declared or defined. + /// + /// \param SelIdents The identifiers that occurred in the selector for the + /// method declaration prior to the code completion point. + /// + /// \param NumSelIdents The number of identifiers provided by SelIdents. + virtual void CodeCompleteObjCMethodDeclSelector(Scope *S, + bool IsInstanceMethod, + bool AtParameterName, + TypeTy *ReturnType, + IdentifierInfo **SelIdents, + unsigned NumSelIdents) { } + //@} }; diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 1e6d3ab..b60a940 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -115,6 +115,7 @@ public: AT_weakref, AT_weak_import, AT_reqd_wg_size, + AT_init_priority, IgnoredAttribute, UnknownAttribute }; diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index 9c19a67..0e6dbec 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -170,6 +170,7 @@ private: /*TST*/unsigned TypeSpecType : 5; bool TypeAltiVecVector : 1; bool TypeAltiVecPixel : 1; + bool TypeAltiVecBool : 1; bool TypeSpecOwned : 1; // type-qualifiers @@ -237,6 +238,7 @@ public: TypeSpecType(TST_unspecified), TypeAltiVecVector(false), TypeAltiVecPixel(false), + TypeAltiVecBool(false), TypeSpecOwned(false), TypeQualifiers(TSS_unspecified), FS_inline_specified(false), @@ -278,6 +280,7 @@ public: TST getTypeSpecType() const { return (TST)TypeSpecType; } bool isTypeAltiVecVector() const { return TypeAltiVecVector; } bool isTypeAltiVecPixel() const { return TypeAltiVecPixel; } + bool isTypeAltiVecBool() const { return TypeAltiVecBool; } bool isTypeSpecOwned() const { return TypeSpecOwned; } void *getTypeRep() const { return TypeRep; } CXXScopeSpec &getTypeSpecScope() { return TypeScope; } @@ -885,6 +888,13 @@ struct DeclaratorChunk { delete[] Exceptions; } + /// isKNRPrototype - Return true if this is a K&R style identifier list, + /// like "void foo(a,b,c)". In a function definition, this will be followed + /// by the argument type definitions. + bool isKNRPrototype() const { + return !hasPrototype && NumArgs != 0; + } + SourceLocation getEllipsisLoc() const { return SourceLocation::getFromRawEncoding(EllipsisLoc); } diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 8081c24..b8c294a 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -72,6 +72,7 @@ namespace prec { class Parser { friend class PragmaUnusedHandler; friend class ColonProtectionRAIIObject; + friend class ParenBraceBracketBalancer; PrettyStackTraceParserEntry CrashInfo; Preprocessor &PP; @@ -93,7 +94,6 @@ class Parser { /// and SemaActions for those uses that don't matter. Action &Actions; - Scope *CurScope; Diagnostic &Diags; /// ScopeCache - Cache scopes to reduce malloc traffic. @@ -140,7 +140,8 @@ public: Action &getActions() const { return Actions; } const Token &getCurToken() const { return Tok; } - + Scope *getCurScope() const { return Actions.getCurScope(); } + // Type forwarding. All of these are statically 'void*', but they may all be // different actual classes based on the actions in place. typedef Action::ExprTy ExprTy; @@ -832,8 +833,8 @@ private: //===--------------------------------------------------------------------===// // C99 6.9: External Definitions. DeclGroupPtrTy ParseExternalDeclaration(CXX0XAttributeList Attr); - bool isDeclarationAfterDeclarator(); - bool isStartOfFunctionDefinition(); + bool isDeclarationAfterDeclarator() const; + bool isStartOfFunctionDefinition(const ParsingDeclarator &Declarator); DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr, AccessSpecifier AS = AS_none); DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, @@ -1059,6 +1060,7 @@ private: OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); OwningExprResult ParseObjCSelectorExpression(SourceLocation AtLoc); OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc); + bool isSimpleObjCMessageExpression(); OwningExprResult ParseObjCMessageExpression(); OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc, SourceLocation SuperLoc, @@ -1345,14 +1347,14 @@ private: CreatedScope = true; P.EnterScope(0); // Not a decl scope. - if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS)) + if (!P.Actions.ActOnCXXEnterDeclaratorScope(P.getCurScope(), SS)) EnteredScope = true; } ~DeclaratorScopeObj() { if (EnteredScope) { assert(SS.isSet() && "C++ scope was cleared ?"); - P.Actions.ActOnCXXExitDeclaratorScope(P.CurScope, SS); + P.Actions.ActOnCXXExitDeclaratorScope(P.getCurScope(), SS); } if (CreatedScope) P.ExitScope(); diff --git a/include/clang/Parse/Template.h b/include/clang/Parse/Template.h index 1f8ccfb..84f4ed9 100644 --- a/include/clang/Parse/Template.h +++ b/include/clang/Parse/Template.h @@ -58,7 +58,7 @@ namespace clang { Loc(TemplateLoc), SS(SS) { } /// \brief Determine whether the given template argument is invalid. - bool isInvalid() { return Arg == 0; } + bool isInvalid() const { return Arg == 0; } /// \brief Determine what kind of template argument we have. KindType getKind() const { return Kind; } diff --git a/include/clang/Rewrite/ASTConsumers.h b/include/clang/Rewrite/ASTConsumers.h new file mode 100644 index 0000000..5fb107c --- /dev/null +++ b/include/clang/Rewrite/ASTConsumers.h @@ -0,0 +1,45 @@ +//===--- ASTConsumers.h - ASTConsumer implementations -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// AST Consumers. +// +//===----------------------------------------------------------------------===// + +#ifndef REWRITE_ASTCONSUMERS_H +#define REWRITE_ASTCONSUMERS_H + +#include <string> + +namespace llvm { + class raw_ostream; +} +namespace clang { + +class ASTConsumer; +class Diagnostic; +class LangOptions; +class Preprocessor; + +// ObjC rewriter: attempts tp rewrite ObjC constructs into pure C code. +// This is considered experimental, and only works with Apple's ObjC runtime. +ASTConsumer *CreateObjCRewriter(const std::string &InFile, + llvm::raw_ostream *OS, + Diagnostic &Diags, + const LangOptions &LOpts, + bool SilenceRewriteMacroWarning); + +/// CreateHTMLPrinter - Create an AST consumer which rewrites source code to +/// HTML with syntax highlighting suitable for viewing in a web-browser. +ASTConsumer *CreateHTMLPrinter(llvm::raw_ostream *OS, Preprocessor &PP, + bool SyntaxHighlight = true, + bool HighlightMacros = true); + +} // end clang namespace + +#endif diff --git a/include/clang/Frontend/FixItRewriter.h b/include/clang/Rewrite/FixItRewriter.h index b432d74..4ebcef0 100644 --- a/include/clang/Frontend/FixItRewriter.h +++ b/include/clang/Rewrite/FixItRewriter.h @@ -12,8 +12,8 @@ // then forwards any diagnostics to the adapted diagnostic client. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H -#define LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H +#ifndef LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H +#define LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" @@ -101,4 +101,4 @@ public: } -#endif // LLVM_CLANG_FRONTEND_FIX_IT_REWRITER_H +#endif // LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H diff --git a/include/clang/Rewrite/FrontendActions.h b/include/clang/Rewrite/FrontendActions.h new file mode 100644 index 0000000..2ff8d0a --- /dev/null +++ b/include/clang/Rewrite/FrontendActions.h @@ -0,0 +1,69 @@ +//===-- FrontendActions.h - Useful Frontend Actions -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REWRITE_FRONTENDACTIONS_H +#define LLVM_CLANG_REWRITE_FRONTENDACTIONS_H + +#include "clang/Frontend/FrontendAction.h" +#include <string> +#include <vector> + +namespace clang { +class FixItRewriter; +class FixItPathRewriter; + +//===----------------------------------------------------------------------===// +// AST Consumer Actions +//===----------------------------------------------------------------------===// + +class HTMLPrintAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class FixItAction : public ASTFrontendAction { +protected: + llvm::OwningPtr<FixItRewriter> Rewriter; + llvm::OwningPtr<FixItPathRewriter> PathRewriter; + + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); + + virtual bool BeginSourceFileAction(CompilerInstance &CI, + llvm::StringRef Filename); + + virtual void EndSourceFileAction(); + + virtual bool hasASTFileSupport() const { return false; } + +public: + FixItAction(); + ~FixItAction(); +}; + +class RewriteObjCAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + llvm::StringRef InFile); +}; + +class RewriteMacrosAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +class RewriteTestAction : public PreprocessorFrontendAction { +protected: + void ExecuteAction(); +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Rewrite/RewriteRope.h b/include/clang/Rewrite/RewriteRope.h index c0bd741..cb3f8a8 100644 --- a/include/clang/Rewrite/RewriteRope.h +++ b/include/clang/Rewrite/RewriteRope.h @@ -16,6 +16,7 @@ #include <cstring> #include <cassert> +#include <cstddef> #include <iterator> namespace clang { diff --git a/include/clang/Rewrite/Rewriter.h b/include/clang/Rewrite/Rewriter.h index adda866..0612a15 100644 --- a/include/clang/Rewrite/Rewriter.h +++ b/include/clang/Rewrite/Rewriter.h @@ -151,6 +151,7 @@ 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; /// 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 diff --git a/include/clang/Rewrite/Rewriters.h b/include/clang/Rewrite/Rewriters.h new file mode 100644 index 0000000..669cf8c --- /dev/null +++ b/include/clang/Rewrite/Rewriters.h @@ -0,0 +1,31 @@ +//===--- Rewriters.h - Rewriter implementations -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains miscellaneous utilities for various front-end actions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_REWRITE_REWRITERS_H +#define LLVM_CLANG_REWRITE_REWRITERS_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/raw_ostream.h" + +namespace clang { +class Preprocessor; + +/// RewriteMacrosInInput - Implement -rewrite-macros mode. +void RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream* OS); + +/// DoRewriteTest - A simple test for the TokenRewriter class. +void DoRewriteTest(Preprocessor &PP, llvm::raw_ostream* OS); + +} // end namespace clang + +#endif diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 1f1c0cc..1d9d250 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -59,6 +59,18 @@ enum { CCD_InBaseClass = 2 }; +/// \brief Priority value factors by which we will divide or multiply the +/// priority of a code-completion result. +enum { + /// \brief Divide by this factor when a code-completion result's type exactly + /// matches the type we expect. + CCF_ExactTypeMatch = 4, + /// \brief Divide by this factor when a code-completion result's type is + /// similar to the type we expect (e.g., both arithmetic types, both + /// Objective-C object pointer types). + CCF_SimilarTypeMatch = 2 +}; + class FunctionDecl; class FunctionType; class FunctionTemplateDecl; @@ -343,6 +355,10 @@ public: /// method, etc.) should be considered "informative". bool AllParametersAreInformative : 1; + /// \brief Whether we're completing a declaration of the given entity, + /// rather than a use of that entity. + bool DeclaringEntity : 1; + /// \brief If the result should have a nested-name-specifier, this is it. /// When \c QualifierIsInformative, the nested-name-specifier is /// informative rather than required. @@ -356,7 +372,7 @@ public: Priority(getPriorityFromDecl(Declaration)), StartParameter(0), Hidden(false), QualifierIsInformative(QualifierIsInformative), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - Qualifier(Qualifier) { + DeclaringEntity(false), Qualifier(Qualifier) { } /// \brief Build a result that refers to a keyword or symbol. @@ -364,21 +380,21 @@ public: : Kind(RK_Keyword), Keyword(Keyword), Priority(Priority), StartParameter(0), Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - Qualifier(0) { } + DeclaringEntity(false), Qualifier(0) { } /// \brief Build a result that refers to a macro. Result(IdentifierInfo *Macro, unsigned Priority = CCP_Macro) : Kind(RK_Macro), Macro(Macro), Priority(Priority), StartParameter(0), Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - Qualifier(0) { } + DeclaringEntity(false), Qualifier(0) { } /// \brief Build a result that refers to a pattern. Result(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern) : Kind(RK_Pattern), Pattern(Pattern), Priority(Priority), StartParameter(0), Hidden(false), QualifierIsInformative(0), StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - Qualifier(0) { } + DeclaringEntity(false), Qualifier(0) { } /// \brief Retrieve the declaration stored in this result. NamedDecl *getDeclaration() const { diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index d27e292..ad42a84 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -29,6 +29,8 @@ public: ExternalASTSource::SemaSource = true; } + ~ExternalSemaSource(); + /// \brief Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. |