diff options
Diffstat (limited to 'include/clang')
39 files changed, 1068 insertions, 617 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index aa01b7fdf06fa..041a0f33ad4d7 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -141,10 +141,19 @@ class ASTContext { /// this ASTContext object. LangOptions LangOpts; + /// \brief Whether we have already loaded comment source ranges from an + /// external source. + bool LoadedExternalComments; + /// MallocAlloc/BumpAlloc - The allocator objects used to create AST objects. bool FreeMemory; llvm::MallocAllocator MallocAlloc; llvm::BumpPtrAllocator BumpAlloc; + + /// \brief Mapping from declarations to their comments, once we have + /// already looked up the comment associated with a given declaration. + llvm::DenseMap<const Decl *, std::string> DeclComments; + public: TargetInfo &Target; IdentifierTable &Idents; @@ -154,6 +163,10 @@ public: llvm::OwningPtr<ExternalASTSource> ExternalSource; clang::PrintingPolicy PrintingPolicy; + /// \brief Source ranges for all of the comments in the source file, + /// sorted in order of appearance in the translation unit. + std::vector<SourceRange> Comments; + SourceManager& getSourceManager() { return SourceMgr; } const SourceManager& getSourceManager() const { return SourceMgr; } void *Allocate(unsigned Size, unsigned Align = 8) { @@ -178,7 +191,8 @@ public: TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } - + const char *getCommentForDecl(const Decl *D); + // Builtin Types. QualType VoidTy; QualType BoolTy; @@ -351,12 +365,6 @@ public: ObjCProtocolDecl **ProtocolList, unsigned NumProtocols); - /// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for a - /// given 'id' and conforming protocol list. - QualType getObjCQualifiedIdType(ObjCProtocolDecl **ProtocolList, - unsigned NumProtocols); - - /// getTypeOfType - GCC extension. QualType getTypeOfExprType(Expr *e); QualType getTypeOfType(QualType t); diff --git a/include/clang/AST/CFG.h b/include/clang/AST/CFG.h index 7a9ee01d4f62b..e60e58e1ac237 100644 --- a/include/clang/AST/CFG.h +++ b/include/clang/AST/CFG.h @@ -17,17 +17,20 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/raw_ostream.h" #include <list> #include <vector> #include <cassert> +namespace llvm { + class raw_ostream; +} namespace clang { class Stmt; class Expr; class CFG; class PrinterHelper; class BlockEdge; + class LangOptions; /// CFGBlock - Represents a single basic block in a source-level CFG. /// It consists of: @@ -181,9 +184,9 @@ public: unsigned getBlockID() const { return BlockID; } - void dump(const CFG* cfg) const; - void print(llvm::raw_ostream& OS, const CFG* cfg) const; - void printTerminator(llvm::raw_ostream& OS) const; + void dump(const CFG *cfg, const LangOptions &LO) const; + void print(llvm::raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const; + void printTerminator(llvm::raw_ostream &OS, const LangOptions &LO) const; }; @@ -283,9 +286,9 @@ public: // CFG Debugging: Pretty-Printing and Visualization. //===--------------------------------------------------------------------===// - void viewCFG() const; - void print(llvm::raw_ostream& OS) const; - void dump() const; + void viewCFG(const LangOptions &LO) const; + void print(llvm::raw_ostream& OS, const LangOptions &LO) const; + void dump(const LangOptions &LO) const; //===--------------------------------------------------------------------===// // Internal: constructors and data. diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 3de01f3baeb5d..69a52869d8188 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -26,13 +26,19 @@ class Stmt; class CompoundStmt; class StringLiteral; class TemplateArgumentList; +class FunctionTemplateSpecializationInfo; /// TranslationUnitDecl - The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { - TranslationUnitDecl() + ASTContext &Ctx; + + explicit TranslationUnitDecl(ASTContext &ctx) : Decl(TranslationUnit, 0, SourceLocation()), - DeclContext(TranslationUnit) {} + DeclContext(TranslationUnit), + Ctx(ctx) {} public: + ASTContext &getASTContext() const { return Ctx; } + static TranslationUnitDecl *Create(ASTContext &C); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; } @@ -621,15 +627,8 @@ public: enum StorageClass { None, Extern, Static, PrivateExtern }; -private: - /// \brief Provides information about a function template specialization, - /// which is a FunctionDecl that has been explicitly specialization or - /// instantiated from a function template. - struct TemplateSpecializationInfo { - FunctionTemplateDecl *Template; - const TemplateArgumentList *TemplateArguments; - }; +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 /// no formals. @@ -684,7 +683,8 @@ private: /// the template being specialized and the template arguments involved in /// that specialization. llvm::PointerUnion3<FunctionTemplateDecl*, FunctionDecl*, - TemplateSpecializationInfo*> TemplateOrSpecialization; + FunctionTemplateSpecializationInfo*> + TemplateOrSpecialization; protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -724,11 +724,11 @@ public: /// function. The variant that accepts a FunctionDecl pointer will /// set that function declaration to the actual declaration /// containing the body (if there is one). - Stmt *getBody(ASTContext &Context, const FunctionDecl *&Definition) const; + Stmt *getBody(const FunctionDecl *&Definition) const; - virtual Stmt *getBody(ASTContext &Context) const { + virtual Stmt *getBody() const { const FunctionDecl* Definition; - return getBody(Context, Definition); + return getBody(Definition); } /// \brief If the function has a body that is immediately available, @@ -809,9 +809,7 @@ public: return PreviousDeclaration; } - void setPreviousDeclaration(FunctionDecl * PrevDecl) { - PreviousDeclaration = PrevDecl; - } + void setPreviousDeclaration(FunctionDecl * PrevDecl); unsigned getBuiltinID(ASTContext &Context) const; @@ -940,27 +938,14 @@ public: /// /// If this function declaration is not a function template specialization, /// returns NULL. - FunctionTemplateDecl *getPrimaryTemplate() const { - if (TemplateSpecializationInfo *Info - = TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>()) { - return Info->Template; - } - return 0; - } + FunctionTemplateDecl *getPrimaryTemplate() const; /// \brief Retrieve the template arguments used to produce this function /// template specialization from the primary template. /// /// If this function declaration is not a function template specialization, /// returns NULL. - const TemplateArgumentList *getTemplateSpecializationArgs() const { - if (TemplateSpecializationInfo *Info - = TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>()) { - return Info->TemplateArguments; - } - return 0; - } - + const TemplateArgumentList *getTemplateSpecializationArgs() const; /// \brief Specify that this function declaration is actually a function /// template specialization. @@ -974,8 +959,17 @@ public: /// function template specialization from the template. void setFunctionTemplateSpecialization(ASTContext &Context, FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs); - + const TemplateArgumentList *TemplateArgs, + void *InsertPos); + + /// \brief Determine whether this is an explicit specialization of a + /// function template or a member function of a class template. + bool isExplicitSpecialization() const; + + /// \brief Note that this is an explicit specialization of a function template + /// or a member function of a class template. + void setExplicitSpecialization(bool ES); + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast; @@ -1268,12 +1262,12 @@ public: // enumeration. typedef specific_decl_iterator<EnumConstantDecl> enumerator_iterator; - enumerator_iterator enumerator_begin(ASTContext &Context) const { - return enumerator_iterator(this->decls_begin(Context)); + enumerator_iterator enumerator_begin() const { + return enumerator_iterator(this->decls_begin()); } - enumerator_iterator enumerator_end(ASTContext &Context) const { - return enumerator_iterator(this->decls_end(Context)); + enumerator_iterator enumerator_end() const { + return enumerator_iterator(this->decls_end()); } /// getIntegerType - Return the integer type this enum decl corresponds to. @@ -1376,17 +1370,17 @@ public: // data members, functions, constructors, destructors, etc. typedef specific_decl_iterator<FieldDecl> field_iterator; - field_iterator field_begin(ASTContext &Context) const { - return field_iterator(decls_begin(Context)); + field_iterator field_begin() const { + return field_iterator(decls_begin()); } - field_iterator field_end(ASTContext &Context) const { - return field_iterator(decls_end(Context)); + field_iterator field_end() const { + return field_iterator(decls_end()); } // field_empty - Whether there are any fields (non-static data // members) in this record. - bool field_empty(ASTContext &Context) const { - return field_begin(Context) == field_end(Context); + bool field_empty() const { + return field_begin() == field_end(); } /// completeDefinition - Notes that the definition of this type is @@ -1448,8 +1442,8 @@ public: bool IsVariadic() const { return isVariadic; } void setIsVariadic(bool value) { isVariadic = value; } - CompoundStmt *getBody() const { return (CompoundStmt*) Body; } - Stmt *getBody(ASTContext &C) const { return (Stmt*) Body; } + CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; } + Stmt *getBody() const { return (Stmt*) Body; } void setBody(CompoundStmt *B) { Body = (Stmt*) B; } // Iterator access to formal parameters. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index c959b05473fee..0bce2f84c7ba7 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -213,6 +213,13 @@ public: const DeclContext *getDeclContext() const { return const_cast<Decl*>(this)->getDeclContext(); } + + TranslationUnitDecl *getTranslationUnitDecl(); + const TranslationUnitDecl *getTranslationUnitDecl() const { + return const_cast<Decl*>(this)->getTranslationUnitDecl(); + } + + ASTContext &getASTContext() const; void setAccess(AccessSpecifier AS) { Access = AS; @@ -225,23 +232,23 @@ public: } bool hasAttrs() const { return HasAttrs; } - void addAttr(ASTContext &Context, Attr *attr); - const Attr *getAttrs(ASTContext &Context) const { + void addAttr(Attr *attr); + const Attr *getAttrs() const { if (!HasAttrs) return 0; // common case, no attributes. - return getAttrsImpl(Context); // Uncommon case, out of line hash lookup. + return getAttrsImpl(); // Uncommon case, out of line hash lookup. } - void swapAttrs(ASTContext &Context, Decl *D); - void invalidateAttrs(ASTContext &Context); + void swapAttrs(Decl *D); + void invalidateAttrs(); - template<typename T> const T *getAttr(ASTContext &Context) const { - for (const Attr *attr = getAttrs(Context); attr; attr = attr->getNext()) + template<typename T> const T *getAttr() const { + for (const Attr *attr = getAttrs(); attr; attr = attr->getNext()) if (const T *V = dyn_cast<T>(attr)) return V; return 0; } - template<typename T> bool hasAttr(ASTContext &Context) const { - return getAttr<T>(Context) != 0; + template<typename T> bool hasAttr() const { + return getAttr<T>() != 0; } /// setInvalidDecl - Indicates the Decl had a semantic error. This @@ -307,14 +314,14 @@ public: /// getBody - If this Decl represents a declaration for a body of code, /// such as a function or method definition, this method returns the /// top-level Stmt* of that body. Otherwise this method returns null. - virtual Stmt* getBody(ASTContext &Context) const { return 0; } + virtual Stmt* getBody() const { return 0; } /// getCompoundBody - Returns getBody(), dyn_casted to a CompoundStmt. - CompoundStmt* getCompoundBody(ASTContext &Context) const; + CompoundStmt* getCompoundBody() const; /// 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(ASTContext &Context) const; + SourceLocation getBodyRBrace() const; // global temp stats (until we have a per-module visitor) static void addDeclKind(Kind k); @@ -340,18 +347,16 @@ public: /// Destroy - Call destructors and release memory. virtual void Destroy(ASTContext& C); - void print(llvm::raw_ostream &Out, ASTContext &Context, + void print(llvm::raw_ostream &Out, unsigned Indentation = 0); + void print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); - void print(llvm::raw_ostream &Out, ASTContext &Context, - const PrintingPolicy &Policy, unsigned Indentation = 0); static void printGroup(Decl** Begin, unsigned NumDecls, - llvm::raw_ostream &Out, ASTContext &Context, - const PrintingPolicy &Policy, + llvm::raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation = 0); - void dump(ASTContext &Context); + void dump(); private: - const Attr *getAttrsImpl(ASTContext &Context) const; + const Attr *getAttrsImpl() const; }; @@ -454,7 +459,11 @@ public: const DeclContext *getLexicalParent() const { return const_cast<DeclContext*>(this)->getLexicalParent(); } - + + ASTContext &getParentASTContext() const { + return cast<Decl>(this)->getASTContext(); + } + bool isFunctionOrMethod() const { switch (DeclKind) { case Decl::Block: @@ -592,9 +601,9 @@ public: /// decls_begin/decls_end - Iterate over the declarations stored in /// this context. - decl_iterator decls_begin(ASTContext &Context) const; - decl_iterator decls_end(ASTContext &Context) const; - bool decls_empty(ASTContext &Context) const; + decl_iterator decls_begin() const; + decl_iterator decls_end() const; + bool decls_empty() const; /// specific_decl_iterator - Iterates over a subrange of /// declarations stored in a DeclContext, providing only those that @@ -750,7 +759,7 @@ public: /// /// If D is also a NamedDecl, it will be made visible within its /// semantic context via makeDeclVisibleInContext. - void addDecl(ASTContext &Context, Decl *D); + void addDecl(Decl *D); /// lookup_iterator - An iterator that provides access to the results /// of looking up a name within this context. @@ -769,8 +778,8 @@ public: /// the declarations with this name, with object, function, member, /// and enumerator names preceding any tag name. Note that this /// routine will not look into parent contexts. - lookup_result lookup(ASTContext &Context, DeclarationName Name); - lookup_const_result lookup(ASTContext &Context, DeclarationName Name) const; + lookup_result lookup(DeclarationName Name); + lookup_const_result lookup(DeclarationName Name) const; /// @brief Makes a declaration visible within this context. /// @@ -786,7 +795,7 @@ public: /// visible from this context, as determined by /// NamedDecl::declarationReplaces, the previous declaration will be /// replaced with D. - void makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D); + void makeDeclVisibleInContext(NamedDecl *D); /// udir_iterator - Iterates through the using-directives stored /// within this context. @@ -794,14 +803,14 @@ public: typedef std::pair<udir_iterator, udir_iterator> udir_iterator_range; - udir_iterator_range getUsingDirectives(ASTContext &Context) const; + udir_iterator_range getUsingDirectives() const; - udir_iterator using_directives_begin(ASTContext &Context) const { - return getUsingDirectives(Context).first; + udir_iterator using_directives_begin() const { + return getUsingDirectives().first; } - udir_iterator using_directives_end(ASTContext &Context) const { - return getUsingDirectives(Context).second; + udir_iterator using_directives_end() const { + return getUsingDirectives().second; } // Low-level accessors @@ -836,11 +845,11 @@ public: #include "clang/AST/DeclNodes.def" private: - void LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const; - void LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const; + void LoadLexicalDeclsFromExternalStorage() const; + void LoadVisibleDeclsFromExternalStorage() const; - void buildLookup(ASTContext &Context, DeclContext *DCtx); - void makeDeclVisibleInContextImpl(ASTContext &Context, NamedDecl *D); + void buildLookup(DeclContext *DCtx); + void makeDeclVisibleInContextImpl(NamedDecl *D); }; inline bool Decl::isTemplateParameter() const { diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index a2fe24e83105b..c523e96e03b06 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -32,6 +32,8 @@ class ClassTemplateSpecializationDecl; class AnyFunctionDecl { NamedDecl *Function; + AnyFunctionDecl(NamedDecl *ND) : Function(ND) { } + public: AnyFunctionDecl(FunctionDecl *FD) : Function(FD) { } AnyFunctionDecl(FunctionTemplateDecl *FTD); @@ -42,6 +44,10 @@ public: /// \brief Retrieve the underlying function or function template. NamedDecl *get() const { return Function; } + + static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) { + return AnyFunctionDecl(ND); + } }; } // end namespace clang @@ -57,6 +63,22 @@ namespace llvm { }; template<> struct simplify_type< ::clang::AnyFunctionDecl> : public simplify_type<const ::clang::AnyFunctionDecl> {}; + + // Provide PointerLikeTypeTraits for non-cvr pointers. + template<> + class PointerLikeTypeTraits< ::clang::AnyFunctionDecl> { + public: + static inline void *getAsVoidPointer(::clang::AnyFunctionDecl F) { + return F.get(); + } + static inline ::clang::AnyFunctionDecl getFromVoidPointer(void *P) { + return ::clang::AnyFunctionDecl::getFromNamedDecl( + static_cast< ::clang::NamedDecl*>(P)); + } + + enum { NumLowBitsAvailable = 2 }; + }; + } // end namespace llvm namespace clang { @@ -91,24 +113,10 @@ public: static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC, DeclarationName N); - /// addOverload - Add an overloaded function FD to this set of - /// overloaded functions. - void addOverload(FunctionDecl *FD) { - assert((FD->getDeclName() == getDeclName() || - isa<CXXConversionDecl>(FD) || isa<CXXConstructorDecl>(FD)) && - "Overloaded functions must have the same name"); - Functions.push_back(FD); - - // An overloaded function declaration always has the location of - // the most-recently-added function declaration. - if (FD->getLocation().isValid()) - this->setLocation(FD->getLocation()); - } + /// \brief Add a new overloaded function or function template to the set + /// of overloaded function templates. + void addOverload(AnyFunctionDecl F); - /// addOverload - Add an overloaded function template FTD to this set of - /// overloaded functions. - void addOverload(FunctionTemplateDecl *FTD); - function_iterator function_begin() { return Functions.begin(); } function_iterator function_end() { return Functions.end(); } function_const_iterator function_begin() const { return Functions.begin(); } @@ -289,8 +297,11 @@ public: CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); + virtual void Destroy(ASTContext& C); + /// setBases - Sets the base classes of this struct or class. - void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); + void setBases(ASTContext &C, + CXXBaseSpecifier const * const *Bases, unsigned NumBases); /// getNumBases - Retrieves the number of base classes of this /// class. @@ -580,15 +591,20 @@ class CXXBaseOrMemberInitializer { /// Args - The arguments used to initialize the base or member. Expr **Args; unsigned NumArgs; + + /// IdLoc - Location of the id in ctor-initializer list. + SourceLocation IdLoc; public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. explicit - CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs); + CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, + SourceLocation L); /// CXXBaseOrMemberInitializer - Creates a new member initializer. explicit - CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs); + CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, + SourceLocation L); /// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer. ~CXXBaseOrMemberInitializer(); @@ -601,6 +617,10 @@ public: /// arguments. typedef Expr * const * arg_const_iterator; + /// getBaseOrMember - get the generic 'member' representing either the field + /// or a base class. + void* getBaseOrMember() const { return reinterpret_cast<void*>(BaseOrMember); } + /// isBaseInitializer - Returns true when this initializer is /// initializing a base class. bool isBaseInitializer() const { return (BaseOrMember & 0x1) != 0; } @@ -641,6 +661,8 @@ public: return 0; } + SourceLocation getSourceLocation() const { return IdLoc; } + /// begin() - Retrieve an iterator to the first initializer argument. arg_iterator begin() { return Args; } /// begin() - Retrieve an iterator to the first initializer argument. @@ -677,16 +699,22 @@ class CXXConstructorDecl : public CXXMethodDecl { /// @c !Implicit && ImplicitlyDefined. bool ImplicitlyDefined : 1; - /// FIXME: Add support for base and member initializers. - + /// Support for base and member initializers. + /// BaseOrMemberInitializers - The arguments used to initialize the base + /// or member. + CXXBaseOrMemberInitializer **BaseOrMemberInitializers; + unsigned NumBaseOrMemberInitializers; + CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isExplicit, bool isInline, bool isImplicitlyDeclared) : CXXMethodDecl(CXXConstructor, RD, L, N, T, false, isInline), - Explicit(isExplicit), ImplicitlyDefined(false) { + Explicit(isExplicit), ImplicitlyDefined(false), + BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { setImplicit(isImplicitlyDeclared); } - + virtual void Destroy(ASTContext& C); + public: static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, @@ -702,7 +730,8 @@ public: /// already been defined. bool isImplicitlyDefined(ASTContext &C) const { assert(isThisDeclarationADefinition() && - "Can only get the implicit-definition flag once the constructor has been defined"); + "Can only get the implicit-definition flag once the " + "constructor has been defined"); return ImplicitlyDefined; } @@ -710,10 +739,41 @@ public: /// implicitly defined or not. void setImplicitlyDefined(bool ID) { assert(isThisDeclarationADefinition() && - "Can only set the implicit-definition flag once the constructor has been defined"); + "Can only set the implicit-definition flag once the constructor " + "has been defined"); ImplicitlyDefined = ID; } + /// init_iterator - Iterates through the member/base initializer list. + typedef CXXBaseOrMemberInitializer **init_iterator; + + /// init_const_iterator - Iterates through the memberbase initializer list. + typedef CXXBaseOrMemberInitializer * const * init_const_iterator; + + /// begin() - Retrieve an iterator to the first initializer. + init_iterator begin() { return BaseOrMemberInitializers; } + /// begin() - Retrieve an iterator to the first initializer. + init_const_iterator begin() const { return BaseOrMemberInitializers; } + + /// end() - Retrieve an iterator past the last initializer. + init_iterator end() { + return BaseOrMemberInitializers + NumBaseOrMemberInitializers; + } + /// end() - Retrieve an iterator past the last initializer. + init_const_iterator end() const { + return BaseOrMemberInitializers + NumBaseOrMemberInitializers; + } + + /// getNumArgs - Determine the number of arguments used to + /// initialize the member or base. + unsigned getNumBaseOrMemberInitializers() const { + return NumBaseOrMemberInitializers; + } + + void setBaseOrMemberInitializers(ASTContext &C, + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers); + /// isDefaultConstructor - Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to /// default-initialize a class of this type. diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 3943ddc19638c..2fcdaa3e2959d 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -242,10 +242,10 @@ public: return ImplementationControl(DeclImplementation); } - virtual Stmt *getBody(ASTContext &C) const { + virtual Stmt *getBody() const { return (Stmt*) Body; } - CompoundStmt *getBody() { return (CompoundStmt*)Body; } + CompoundStmt *getCompoundBody() { return (CompoundStmt*)Body; } void setBody(Stmt *B) { Body = B; } // Implement isa/cast/dyncast/etc. @@ -291,55 +291,52 @@ public: // Iterator access to properties. typedef specific_decl_iterator<ObjCPropertyDecl> prop_iterator; - prop_iterator prop_begin(ASTContext &Context) const { - return prop_iterator(decls_begin(Context)); + prop_iterator prop_begin() const { + return prop_iterator(decls_begin()); } - prop_iterator prop_end(ASTContext &Context) const { - return prop_iterator(decls_end(Context)); + prop_iterator prop_end() const { + return prop_iterator(decls_end()); } // Iterator access to instance/class methods. typedef specific_decl_iterator<ObjCMethodDecl> method_iterator; - method_iterator meth_begin(ASTContext &Context) const { - return method_iterator(decls_begin(Context)); + method_iterator meth_begin() const { + return method_iterator(decls_begin()); } - method_iterator meth_end(ASTContext &Context) const { - return method_iterator(decls_end(Context)); + method_iterator meth_end() const { + return method_iterator(decls_end()); } typedef filtered_decl_iterator<ObjCMethodDecl, &ObjCMethodDecl::isInstanceMethod> instmeth_iterator; - instmeth_iterator instmeth_begin(ASTContext &Context) const { - return instmeth_iterator(decls_begin(Context)); + instmeth_iterator instmeth_begin() const { + return instmeth_iterator(decls_begin()); } - instmeth_iterator instmeth_end(ASTContext &Context) const { - return instmeth_iterator(decls_end(Context)); + instmeth_iterator instmeth_end() const { + return instmeth_iterator(decls_end()); } typedef filtered_decl_iterator<ObjCMethodDecl, &ObjCMethodDecl::isClassMethod> classmeth_iterator; - classmeth_iterator classmeth_begin(ASTContext &Context) const { - return classmeth_iterator(decls_begin(Context)); + classmeth_iterator classmeth_begin() const { + return classmeth_iterator(decls_begin()); } - classmeth_iterator classmeth_end(ASTContext &Context) const { - return classmeth_iterator(decls_end(Context)); + classmeth_iterator classmeth_end() const { + return classmeth_iterator(decls_end()); } // Get the local instance/class method declared in this interface. - ObjCMethodDecl *getInstanceMethod(ASTContext &Context, Selector Sel) const; - ObjCMethodDecl *getClassMethod(ASTContext &Context, Selector Sel) const; - ObjCIvarDecl *getIvarDecl(ASTContext &Context, IdentifierInfo *Id) const; + ObjCMethodDecl *getInstanceMethod(Selector Sel) const; + ObjCMethodDecl *getClassMethod(Selector Sel) const; + ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; - ObjCMethodDecl * - getMethod(ASTContext &Context, Selector Sel, bool isInstance) const { - return isInstance ? getInstanceMethod(Context, Sel) - : getClassMethod(Context, Sel); + ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const { + return isInstance ? getInstanceMethod(Sel) : getClassMethod(Sel); } - ObjCPropertyDecl *FindPropertyDeclaration(ASTContext &Context, - IdentifierInfo *PropertyId) const; + ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; // Marks the end of the container. SourceLocation getAtEndLoc() const { return AtEndLoc; } @@ -474,19 +471,17 @@ public: return false; } - ObjCIvarDecl *lookupInstanceVariable(ASTContext &Context, - IdentifierInfo *IVarName, + ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName, ObjCInterfaceDecl *&ClassDeclared); - ObjCIvarDecl *lookupInstanceVariable(ASTContext &Context, - IdentifierInfo *IVarName) { + ObjCIvarDecl *lookupInstanceVariable(IdentifierInfo *IVarName) { ObjCInterfaceDecl *ClassDeclared; - return lookupInstanceVariable(Context, IVarName, ClassDeclared); + return lookupInstanceVariable(IVarName, ClassDeclared); } // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. - ObjCMethodDecl *lookupInstanceMethod(ASTContext &Context, Selector Sel); - ObjCMethodDecl *lookupClassMethod(ASTContext &Context, Selector Sel); + ObjCMethodDecl *lookupInstanceMethod(Selector Sel); + ObjCMethodDecl *lookupClassMethod(Selector Sel); ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); // Location information, modeled after the Stmt API. @@ -648,8 +643,8 @@ public: // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. - ObjCMethodDecl *lookupInstanceMethod(ASTContext &Context, Selector Sel); - ObjCMethodDecl *lookupClassMethod(ASTContext &Context, Selector Sel); + ObjCMethodDecl *lookupInstanceMethod(Selector Sel); + ObjCMethodDecl *lookupClassMethod(Selector Sel); bool isForwardDecl() const { return isForwardProtoDecl; } void setForwardDecl(bool val) { isForwardProtoDecl = val; } @@ -831,61 +826,57 @@ public: ObjCInterfaceDecl *getClassInterface() { return ClassInterface; } void setClassInterface(ObjCInterfaceDecl *IFace) { ClassInterface = IFace; } - void addInstanceMethod(ASTContext &Context, ObjCMethodDecl *method) { + void addInstanceMethod(ObjCMethodDecl *method) { // FIXME: Context should be set correctly before we get here. method->setLexicalDeclContext(this); - addDecl(Context, method); + addDecl(method); } - void addClassMethod(ASTContext &Context, ObjCMethodDecl *method) { + void addClassMethod(ObjCMethodDecl *method) { // FIXME: Context should be set correctly before we get here. method->setLexicalDeclContext(this); - addDecl(Context, method); + addDecl(method); } // Get the local instance/class method declared in this interface. - ObjCMethodDecl *getInstanceMethod(ASTContext &Context, Selector Sel) const; - ObjCMethodDecl *getClassMethod(ASTContext &Context, Selector Sel) const; - ObjCMethodDecl *getMethod(ASTContext &Context, Selector Sel, - bool isInstance) const { - return isInstance ? getInstanceMethod(Context, Sel) - : getClassMethod(Context, Sel); + ObjCMethodDecl *getInstanceMethod(Selector Sel) const; + ObjCMethodDecl *getClassMethod(Selector Sel) const; + ObjCMethodDecl *getMethod(Selector Sel, bool isInstance) const { + return isInstance ? getInstanceMethod(Sel) + : getClassMethod(Sel); } - void addPropertyImplementation(ASTContext &Context, - ObjCPropertyImplDecl *property); + void addPropertyImplementation(ObjCPropertyImplDecl *property); - ObjCPropertyImplDecl *FindPropertyImplDecl(ASTContext &Context, - IdentifierInfo *propertyId) const; - ObjCPropertyImplDecl *FindPropertyImplIvarDecl(ASTContext &Context, - IdentifierInfo *ivarId) const; + ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const; + ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const; // Iterator access to properties. typedef specific_decl_iterator<ObjCPropertyImplDecl> propimpl_iterator; - propimpl_iterator propimpl_begin(ASTContext &Context) const { - return propimpl_iterator(decls_begin(Context)); + propimpl_iterator propimpl_begin() const { + return propimpl_iterator(decls_begin()); } - propimpl_iterator propimpl_end(ASTContext &Context) const { - return propimpl_iterator(decls_end(Context)); + propimpl_iterator propimpl_end() const { + return propimpl_iterator(decls_end()); } typedef filtered_decl_iterator<ObjCMethodDecl, &ObjCMethodDecl::isInstanceMethod> instmeth_iterator; - instmeth_iterator instmeth_begin(ASTContext &Context) const { - return instmeth_iterator(decls_begin(Context)); + instmeth_iterator instmeth_begin() const { + return instmeth_iterator(decls_begin()); } - instmeth_iterator instmeth_end(ASTContext &Context) const { - return instmeth_iterator(decls_end(Context)); + instmeth_iterator instmeth_end() const { + return instmeth_iterator(decls_end()); } typedef filtered_decl_iterator<ObjCMethodDecl, &ObjCMethodDecl::isClassMethod> classmeth_iterator; - classmeth_iterator classmeth_begin(ASTContext &Context) const { - return classmeth_iterator(decls_begin(Context)); + classmeth_iterator classmeth_begin() const { + return classmeth_iterator(decls_begin()); } - classmeth_iterator classmeth_end(ASTContext &Context) const { - return classmeth_iterator(decls_end(Context)); + classmeth_iterator classmeth_end() const { + return classmeth_iterator(decls_end()); } // Location information, modeled after the Stmt API. @@ -1002,17 +993,17 @@ public: void setSuperClass(ObjCInterfaceDecl * superCls) { SuperClass = superCls; } typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator; - ivar_iterator ivar_begin(ASTContext &Context) const { - return ivar_iterator(decls_begin(Context)); + ivar_iterator ivar_begin() const { + return ivar_iterator(decls_begin()); } - ivar_iterator ivar_end(ASTContext &Context) const { - return ivar_iterator(decls_end(Context)); + ivar_iterator ivar_end() const { + return ivar_iterator(decls_end()); } - unsigned ivar_size(ASTContext &Context) const { - return std::distance(ivar_begin(Context), ivar_end(Context)); + unsigned ivar_size() const { + return std::distance(ivar_begin(), ivar_end()); } - bool ivar_empty(ASTContext &Context) const { - return ivar_begin(Context) == ivar_end(Context); + bool ivar_empty() const { + return ivar_begin() == ivar_end(); } static bool classof(const Decl *D) { diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index aad19a63ef0f2..5d0fe158e054f 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -100,6 +100,352 @@ public: } }; +/// \brief Represents a template argument within a class template +/// specialization. +class TemplateArgument { + union { + uintptr_t TypeOrValue; + struct { + char Value[sizeof(llvm::APSInt)]; + void *Type; + } Integer; + struct { + TemplateArgument *Args; + unsigned NumArgs; + bool CopyArgs; + } Args; + }; + + /// \brief Location of the beginning of this template argument. + SourceLocation StartLoc; + +public: + /// \brief The type of template argument we're storing. + enum ArgKind { + Null = 0, + /// The template argument is a type. Its value is stored in the + /// TypeOrValue field. + Type = 1, + /// The template argument is a declaration + Declaration = 2, + /// The template argument is an integral value stored in an llvm::APSInt. + Integral = 3, + /// The template argument is a value- or type-dependent expression + /// stored in an Expr*. + Expression = 4, + + /// The template argument is actually a parameter pack. Arguments are stored + /// in the Args struct. + Pack = 5 + } Kind; + + /// \brief Construct an empty, invalid template argument. + TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { } + + /// \brief Construct a template type argument. + TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) { + TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); + StartLoc = Loc; + } + + /// \brief Construct a template argument that refers to a + /// declaration, which is either an external declaration or a + /// template declaration. + TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) { + // FIXME: Need to be sure we have the "canonical" declaration! + TypeOrValue = reinterpret_cast<uintptr_t>(D); + StartLoc = Loc; + } + + /// \brief Construct an integral constant template argument. + TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value, + QualType Type) + : Kind(Integral) { + new (Integer.Value) llvm::APSInt(Value); + Integer.Type = Type.getAsOpaquePtr(); + StartLoc = Loc; + } + + /// \brief Construct a template argument that is an expression. + /// + /// This form of template argument only occurs in template argument + /// lists used for dependent types and for expression; it will not + /// occur in a non-dependent, canonical template argument list. + TemplateArgument(Expr *E); + + /// \brief Copy constructor for a template argument. + TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { + if (Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else if (Kind == Pack) { + Args.NumArgs = Other.Args.NumArgs; + Args.Args = new TemplateArgument[Args.NumArgs]; + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I] = Other.Args.Args[I]; + } + else + TypeOrValue = Other.TypeOrValue; + StartLoc = Other.StartLoc; + } + + TemplateArgument& operator=(const TemplateArgument& Other) { + // FIXME: Does not provide the strong guarantee for exception + // safety. + using llvm::APSInt; + + // FIXME: Handle Packs + assert(Kind != Pack && "FIXME: Handle packs"); + assert(Other.Kind != Pack && "FIXME: Handle packs"); + + if (Kind == Other.Kind && Kind == Integral) { + // Copy integral values. + *this->getAsIntegral() = *Other.getAsIntegral(); + Integer.Type = Other.Integer.Type; + } else { + // Destroy the current integral value, if that's what we're holding. + if (Kind == Integral) + getAsIntegral()->~APSInt(); + + Kind = Other.Kind; + + if (Other.Kind == Integral) { + new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); + Integer.Type = Other.Integer.Type; + } else + TypeOrValue = Other.TypeOrValue; + } + StartLoc = Other.StartLoc; + + return *this; + } + + ~TemplateArgument() { + using llvm::APSInt; + + if (Kind == Integral) + getAsIntegral()->~APSInt(); + else if (Kind == Pack && Args.CopyArgs) + delete[] Args.Args; + } + + /// \brief Return the kind of stored template argument. + ArgKind getKind() const { return Kind; } + + /// \brief Determine whether this template argument has no value. + bool isNull() const { return Kind == Null; } + + /// \brief Retrieve the template argument as a type. + QualType getAsType() const { + if (Kind != Type) + return QualType(); + + return QualType::getFromOpaquePtr( + reinterpret_cast<void*>(TypeOrValue)); + } + + /// \brief Retrieve the template argument as a declaration. + Decl *getAsDecl() const { + if (Kind != Declaration) + return 0; + return reinterpret_cast<Decl *>(TypeOrValue); + } + + /// \brief Retrieve the template argument as an integral value. + llvm::APSInt *getAsIntegral() { + if (Kind != Integral) + return 0; + return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); + } + + const llvm::APSInt *getAsIntegral() const { + return const_cast<TemplateArgument*>(this)->getAsIntegral(); + } + + /// \brief Retrieve the type of the integral value. + QualType getIntegralType() const { + if (Kind != Integral) + return QualType(); + + return QualType::getFromOpaquePtr(Integer.Type); + } + + void setIntegralType(QualType T) { + assert(Kind == Integral && + "Cannot set the integral type of a non-integral template argument"); + Integer.Type = T.getAsOpaquePtr(); + }; + + /// \brief Retrieve the template argument as an expression. + Expr *getAsExpr() const { + if (Kind != Expression) + return 0; + + return reinterpret_cast<Expr *>(TypeOrValue); + } + + /// \brief Iterator that traverses the elements of a template argument pack. + typedef const TemplateArgument * pack_iterator; + + /// \brief Iterator referencing the first argument of a template argument + /// pack. + pack_iterator pack_begin() const { + assert(Kind == Pack); + return Args.Args; + } + + /// \brief Iterator referencing one past the last argument of a template + /// argument pack. + pack_iterator pack_end() const { + assert(Kind == Pack); + return Args.Args + Args.NumArgs; + } + + /// \brief The number of template arguments in the given template argument + /// pack. + unsigned pack_size() const { + assert(Kind == Pack); + return Args.NumArgs; + } + + /// \brief Retrieve the location where the template argument starts. + SourceLocation getLocation() const { return StartLoc; } + + /// \brief Construct a template argument pack. + void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); + + /// \brief Used to insert TemplateArguments into FoldingSets. + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger(Kind); + switch (Kind) { + case Null: + break; + + case Type: + getAsType().Profile(ID); + break; + + case Declaration: + ID.AddPointer(getAsDecl()); // FIXME: Must be canonical! + break; + + case Integral: + getAsIntegral()->Profile(ID); + getIntegralType().Profile(ID); + break; + + case Expression: + // FIXME: We need a canonical representation of expressions. + ID.AddPointer(getAsExpr()); + break; + + case Pack: + ID.AddInteger(Args.NumArgs); + for (unsigned I = 0; I != Args.NumArgs; ++I) + Args.Args[I].Profile(ID); + } + } +}; + +/// \brief A helper class for making template argument lists. +class TemplateArgumentListBuilder { + TemplateArgument *StructuredArgs; + unsigned MaxStructuredArgs; + unsigned NumStructuredArgs; + + TemplateArgument *FlatArgs; + unsigned MaxFlatArgs; + unsigned NumFlatArgs; + + bool AddingToPack; + unsigned PackBeginIndex; + +public: + TemplateArgumentListBuilder(const TemplateParameterList *Parameters, + unsigned NumTemplateArgs) + : StructuredArgs(0), MaxStructuredArgs(Parameters->size()), + NumStructuredArgs(0), FlatArgs(0), + MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0), + AddingToPack(false), PackBeginIndex(0) { } + + void Append(const TemplateArgument& Arg); + void BeginPack(); + void EndPack(); + + void ReleaseArgs(); + + unsigned flatSize() const { + return NumFlatArgs; + } + const TemplateArgument *getFlatArguments() const { + return FlatArgs; + } + + unsigned structuredSize() const { + // If we don't have any structured args, just reuse the flat size. + if (!StructuredArgs) + return flatSize(); + + return NumStructuredArgs; + } + const TemplateArgument *getStructuredArguments() const { + // If we don't have any structured args, just reuse the flat args. + if (!StructuredArgs) + return getFlatArguments(); + + return StructuredArgs; + } +}; + +/// \brief A template argument list. +/// +/// FIXME: In the future, this class will be extended to support +/// variadic templates and member templates, which will make some of +/// the function names below make more sense. +class TemplateArgumentList { + /// \brief The template argument list. + /// + /// The integer value will be non-zero to indicate that this + /// template argument list does not own the pointer. + llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments; + + /// \brief The number of template arguments in this template + /// argument list. + unsigned NumFlatArguments; + + llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments; + unsigned NumStructuredArguments; + +public: + TemplateArgumentList(ASTContext &Context, + TemplateArgumentListBuilder &Builder, + bool TakeArgs); + + ~TemplateArgumentList(); + + /// \brief Retrieve the template argument at a given index. + const TemplateArgument &get(unsigned Idx) const { + assert(Idx < NumFlatArguments && "Invalid template argument index"); + return getFlatArgumentList()[Idx]; + } + + /// \brief Retrieve the template argument at a given index. + const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } + + /// \brief Retrieve the number of template arguments in this + /// template argument list. + unsigned size() const { return NumFlatArguments; } + + /// \brief Retrieve the number of template arguments in the + /// flattened template argument list. + unsigned flat_size() const { return NumFlatArguments; } + + /// \brief Retrieve the flattened template argument list. + const TemplateArgument *getFlatArgumentList() const { + return FlatArguments.getPointer(); + } +}; + //===----------------------------------------------------------------------===// // Kinds of Templates //===----------------------------------------------------------------------===// @@ -154,18 +500,110 @@ protected: TemplateParameterList* TemplateParams; }; +/// \brief Provides information about a function template specialization, +/// which is a FunctionDecl that has been explicitly specialization or +/// instantiated from a function template. +class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode { +public: + /// \brief The function template specialization that this structure + /// describes. + FunctionDecl *Function; + + /// \brief The function template from which this function template + /// specialization was generated. + /// + /// The bit will be 0 for an implicit instantiation, 1 for an explicit + /// specialization. + llvm::PointerIntPair<FunctionTemplateDecl *, 1> Template; + + /// \brief The template arguments used to produce the function template + /// specialization from the function template. + const TemplateArgumentList *TemplateArguments; + + /// \brief Retrieve the template from which this function was specialized. + FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); } + + /// \brief Determine whether this is an explicit specialization. + bool isExplicitSpecialization() const { return Template.getInt(); } + + /// \brief Set whether this is an explicit specialization or an implicit + /// instantiation. + void setExplicitSpecialization(bool ES) { + Template.setInt(ES); + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, TemplateArguments->getFlatArgumentList(), + TemplateArguments->flat_size()); + } + + static void + Profile(llvm::FoldingSetNodeID &ID, const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs) { + ID.AddInteger(NumTemplateArgs); + for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) + TemplateArgs[Arg].Profile(ID); + } +}; + /// Declaration of a template function. -class FunctionTemplateDecl : public TemplateDecl { +class FunctionTemplateDecl : public TemplateDecl { protected: + /// \brief Data that is common to all of the declarations of a given + /// function template. + struct Common { + /// \brief The function template specializations for this function + /// template, including explicit specializations and instantiations. + llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations; + }; + + /// \brief A pointer to the previous declaration (if this is a redeclaration) + /// or to the data that is common to all declarations of this function + /// template. + llvm::PointerUnion<Common*, FunctionTemplateDecl*> CommonOrPrev; + + /// \brief Retrieves the "common" pointer shared by all + /// (re-)declarations of the same function template. Calling this routine + /// may implicitly allocate memory for the common pointer. + Common *getCommonPtr(); + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } + : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl), + CommonOrPrev((Common*)0) { } + public: - /// Get the underling function declaration of the template. + void Destroy(ASTContext &C); + + /// Get the underlying function declaration of the template. FunctionDecl *getTemplatedDecl() const { return static_cast<FunctionDecl*>(TemplatedDecl); } + /// \brief Retrieve the set of function template specializations of this + /// function template. + llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() { + return getCommonPtr()->Specializations; + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + const FunctionTemplateDecl *getPreviousDeclaration() const { + return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + FunctionTemplateDecl *getPreviousDeclaration() { + return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>(); + } + + /// \brief Set the previous declaration of this function template. + void setPreviousDeclaration(FunctionTemplateDecl *Prev) { + if (Prev) + CommonOrPrev = Prev; + } + /// Create a template function node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -396,352 +834,6 @@ public: static bool classof(const TemplateTemplateParmDecl *D) { return true; } }; -/// \brief Represents a template argument within a class template -/// specialization. -class TemplateArgument { - union { - uintptr_t TypeOrValue; - struct { - char Value[sizeof(llvm::APSInt)]; - void *Type; - } Integer; - struct { - TemplateArgument *Args; - unsigned NumArgs; - bool CopyArgs; - } Args; - }; - - /// \brief Location of the beginning of this template argument. - SourceLocation StartLoc; - -public: - /// \brief The type of template argument we're storing. - enum ArgKind { - Null = 0, - /// The template argument is a type. Its value is stored in the - /// TypeOrValue field. - Type = 1, - /// The template argument is a declaration - Declaration = 2, - /// The template argument is an integral value stored in an llvm::APSInt. - Integral = 3, - /// The template argument is a value- or type-dependent expression - /// stored in an Expr*. - Expression = 4, - - /// The template argument is actually a parameter pack. Arguments are stored - /// in the Args struct. - Pack = 5 - } Kind; - - /// \brief Construct an empty, invalid template argument. - TemplateArgument() : TypeOrValue(0), StartLoc(), Kind(Null) { } - - /// \brief Construct a template type argument. - TemplateArgument(SourceLocation Loc, QualType T) : Kind(Type) { - TypeOrValue = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); - StartLoc = Loc; - } - - /// \brief Construct a template argument that refers to a - /// declaration, which is either an external declaration or a - /// template declaration. - TemplateArgument(SourceLocation Loc, Decl *D) : Kind(Declaration) { - // FIXME: Need to be sure we have the "canonical" declaration! - TypeOrValue = reinterpret_cast<uintptr_t>(D); - StartLoc = Loc; - } - - /// \brief Construct an integral constant template argument. - TemplateArgument(SourceLocation Loc, const llvm::APSInt &Value, - QualType Type) - : Kind(Integral) { - new (Integer.Value) llvm::APSInt(Value); - Integer.Type = Type.getAsOpaquePtr(); - StartLoc = Loc; - } - - /// \brief Construct a template argument that is an expression. - /// - /// This form of template argument only occurs in template argument - /// lists used for dependent types and for expression; it will not - /// occur in a non-dependent, canonical template argument list. - TemplateArgument(Expr *E); - - /// \brief Copy constructor for a template argument. - TemplateArgument(const TemplateArgument &Other) : Kind(Other.Kind) { - if (Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else if (Kind == Pack) { - Args.NumArgs = Other.Args.NumArgs; - Args.Args = new TemplateArgument[Args.NumArgs]; - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I] = Other.Args.Args[I]; - } - else - TypeOrValue = Other.TypeOrValue; - StartLoc = Other.StartLoc; - } - - TemplateArgument& operator=(const TemplateArgument& Other) { - // FIXME: Does not provide the strong guarantee for exception - // safety. - using llvm::APSInt; - - // FIXME: Handle Packs - assert(Kind != Pack && "FIXME: Handle packs"); - assert(Other.Kind != Pack && "FIXME: Handle packs"); - - if (Kind == Other.Kind && Kind == Integral) { - // Copy integral values. - *this->getAsIntegral() = *Other.getAsIntegral(); - Integer.Type = Other.Integer.Type; - } else { - // Destroy the current integral value, if that's what we're holding. - if (Kind == Integral) - getAsIntegral()->~APSInt(); - - Kind = Other.Kind; - - if (Other.Kind == Integral) { - new (Integer.Value) llvm::APSInt(*Other.getAsIntegral()); - Integer.Type = Other.Integer.Type; - } else - TypeOrValue = Other.TypeOrValue; - } - StartLoc = Other.StartLoc; - - return *this; - } - - ~TemplateArgument() { - using llvm::APSInt; - - if (Kind == Integral) - getAsIntegral()->~APSInt(); - else if (Kind == Pack && Args.CopyArgs) - delete[] Args.Args; - } - - /// \brief Return the kind of stored template argument. - ArgKind getKind() const { return Kind; } - - /// \brief Determine whether this template argument has no value. - bool isNull() const { return Kind == Null; } - - /// \brief Retrieve the template argument as a type. - QualType getAsType() const { - if (Kind != Type) - return QualType(); - - return QualType::getFromOpaquePtr( - reinterpret_cast<void*>(TypeOrValue)); - } - - /// \brief Retrieve the template argument as a declaration. - Decl *getAsDecl() const { - if (Kind != Declaration) - return 0; - return reinterpret_cast<Decl *>(TypeOrValue); - } - - /// \brief Retrieve the template argument as an integral value. - llvm::APSInt *getAsIntegral() { - if (Kind != Integral) - return 0; - return reinterpret_cast<llvm::APSInt*>(&Integer.Value[0]); - } - - const llvm::APSInt *getAsIntegral() const { - return const_cast<TemplateArgument*>(this)->getAsIntegral(); - } - - /// \brief Retrieve the type of the integral value. - QualType getIntegralType() const { - if (Kind != Integral) - return QualType(); - - return QualType::getFromOpaquePtr(Integer.Type); - } - - void setIntegralType(QualType T) { - assert(Kind == Integral && - "Cannot set the integral type of a non-integral template argument"); - Integer.Type = T.getAsOpaquePtr(); - }; - - /// \brief Retrieve the template argument as an expression. - Expr *getAsExpr() const { - if (Kind != Expression) - return 0; - - return reinterpret_cast<Expr *>(TypeOrValue); - } - - /// \brief Iterator that traverses the elements of a template argument pack. - typedef const TemplateArgument * pack_iterator; - - /// \brief Iterator referencing the first argument of a template argument - /// pack. - pack_iterator pack_begin() const { - assert(Kind == Pack); - return Args.Args; - } - - /// \brief Iterator referencing one past the last argument of a template - /// argument pack. - pack_iterator pack_end() const { - assert(Kind == Pack); - return Args.Args + Args.NumArgs; - } - - /// \brief The number of template arguments in the given template argument - /// pack. - unsigned pack_size() const { - assert(Kind == Pack); - return Args.NumArgs; - } - - /// \brief Retrieve the location where the template argument starts. - SourceLocation getLocation() const { return StartLoc; } - - /// \brief Construct a template argument pack. - void setArgumentPack(TemplateArgument *Args, unsigned NumArgs, bool CopyArgs); - - /// \brief Used to insert TemplateArguments into FoldingSets. - void Profile(llvm::FoldingSetNodeID &ID) const { - ID.AddInteger(Kind); - switch (Kind) { - case Null: - break; - - case Type: - getAsType().Profile(ID); - break; - - case Declaration: - ID.AddPointer(getAsDecl()); // FIXME: Must be canonical! - break; - - case Integral: - getAsIntegral()->Profile(ID); - getIntegralType().Profile(ID); - break; - - case Expression: - // FIXME: We need a canonical representation of expressions. - ID.AddPointer(getAsExpr()); - break; - - case Pack: - ID.AddInteger(Args.NumArgs); - for (unsigned I = 0; I != Args.NumArgs; ++I) - Args.Args[I].Profile(ID); - } - } -}; - -/// \brief A helper class for making template argument lists. -class TemplateArgumentListBuilder { - TemplateArgument *StructuredArgs; - unsigned MaxStructuredArgs; - unsigned NumStructuredArgs; - - TemplateArgument *FlatArgs; - unsigned MaxFlatArgs; - unsigned NumFlatArgs; - - bool AddingToPack; - unsigned PackBeginIndex; - -public: - TemplateArgumentListBuilder(const TemplateParameterList *Parameters, - unsigned NumTemplateArgs) - : StructuredArgs(0), MaxStructuredArgs(Parameters->size()), - NumStructuredArgs(0), FlatArgs(0), - MaxFlatArgs(std::max(MaxStructuredArgs, NumTemplateArgs)), NumFlatArgs(0), - AddingToPack(false), PackBeginIndex(0) { } - - void Append(const TemplateArgument& Arg); - void BeginPack(); - void EndPack(); - - void ReleaseArgs(); - - unsigned flatSize() const { - return NumFlatArgs; - } - const TemplateArgument *getFlatArguments() const { - return FlatArgs; - } - - unsigned structuredSize() const { - // If we don't have any structured args, just reuse the flat size. - if (!StructuredArgs) - return flatSize(); - - return NumStructuredArgs; - } - const TemplateArgument *getStructuredArguments() const { - // If we don't have any structured args, just reuse the flat args. - if (!StructuredArgs) - return getFlatArguments(); - - return StructuredArgs; - } -}; - -/// \brief A template argument list. -/// -/// FIXME: In the future, this class will be extended to support -/// variadic templates and member templates, which will make some of -/// the function names below make more sense. -class TemplateArgumentList { - /// \brief The template argument list. - /// - /// The integer value will be non-zero to indicate that this - /// template argument list does not own the pointer. - llvm::PointerIntPair<const TemplateArgument *, 1> FlatArguments; - - /// \brief The number of template arguments in this template - /// argument list. - unsigned NumFlatArguments; - - llvm::PointerIntPair<const TemplateArgument *, 1> StructuredArguments; - unsigned NumStructuredArguments; - -public: - TemplateArgumentList(ASTContext &Context, - TemplateArgumentListBuilder &Builder, - bool TakeArgs); - - ~TemplateArgumentList(); - - /// \brief Retrieve the template argument at a given index. - const TemplateArgument &get(unsigned Idx) const { - assert(Idx < NumFlatArguments && "Invalid template argument index"); - return getFlatArgumentList()[Idx]; - } - - /// \brief Retrieve the template argument at a given index. - const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } - - /// \brief Retrieve the number of template arguments in this - /// template argument list. - unsigned size() const { return NumFlatArguments; } - - /// \brief Retrieve the number of template arguments in the - /// flattened template argument list. - unsigned flat_size() const { return NumFlatArguments; } - - /// \brief Retrieve the flattened template argument list. - const TemplateArgument *getFlatArgumentList() const { - return FlatArguments.getPointer(); - } -}; - // \brief Describes the kind of template specialization that a // particular template specialization declaration represents. enum TemplateSpecializationKind { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 2ed91124758d5..6a1046e6d03fe 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -124,7 +124,7 @@ public: /// with location to warn on and the source range[s] to report with the /// warning. bool isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, - SourceRange &R2, ASTContext &Context) const; + SourceRange &R2) const; /// isLvalue - C99 6.3.2.1: an lvalue is an expression with an object type or /// incomplete type other than void. Nonarray expressions that can be lvalues: @@ -467,9 +467,9 @@ class FloatingLiteral : public Expr { bool IsExact : 1; SourceLocation Loc; public: - FloatingLiteral(const llvm::APFloat &V, bool* isexact, + FloatingLiteral(const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L) - : Expr(FloatingLiteralClass, Type), Value(V), IsExact(*isexact), Loc(L) {} + : Expr(FloatingLiteralClass, Type), Value(V), IsExact(isexact), Loc(L) {} /// \brief Construct an empty floating-point literal. explicit FloatingLiteral(EmptyShell Empty) @@ -2433,9 +2433,6 @@ public: const Stmt *getBody() const; Stmt *getBody(); - const Stmt *getBody(ASTContext &C) const { return getBody(); } - Stmt *getBody(ASTContext &C) { return getBody(); } - virtual SourceRange getSourceRange() const { return SourceRange(getCaretLocation(), getBody()->getLocEnd()); } diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index f9f5da1291428..7d76a49d1267b 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1017,6 +1017,100 @@ public: virtual StmtIterator child_end(); }; +/// \brief An expression that refers to a C++ template-id, such as +/// @c isa<FunctionDecl>. +class TemplateIdRefExpr : public Expr { + /// \brief If this template-id was qualified-id, e.g., @c std::sort<int>, + /// this nested name specifier contains the @c std::. + NestedNameSpecifier *Qualifier; + + /// \brief If this template-id was a qualified-id, e.g., @c std::sort<int>, + /// this covers the source code range of the @c std::. + SourceRange QualifierRange; + + /// \brief The actual template to which this template-id refers. + TemplateName Template; + + /// \brief The source location of the template name. + SourceLocation TemplateNameLoc; + + /// \brief The source location of the left angle bracket ('<'); + SourceLocation LAngleLoc; + + /// \brief The source location of the right angle bracket ('>'); + SourceLocation RAngleLoc; + + /// \brief The number of template arguments in TemplateArgs. + unsigned NumTemplateArgs; + + TemplateIdRefExpr(QualType T, + NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + TemplateName Template, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc); + +public: + static TemplateIdRefExpr * + Create(ASTContext &Context, QualType T, + NestedNameSpecifier *Qualifier, SourceRange QualifierRange, + TemplateName Template, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, SourceLocation RAngleLoc); + + void Destroy(ASTContext &Context); + + /// \brief Retrieve the nested name specifier used to qualify the name of + /// this template-id, e.g., the "std::sort" in @c std::sort<int>, or NULL + /// if this template-id was an unqualified-id. + NestedNameSpecifier *getQualifier() const { return Qualifier; } + + /// \brief Retrieve the source range describing the nested name specifier + /// used to qualified the name of this template-id, if the name was qualified. + SourceRange getQualifierRange() const { return QualifierRange; } + + /// \brief Retrieve the name of the template referenced, e.g., "sort" in + /// @c std::sort<int>; + TemplateName getTemplateName() const { return Template; } + + /// \brief Retrieve the location of the name of the template referenced, e.g., + /// the location of "sort" in @c std::sort<int>. + SourceLocation getTemplateNameLoc() const { return TemplateNameLoc; } + + /// \brief Retrieve the location of the left angle bracket following the + /// template name ('<'). + SourceLocation getLAngleLoc() const { return LAngleLoc; } + + /// \brief Retrieve the template arguments provided as part of this + /// template-id. + const TemplateArgument *getTemplateArgs() const { + return reinterpret_cast<const TemplateArgument *>(this + 1); + } + + /// \brief Retrieve the number of template arguments provided as part of this + /// template-id. + unsigned getNumTemplateArgs() const { return NumTemplateArgs; } + + /// \brief Retrieve the location of the right angle bracket following the + /// template arguments ('>'). + SourceLocation getRAngleLoc() const { return RAngleLoc; } + + virtual SourceRange getSourceRange() const { + return SourceRange(Qualifier? QualifierRange.getBegin() : TemplateNameLoc, + RAngleLoc); + } + + // Iterators + virtual child_iterator child_begin(); + virtual child_iterator child_end(); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == TemplateIdRefExprClass; + } + static bool classof(const TemplateIdRefExpr *) { return true; } +}; + class CXXExprWithTemporaries : public Expr { Stmt *SubExpr; diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 4219bd507a900..6f862a55d4bad 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -18,6 +18,7 @@ #include "clang/AST/Type.h" #include "llvm/ADT/SmallVector.h" #include <cassert> +#include <vector> namespace clang { class ASTConsumer; @@ -57,6 +58,14 @@ public: virtual ~ExternalASTSource(); + /// \brief Reads the source ranges that correspond to comments from + /// an external AST source. + /// + /// \param Comments the contents of this vector will be + /// replaced with the sorted set of source ranges corresponding to + /// comments in the source code. + virtual void ReadComments(std::vector<SourceRange> &Comments) = 0; + /// \brief Resolve a type ID into a type, potentially building a new /// type. virtual QualType GetType(uint32_t ID) = 0; diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 4eea1031f0637..b304cc8e8a042 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -28,6 +28,7 @@ class NamespaceDecl; class IdentifierInfo; class PrintingPolicy; class Type; +class LangOptions; /// \brief Represents a C++ nested name specifier, such as /// "::std::vector<int>::". @@ -175,7 +176,7 @@ public: /// \brief Dump the nested name specifier to standard output to aid /// in debugging. - void dump(); + void dump(const LangOptions &LO); }; } diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 385602b1fb9c4..6ad3a6bcc2763 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -22,6 +22,7 @@ namespace clang { class Stmt; class TagDecl; +class LangOptions; class PrinterHelper { public: @@ -33,16 +34,15 @@ public: /// declarations should be printed. struct PrintingPolicy { /// \brief Create a default printing policy for C. - PrintingPolicy() - : Indentation(2), CPlusPlus(false), SuppressSpecifiers(false), + PrintingPolicy(const LangOptions &LO) + : Indentation(2), LangOpts(LO), SuppressSpecifiers(false), SuppressTag(false), SuppressTagKind(false), Dump(false) { } /// \brief The number of spaces to use to indent each line. unsigned Indentation : 8; - /// \brief Whether we're printing C++ code (otherwise, we're - /// printing C code). - bool CPlusPlus : 1; + /// \brief What language we're printing. + const LangOptions &LangOpts; /// \brief Whether we should suppress printing of the actual specifiers for /// the given type or declaration. diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index a8688f62e2d9e..0a64dafd4e2c8 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -187,14 +187,14 @@ public: /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST /// back to its original source language syntax. void dumpPretty(ASTContext& Context) const; - void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper = 0, - const PrintingPolicy &Policy = PrintingPolicy(), + void printPretty(llvm::raw_ostream &OS, PrinterHelper *Helper, + const PrintingPolicy &Policy, unsigned Indentation = 0) const { printPretty(OS, *(ASTContext*)0, Helper, Policy, Indentation); } - void printPretty(llvm::raw_ostream &OS, ASTContext& Context, - PrinterHelper *Helper = 0, - const PrintingPolicy &Policy = PrintingPolicy(), + void printPretty(llvm::raw_ostream &OS, ASTContext &Context, + PrinterHelper *Helper, + const PrintingPolicy &Policy, unsigned Indentation = 0) const; /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def index ab6524663d632..a95a627311860 100644 --- a/include/clang/AST/StmtNodes.def +++ b/include/clang/AST/StmtNodes.def @@ -9,7 +9,7 @@ // // This file defines the AST Node info database. // -//===----------------------------------------------------------------------===// +//===---------------------------------------------------------------------===// #ifndef FIRST_STMT #define FIRST_STMT(CLASS) @@ -123,6 +123,7 @@ EXPR(UnresolvedFunctionNameExpr , Expr) EXPR(UnaryTypeTraitExpr , Expr) EXPR(QualifiedDeclRefExpr , DeclRefExpr) EXPR(UnresolvedDeclRefExpr , Expr) +EXPR(TemplateIdRefExpr , Expr) EXPR(CXXConstructExpr , Expr) EXPR(CXXBindTemporaryExpr , Expr) EXPR(CXXExprWithTemporaries , Expr) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 321b1f204fcfb..a00c0c4ff1c4a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -188,7 +188,8 @@ public: getAsStringInternal(S, Policy); return S; } - void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const; + void getAsStringInternal(std::string &Str, + const PrintingPolicy &Policy) const; void dump(const char *s) const; void dump() const; @@ -375,6 +376,7 @@ public: bool isFunctionProtoType() const { return getAsFunctionProtoType() != 0; } bool isPointerType() const; bool isBlockPointerType() const; + bool isVoidPointerType() const; bool isReferenceType() const; bool isLValueReferenceType() const; bool isRValueReferenceType() const; @@ -585,7 +587,7 @@ public: TypeKind(K) {} Kind getKind() const { return TypeKind; } - const char *getName(bool CPlusPlus) const; + const char *getName(const LangOptions &LO) const; virtual void getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const; diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 65ac0b53027c8..5926229e517c3 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -62,7 +62,6 @@ protected: ASTContext &getContext() const; public: - // virtual MemExtent getExtent(MemRegionManager& mrm) const = 0; virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0; virtual MemRegionManager* getMemRegionManager() const = 0; @@ -73,17 +72,25 @@ public: bool hasStackStorage() const; + bool hasParametersStorage() const; + + bool hasGlobalsStorage() const; + + bool hasGlobalsOrParametersStorage() const; + bool hasHeapStorage() const; bool hasHeapOrStackStorage() const; - virtual void print(llvm::raw_ostream& os) const; + virtual void print(llvm::raw_ostream& os) const; + + void printStdErr() const; Kind getKind() const { return kind; } template<typename RegionTy> const RegionTy* getAs() const; - virtual bool isBoundable() const { return true; } + virtual bool isBoundable() const { return false; } static bool classof(const MemRegion*) { return true; } }; @@ -104,8 +111,6 @@ protected: } public: - //RegionExtent getExtent() const { return UndefinedExtent(); } - void Profile(llvm::FoldingSetNodeID& ID) const; bool isBoundable() const { return false; } @@ -315,6 +320,8 @@ public: return Str->getType(); } + bool isBoundable() const { return false; } + void Profile(llvm::FoldingSetNodeID& ID) const { ProfileRegion(ID, Str, superRegion); } @@ -384,7 +391,9 @@ public: QualType getValueType(ASTContext& C) const { return C.getCanonicalType(CL->getType()); } - + + bool isBoundable() const { return !CL->isFileScope(); } + void Profile(llvm::FoldingSetNodeID& ID) const; void print(llvm::raw_ostream& os) const; @@ -584,15 +593,17 @@ class MemRegionManager { llvm::BumpPtrAllocator& A; llvm::FoldingSet<MemRegion> Regions; - MemSpaceRegion* globals; - MemSpaceRegion* stack; - MemSpaceRegion* heap; - MemSpaceRegion* unknown; - MemSpaceRegion* code; + MemSpaceRegion *globals; + MemSpaceRegion *stack; + MemSpaceRegion *stackArguments; + MemSpaceRegion *heap; + MemSpaceRegion *unknown; + MemSpaceRegion *code; public: MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), globals(0), stack(0), heap(0), unknown(0), code(0) {} + : C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0), + unknown(0), code(0) {} ~MemRegionManager() {} @@ -600,24 +611,28 @@ public: /// getStackRegion - Retrieve the memory region associated with the /// current stack frame. - MemSpaceRegion* getStackRegion(); + MemSpaceRegion *getStackRegion(); + + /// getStackArgumentsRegion - Retrieve the memory region associated with + /// function/method arguments of the current stack frame. + MemSpaceRegion *getStackArgumentsRegion(); /// getGlobalsRegion - Retrieve the memory region associated with /// all global variables. - MemSpaceRegion* getGlobalsRegion(); + MemSpaceRegion *getGlobalsRegion(); /// getHeapRegion - Retrieve the memory region associated with the /// generic "heap". - MemSpaceRegion* getHeapRegion(); + MemSpaceRegion *getHeapRegion(); /// getUnknownRegion - Retrieve the memory region associated with unknown /// memory space. - MemSpaceRegion* getUnknownRegion(); + MemSpaceRegion *getUnknownRegion(); - MemSpaceRegion* getCodeRegion(); + MemSpaceRegion *getCodeRegion(); /// getAllocaRegion - Retrieve a region associated with a call to alloca(). - AllocaRegion* getAllocaRegion(const Expr* Ex, unsigned Cnt); + AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt); /// getCompoundLiteralRegion - Retrieve the region associated with a /// given CompoundLiteral. @@ -785,8 +800,12 @@ template <> struct MemRegionManagerTrait<VarRegion> { typedef MemRegion SuperRegionTy; static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, const VarDecl *d) { - return d->hasLocalStorage() ? MRMgr.getStackRegion() - : MRMgr.getGlobalsRegion(); + if (d->hasLocalStorage()) { + return isa<ParmVarDecl>(d) || isa<ImplicitParamDecl>(d) + ? MRMgr.getStackArgumentsRegion() : MRMgr.getStackRegion(); + } + + return MRMgr.getGlobalsRegion(); } }; diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h index 36137fb117b36..4bc5e27aacf05 100644 --- a/include/clang/Analysis/PathSensitive/SVals.h +++ b/include/clang/Analysis/PathSensitive/SVals.h @@ -110,6 +110,8 @@ public: /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then /// return that expression. Otherwise return NULL. const SymExpr *getAsSymbolicExpression() const; + + const MemRegion *getAsRegion() const; void print(llvm::raw_ostream& OS) const; void printStdErr() const; diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h index de318a0f03e8f..36d1df2150df9 100644 --- a/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/include/clang/Analysis/PathSensitive/ValueManager.h @@ -67,12 +67,17 @@ public: const void* SymbolTag = 0) { return SymMgr.getConjuredSymbol(E, VisitCount, SymbolTag); } - + /// makeZeroVal - Construct an SVal representing '0' for the specified type. SVal makeZeroVal(QualType T); - /// GetRegionValueSymbolVal - make a unique symbol for value of R. - SVal getRegionValueSymbolVal(const MemRegion* R, QualType T = QualType()); + /// getRegionValueSymbolVal - make a unique symbol for value of R. + SVal getRegionValueSymbolVal(const MemRegion *R, QualType T = QualType()); + + SVal getRegionValueSymbolValOrUnknown(const MemRegion *R, QualType T) { + return SymMgr.canSymbolicate(T) ? getRegionValueSymbolVal(R, T) + : UnknownVal(); + } SVal getConjuredSymbolVal(const Expr *E, unsigned Count); SVal getConjuredSymbolVal(const Expr* E, QualType T, unsigned Count); diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 327db00e0b287..a8dbd68df10ff 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -45,6 +45,10 @@ def err_drv_no_linker_llvm_support : Error< "'%0': unable to pass LLVM bit-code files to linker">; def err_drv_clang_unsupported : Error< "the clang compiler does not support '%0'">; +def err_drv_command_failed : Error< + "%0 command failed with exit code %1 (use -v to see invocation)">; +def err_drv_command_signalled : Error< + "%0 command failed due to signal %1 (use -v to see invocation)">; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused when '%2' is present">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4ba1083089e6d..b1a73d05a45fc 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -287,6 +287,8 @@ def err_distant_exception_spec : Error< def err_incomplete_in_exception_spec : Error< "%select{|pointer to |reference to }1incomplete type %0 is not allowed " "in exception specification">; +def err_mismatched_exception_spec : Error< + "exception specification in declaration does not match previous declaration">; // C++ access checking def err_class_redeclared_with_different_access : Error< @@ -398,6 +400,10 @@ def err_init_reference_member_uninitialized : Error< def note_uninit_reference_member : Note< "uninitialized reference member is here">; +// C++0x decltype +def err_cannot_determine_declared_type_of_overloaded_function : Error< + "can't determine the declared type of an overloaded function">; + // C++0x auto def err_auto_variable_cannot_appear_in_own_initializer : Error< "variable %0 declared with 'auto' type cannot appear in its own initializer">; @@ -835,6 +841,12 @@ def note_function_template_spec_here : Note< def note_default_arg_instantiation_here : Note< "in instantiation of default argument for '%0' required here">; +def note_explicit_template_arg_substitution_here : Note< + "while substituting explicitly-specified template arguments into function " + "template %f, here">; +def note_function_template_deduction_instantiation_here : Note< + "while substituting deduced template arguments into function template %0, " + "here">; def note_partial_spec_deduct_instantiation_here : Note< "during template argument deduction for class template partial " "specialization %0, here">; @@ -1070,6 +1082,8 @@ def err_array_star_outside_prototype : Error< "star modifier used outside of function prototype">; def err_illegal_decl_pointer_to_reference : Error< "'%0' declared as a pointer to a reference">; +def err_illegal_decl_mempointer_to_reference : Error< + "'%0' declared as a member pointer to a reference">; def err_illegal_decl_mempointer_to_void : Error< "'%0' declared as a member pointer to void">; def err_illegal_decl_mempointer_in_nonclass : Error< @@ -1207,6 +1221,10 @@ def err_typecheck_sub_ptr_object : Error< "subtraction of pointer %0 requires pointee to be a complete object type">; def err_typecheck_sub_ptr_compatible : Error< "%0 and %1 are not pointers to compatible types">; +def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn< + "ordered comparison between pointer and integer (%0 and %1)">; +def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn< + "ordered comparison of function pointers (%0 and %1)">; def ext_typecheck_comparison_of_pointer_integer : ExtWarn< "comparison between pointer and integer (%0 and %1)">; def ext_typecheck_comparison_of_distinct_pointers : ExtWarn< @@ -1579,6 +1597,12 @@ def err_overload_multiple_match : Error< def err_only_constructors_take_base_inits : Error< "only constructors take base initializers">; +def error_multiple_mem_initialization : Error < + "multiple initializations given for non-static member '%0'">; + +def error_multiple_base_initialization : Error < + "multiple initializations given for base %0">; + def err_mem_init_not_member_or_class : Error< "member initializer %0 does not name a non-static data member or base " "class">; @@ -1588,6 +1612,8 @@ def err_base_init_does_not_name_class : Error< def err_base_init_direct_and_virtual : Error< "base class initializer %0 names both a direct base class and an " "inherited virtual base class">; +def err_not_direct_base_or_virtual : Error< + "type %0 is not a direct or virtual base of '%1'">; def err_in_class_initializer_non_integral_type : Error< "in-class initializer has non-integral, non-enumeration type %0">; diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 543a0fff8e7bf..26688bf567284 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -22,6 +22,7 @@ class LangOptions { public: unsigned Trigraphs : 1; // Trigraphs in source files. unsigned BCPLComment : 1; // BCPL-style '//' comments. + unsigned Bool : 1; // 'bool', 'true', 'false' keywords. unsigned DollarIdents : 1; // '$' allowed in identifiers. unsigned AsmPreprocessor : 1; // Preprocessor in asm mode. unsigned GNUMode : 1; // True in gnu99 mode false in c99 mode (etc) @@ -84,12 +85,16 @@ public: unsigned OpenCL : 1; // OpenCL C99 language extensions. - 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. + 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. 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. /// The user provided name for the "main file", if non-null. This is /// useful in situations where the input file name does not match @@ -100,6 +105,7 @@ public: unsigned InstantiationDepth; // Maximum template instantiation depth. enum GCMode { NonGC, GCOnly, HybridGC }; + enum StackProtectorMode { SSPOff, SSPOn, SSPReq }; enum VisibilityMode { Default, Protected, @@ -107,7 +113,7 @@ public: }; LangOptions() { - Trigraphs = BCPLComment = DollarIdents = AsmPreprocessor = 0; + Trigraphs = BCPLComment = Bool = DollarIdents = AsmPreprocessor = 0; GNUMode = ImplicitInt = Digraphs = 0; HexFloats = 0; GC = ObjC1 = ObjC2 = ObjCNonFragileABI = 0; @@ -116,7 +122,7 @@ public: Exceptions = NeXTRuntime = Freestanding = NoBuiltin = 0; LaxVectorConversions = 1; HeinousExtensions = 0; - AltiVec = OpenCL = 0; + AltiVec = OpenCL = StackProtector = 0; SymbolVisibility = (unsigned) Default; @@ -152,6 +158,13 @@ public: GCMode getGCMode() const { return (GCMode) GC; } void setGCMode(GCMode m) { GC = (unsigned) m; } + StackProtectorMode getStackProtectorMode() const { + return static_cast<StackProtectorMode>(StackProtector); + } + void setStackProtectorMode(StackProtectorMode m) { + StackProtector = static_cast<unsigned>(m); + } + const char *getMainFileName() const { return MainFileName; } void setMainFileName(const char *Name) { MainFileName = Name; } diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index a59c60b002248..537d553bc2d1a 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -76,7 +76,8 @@ public: UnsignedLongLong }; protected: - IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType; + IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, + Int64Type; public: IntType getSizeType() const { return SizeType; } IntType getIntMaxType() const { return IntMaxType; } @@ -86,6 +87,7 @@ public: } IntType getIntPtrType() const { return IntPtrType; } IntType getWCharType() const { return WCharType; } + IntType getInt64Type() const { return Int64Type; } /// getPointerWidth - Return the width of pointers on this target, for the /// specified address space. diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index ed0270acd0ddb..e711996cf26da 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -224,7 +224,7 @@ KEYWORD(__func__ , KEYALL) // C++ 2.11p1: Keywords. KEYWORD(asm , KEYCXX|KEYGNU) -KEYWORD(bool , KEYCXX|BOOLSUPPORT) +KEYWORD(bool , BOOLSUPPORT) KEYWORD(catch , KEYCXX) KEYWORD(class , KEYCXX) KEYWORD(const_cast , KEYCXX) @@ -232,7 +232,7 @@ KEYWORD(delete , KEYCXX) KEYWORD(dynamic_cast , KEYCXX) KEYWORD(explicit , KEYCXX) KEYWORD(export , KEYCXX) -KEYWORD(false , KEYCXX|BOOLSUPPORT) +KEYWORD(false , BOOLSUPPORT) KEYWORD(friend , KEYCXX) KEYWORD(mutable , KEYCXX) KEYWORD(namespace , KEYCXX) @@ -246,7 +246,7 @@ KEYWORD(static_cast , KEYCXX) KEYWORD(template , KEYCXX) KEYWORD(this , KEYCXX) KEYWORD(throw , KEYCXX) -KEYWORD(true , KEYCXX|BOOLSUPPORT) +KEYWORD(true , BOOLSUPPORT) KEYWORD(try , KEYCXX) KEYWORD(typename , KEYCXX) KEYWORD(typeid , KEYCXX) diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index 5812da1b562e2..12b74d51473e2 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -18,6 +18,7 @@ #include <string> namespace llvm { + class LLVMContext; class Module; } @@ -34,7 +35,8 @@ namespace clang { CodeGenerator *CreateLLVMCodeGen(Diagnostic &Diags, const std::string &ModuleName, - const CompileOptions &CO); + const CompileOptions &CO, + llvm::LLVMContext& C); } #endif diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index b9bf671db2bde..ceef189f7b7ef 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -75,6 +75,8 @@ protected: public: virtual ~Action(); + const char *getClassName() const { return Action::getClassName(getKind()); } + ActionClass getKind() const { return Kind; } types::ID getType() const { return Type; } diff --git a/include/clang/Driver/ArgList.h b/include/clang/Driver/ArgList.h index 84e0329a375e0..a9c890b0b8994 100644 --- a/include/clang/Driver/ArgList.h +++ b/include/clang/Driver/ArgList.h @@ -83,6 +83,8 @@ namespace driver { /// \arg Claim Whether the argument should be claimed, if it exists. Arg *getLastArg(options::ID Id, bool Claim=true) const; Arg *getLastArg(options::ID Id0, options::ID Id1, bool Claim=true) const; + Arg *getLastArg(options::ID Id0, options::ID Id1, options::ID Id2, + bool Claim=true) const; /// getArgString - Return the input argument string at \arg Index. virtual const char *getArgString(unsigned Index) const = 0; diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 4985f30ad553d..6414ef13692b0 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -32,10 +32,10 @@ namespace driver { /// invocation. class Compilation { /// The driver we were created by. - Driver &TheDriver; + const Driver &TheDriver; /// The default tool chain. - ToolChain &DefaultToolChain; + const ToolChain &DefaultToolChain; /// The original (untranslated) input argument list. InputArgList *Args; @@ -56,7 +56,8 @@ class Compilation { ArgStringList ResultFiles; public: - Compilation(Driver &D, ToolChain &DefaultToolChain, InputArgList *Args); + Compilation(const Driver &D, const ToolChain &DefaultToolChain, + InputArgList *Args); ~Compilation(); const Driver &getDriver() const { return TheDriver; } @@ -69,6 +70,11 @@ public: const ActionList &getActions() const { return Actions; } JobList &getJobs() { return Jobs; } + const JobList &getJobs() const { return Jobs; } + + const ArgStringList &getTempFiles() const { return TempFiles; } + + const ArgStringList &getResultFiles() const { return ResultFiles; } /// getArgsForToolChain - Return the derived argument list for the /// tool chain \arg TC (or the default tool chain, if TC is not @@ -89,11 +95,6 @@ public: return Name; } - /// Execute - Execute the compilation jobs and return an - /// appropriate exit code. - int Execute() const; - -private: /// CleanupFileList - Remove the files in the given list. /// /// \param IssueErrors - Report failures as errors. @@ -103,22 +104,26 @@ private: /// PrintJob - Print one job in -### format. /// - /// OS - The stream to print on. - /// J - The job to print. - /// Terminator - A string to print at the end of the line. - /// Quote - Should separate arguments be quoted. + /// \param OS - The stream to print on. + /// \param J - The job to print. + /// \param Terminator - A string to print at the end of the line. + /// \param Quote - Should separate arguments be quoted. void PrintJob(llvm::raw_ostream &OS, const Job &J, const char *Terminator, bool Quote) const; /// ExecuteCommand - Execute an actual command. /// + /// \param FailingCommand - For non-zero results, this will be set to the + /// Command which failed, if any. /// \return The result code of the subprocess. - int ExecuteCommand(const Command &C) const; + int ExecuteCommand(const Command &C, const Command *&FailingCommand) const; /// ExecuteJob - Execute a single job. /// + /// \param FailingCommand - For non-zero results, this will be set to the + /// Command which failed. /// \return The accumulated result code of the job. - int ExecuteJob(const Job &J) const; + int ExecuteJob(const Job &J, const Command *&FailingCommand) const; }; } // end namespace driver diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index 66e3b97875940..c0def2bcca29f 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -161,6 +161,14 @@ public: /// \arg C - The compilation that is being built. void BuildJobs(Compilation &C) const; + /// ExecuteCompilation - Execute the compilation according to the command line + /// arguments and return an appropriate exit code. + /// + /// This routine handles additional processing that must be done in addition + /// to just running the subprocesses, for example reporting errors, removing + /// temporary files, etc. + int ExecuteCompilation(const Compilation &C) const; + /// @} /// @name Helper Methods /// @{ diff --git a/include/clang/Driver/HostInfo.h b/include/clang/Driver/HostInfo.h index 3485f5fbfd76c..b5e80b0c3bfe6 100644 --- a/include/clang/Driver/HostInfo.h +++ b/include/clang/Driver/HostInfo.h @@ -69,6 +69,8 @@ public: const HostInfo *createDarwinHostInfo(const Driver &D, const llvm::Triple& Triple); +const HostInfo *createOpenBSDHostInfo(const Driver &D, + const llvm::Triple& Triple); const HostInfo *createFreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple); const HostInfo *createDragonFlyHostInfo(const Driver &D, diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index f60f5146414c3..a23babdbb31a5 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -52,6 +52,9 @@ public: /// Command - An executable path/name and argument vector to /// execute. class Command : public Job { + /// Source - The action which caused the creation of this job. + const Action &Source; + /// The executable to run. const char *Executable; @@ -60,9 +63,14 @@ class Command : public Job { ArgStringList Arguments; public: - Command(const char *_Executable, const ArgStringList &_Arguments); + Command(const Action &_Source, const char *_Executable, + const ArgStringList &_Arguments); + + /// getSource - Return the Action which caused the creation of this job. + const Action &getSource() const { return Source; } const char *getExecutable() const { return Executable; } + const ArgStringList &getArguments() const { return Arguments; } static bool classof(const Job *J) { diff --git a/include/clang/Driver/Options.def b/include/clang/Driver/Options.def index abd07a92b1a26..af108a85ebdd9 100644 --- a/include/clang/Driver/Options.def +++ b/include/clang/Driver/Options.def @@ -420,7 +420,7 @@ OPTION("-fno-math-errno", fno_math_errno, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-pascal-strings", fno_pascal_strings, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-show-column", fno_show_column, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-show-source-location", fno_show_source_location, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fno-stack-protector", fno_stack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) +OPTION("-fno-stack-protector", fno_stack_protector, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-strict-aliasing", fno_strict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-unit-at-a-time", fno_unit_at_a_time, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fno-unwind-tables", fno_unwind_tables, Flag, f_Group, INVALID, "", 0, 0, 0) @@ -450,7 +450,8 @@ OPTION("-framework", framework, Separate, INVALID, INVALID, "l", 0, 0, 0) OPTION("-fshow-source-location", fshow_source_location, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fsigned-bitfields", fsigned_bitfields, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fsigned-char", fsigned_char, Flag, f_Group, INVALID, "", 0, 0, 0) -OPTION("-fstack-protector", fstack_protector, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) +OPTION("-fstack-protector-all", fstack_protector_all, Flag, f_Group, INVALID, "", 0, 0, 0) +OPTION("-fstack-protector", fstack_protector, Flag, f_Group, INVALID, "", 0, 0, 0) OPTION("-fstrict-aliasing", fstrict_aliasing, Flag, clang_ignored_f_Group, INVALID, "", 0, 0, 0) OPTION("-fsyntax-only", fsyntax_only, Flag, INVALID, INVALID, "d", 0, 0, 0) OPTION("-ftemplate-depth-", ftemplate_depth_, Joined, f_Group, INVALID, "", 0, 0, 0) diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 04365d7c78d84..be45202625586 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -20,6 +20,7 @@ namespace llvm { class Module; + class LLVMContext; namespace sys { class Path; } } namespace clang { @@ -79,7 +80,8 @@ ASTConsumer *CreateBackendConsumer(BackendAction Action, const LangOptions &Features, const CompileOptions &CompileOpts, const std::string &ModuleID, - llvm::raw_ostream *OS); + llvm::raw_ostream *OS, + llvm::LLVMContext& C); // HTML printer: uses the rewriter to convert source code to HTML with // syntax highlighting suitable for viewing in a web-browser. diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 63222725d529e..80aa248a78e6f 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -218,7 +218,11 @@ namespace clang { /// \brief Record code for the original file that was used to /// generate the precompiled header. - ORIGINAL_FILE_NAME = 20 + ORIGINAL_FILE_NAME = 20, + + /// \brief Record code for the sorted array of source ranges where + /// comments were encountered in the source code. + COMMENT_RANGES = 21 }; /// \brief Record types used within a source manager block. diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index b3ed364343124..8291f4697a8ea 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -279,6 +279,12 @@ private: /// been loaded. llvm::SmallVector<Selector, 16> SelectorsLoaded; + /// \brief A sorted array of source ranges containing comments. + SourceRange *Comments; + + /// \brief The number of source ranges in the Comments array. + unsigned NumComments; + /// \brief The set of external definitions stored in the the PCH /// file. llvm::SmallVector<uint64_t, 16> ExternalDefinitions; @@ -452,6 +458,14 @@ public: /// build prior to including the precompiled header. const std::string &getSuggestedPredefines() { return SuggestedPredefines; } + /// \brief Reads the source ranges that correspond to comments from + /// an external AST source. + /// + /// \param Comments the contents of this vector will be + /// replaced with the sorted set of source ranges corresponding to + /// comments in the source code. + virtual void ReadComments(std::vector<SourceRange> &Comments); + /// \brief Resolve a type ID into a type, potentially building a new /// type. virtual QualType GetType(pch::TypeID ID); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index 5cb939547f2c4..c663442e64d8c 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -166,6 +166,7 @@ private: void WriteSourceManagerBlock(SourceManager &SourceMgr, const Preprocessor &PP); void WritePreprocessor(const Preprocessor &PP); + void WriteComments(ASTContext &Context); void WriteType(const Type *T); void WriteTypesBlock(ASTContext &Context); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index f229881bfc44a..6d5ed72455b90 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -26,6 +26,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Support/Allocator.h" +#include <vector> namespace clang { @@ -35,6 +36,7 @@ class FileEntry; class HeaderSearch; class PragmaNamespace; class PragmaHandler; +class CommentHandler; class ScratchBuffer; class TargetInfo; class PPCallbacks; @@ -109,6 +111,10 @@ class Preprocessor { /// with this preprocessor. PragmaNamespace *PragmaHandlers; + /// \brief Tracks all of the comment handlers that the client registered + /// with this preprocessor. + std::vector<CommentHandler *> CommentHandlers; + /// CurLexer - This is the current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. @@ -301,6 +307,14 @@ public: /// to remove a handler that has not been registered. void RemovePragmaHandler(const char *Namespace, PragmaHandler *Handler); + /// \brief Add the specified comment handler to the preprocessor. + void AddCommentHandler(CommentHandler *Handler); + + /// \brief Remove the specified comment handler. + /// + /// It is an error to remove a handler that has not been registered. + void RemoveCommentHandler(CommentHandler *Handler); + /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void EnterMainSourceFile(); @@ -791,6 +805,7 @@ public: void HandlePragmaSystemHeader(Token &SysHeaderTok); void HandlePragmaDependency(Token &DependencyTok); void HandlePragmaComment(Token &CommentTok); + void HandleComment(SourceRange Comment); }; /// PreprocessorFactory - A generic factory interface for lazily creating @@ -801,6 +816,15 @@ public: virtual Preprocessor* CreatePreprocessor() = 0; }; +/// \brief Abstract base class that describes a handler that will receive +/// source ranges for each of the comments encountered in the source file. +class CommentHandler { +public: + virtual ~CommentHandler(); + + virtual void HandleComment(Preprocessor &PP, SourceRange Comment) = 0; +}; + } // end namespace clang #endif diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index bfb74748c5f12..d969562977ea3 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -152,6 +152,10 @@ public: /// an empty string if not. This is used for pretty crash reporting. virtual std::string getDeclName(DeclPtrTy D) { return ""; } + /// \brief Invoked for each comment in the source code, providing the source + /// range that contains the comment. + virtual void ActOnComment(SourceRange Comment) { } + //===--------------------------------------------------------------------===// // Declaration Tracking Callbacks. //===--------------------------------------------------------------------===// @@ -1203,7 +1207,9 @@ public: virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl, Scope *S, + const CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, + TypeTy *TemplateTypeTy, SourceLocation IdLoc, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, @@ -1379,6 +1385,24 @@ public: return TypeResult(); }; + /// \brief Form a reference to a template-id (that will refer to a function) + /// from a template and a list of template arguments. + /// + /// This action forms an expression that references the given template-id, + /// possibly checking well-formedness of the template arguments. It does not + /// imply the declaration of any entity. + /// + /// \param Template A template whose specialization results in a + /// function or a dependent template. + virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc) { + return ExprError(); + } + /// \brief Form a dependent template name. /// /// This action forms a dependent template name given the template diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h index 59517930de957..987edfa96dd1b 100644 --- a/include/clang/Parse/Ownership.h +++ b/include/clang/Parse/Ownership.h @@ -574,6 +574,19 @@ namespace clang { #if !defined(DISABLE_SMART_POINTERS) friend class moving::ASTMultiMover<Destroyer>; +#if defined(_MSC_VER) + // Last tested with Visual Studio 2008. + // Visual C++ appears to have a bug where it does not recognise + // the return value from ASTMultiMover<Destroyer>::opeator-> as + // being a pointer to ASTMultiPtr. However, the diagnostics + // suggest it has the right name, simply that the pointer type + // is not convertible to itself. + // Either way, a classic C-style hard cast resolves any issue. + static ASTMultiPtr* hack(moving::ASTMultiMover<Destroyer> & source) { + return (ASTMultiPtr*)source.operator->(); + } +#endif + ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT // Reference member prevents copy assignment. @@ -594,7 +607,13 @@ namespace clang { : Actions(actions), Nodes(nodes), Count(count) {} /// Move constructor ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover) +#if defined(_MSC_VER) + // Apply the visual C++ hack supplied above. + // Last tested with Visual Studio 2008. + : Actions(hack(mover)->Actions), Nodes(hack(mover)->Nodes), Count(hack(mover)->Count) { +#else : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) { +#endif mover.release(); } #else diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index e5f62ec683e37..e2380542ae6f6 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -82,7 +82,8 @@ class Parser { llvm::OwningPtr<PragmaHandler> PackHandler; llvm::OwningPtr<PragmaHandler> UnusedHandler; llvm::OwningPtr<PragmaHandler> WeakHandler; - + llvm::OwningPtr<clang::CommentHandler> CommentHandler; + /// Whether the '>' token acts as an operator or not. This will be /// true except when we are parsing an expression within a C++ /// template argument list, where the '>' closes the template |