diff options
author | Ed Schouten <ed@FreeBSD.org> | 2009-07-04 13:58:54 +0000 |
---|---|---|
committer | Ed Schouten <ed@FreeBSD.org> | 2009-07-04 13:58:54 +0000 |
commit | 5362a71c02e7d448a8ce98cf00c47e353fba5d04 (patch) | |
tree | 8ddfe382e1c6d590dc240e76f7cd45cea5c78e24 | |
parent | 4ebdf5c4f587daef4e0be499802eac3a7a49bf2f (diff) |
Import Clang r74788.vendor/clang/clang-r74788
Notes
Notes:
svn path=/vendor/clang/dist/; revision=195341
svn path=/vendor/clang/clang-r74788/; revision=195343; tag=vendor/clang/clang-r74788
184 files changed, 5851 insertions, 3551 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index aa01b7fdf06f..041a0f33ad4d 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 7a9ee01d4f62..e60e58e1ac23 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 3de01f3baeb5..69a52869d818 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 c959b05473fe..0bce2f84c7ba 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 a2fe24e83105..c523e96e03b0 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 3943ddc19638..2fcdaa3e2959 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 aad19a63ef0f..5d0fe158e054 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 2ed91124758d..6a1046e6d03f 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 f9f5da129142..7d76a49d1267 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 4219bd507a90..6f862a55d4ba 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 4eea1031f063..b304cc8e8a04 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 385602b1fb9c..6ad3a6bcc276 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 a8688f62e2d9..0a64dafd4e2c 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 ab6524663d63..a95a62731186 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 321b1f204fcf..a00c0c4ff1c4 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 65ac0b53027c..5926229e517c 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 36137fb117b3..4bc5e27aacf0 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 de318a0f03e8..36d1df2150df 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 327db00e0b28..a8dbd68df10f 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 4ba1083089e6..b1a73d05a45f 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 543a0fff8e7b..26688bf56728 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 a59c60b00224..537d553bc2d1 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 ed0270acd0dd..e711996cf26d 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 5812da1b562e..12b74d51473e 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 b9bf671db2bd..ceef189f7b7e 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 84e0329a375e..a9c890b0b899 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 4985f30ad553..6414ef13692b 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 66e3b9787594..c0def2bcca29 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 3485f5fbfd76..b5e80b0c3bfe 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 f60f5146414c..a23babdbb31a 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 abd07a92b1a2..af108a85ebdd 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 04365d7c78d8..be4520262558 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 63222725d529..80aa248a78e6 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 b3ed36434312..8291f4697a8e 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 5cb939547f2c..c663442e64d8 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 f229881bfc44..6d5ed72455b9 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 bfb74748c5f1..d969562977ea 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 59517930de95..987edfa96dd1 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 e5f62ec683e3..e2380542ae6f 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 diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 12f75ae863a2..2877cc3b7fe7 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -37,12 +37,12 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM, bool FreeMem, unsigned size_reserve) : GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0), ObjCFastEnumerationStateTypeDecl(0), SourceMgr(SM), LangOpts(LOpts), - FreeMemory(FreeMem), Target(t), Idents(idents), Selectors(sels), - BuiltinInfo(builtins), ExternalSource(0) { + LoadedExternalComments(false), FreeMemory(FreeMem), Target(t), + Idents(idents), Selectors(sels), + BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) { if (size_reserve > 0) Types.reserve(size_reserve); InitBuiltinTypes(); TUDecl = TranslationUnitDecl::Create(*this); - PrintingPolicy.CPlusPlus = LangOpts.CPlusPlus; } ASTContext::~ASTContext() { @@ -203,6 +203,207 @@ void ASTContext::InitBuiltinTypes() { InitBuiltinType(NullPtrTy, BuiltinType::NullPtr); } +namespace { + class BeforeInTranslationUnit + : std::binary_function<SourceRange, SourceRange, bool> { + SourceManager *SourceMgr; + + public: + explicit BeforeInTranslationUnit(SourceManager *SM) : SourceMgr(SM) { } + + bool operator()(SourceRange X, SourceRange Y) { + return SourceMgr->isBeforeInTranslationUnit(X.getBegin(), Y.getBegin()); + } + }; +} + +/// \brief Determine whether the given comment is a Doxygen-style comment. +/// +/// \param Start the start of the comment text. +/// +/// \param End the end of the comment text. +/// +/// \param Member whether we want to check whether this is a member comment +/// (which requires a < after the Doxygen-comment delimiter). Otherwise, +/// we only return true when we find a non-member comment. +static bool +isDoxygenComment(SourceManager &SourceMgr, SourceRange Comment, + bool Member = false) { + const char *BufferStart + = SourceMgr.getBufferData(SourceMgr.getFileID(Comment.getBegin())).first; + const char *Start = BufferStart + SourceMgr.getFileOffset(Comment.getBegin()); + const char* End = BufferStart + SourceMgr.getFileOffset(Comment.getEnd()); + + if (End - Start < 4) + return false; + + assert(Start[0] == '/' && "Not a comment?"); + if (Start[1] == '*' && !(Start[2] == '!' || Start[2] == '*')) + return false; + if (Start[1] == '/' && !(Start[2] == '!' || Start[2] == '/')) + return false; + + return (Start[3] == '<') == Member; +} + +/// \brief Retrieve the comment associated with the given declaration, if +/// it has one. +const char *ASTContext::getCommentForDecl(const Decl *D) { + if (!D) + return 0; + + // Check whether we have cached a comment string for this declaration + // already. + llvm::DenseMap<const Decl *, std::string>::iterator Pos + = DeclComments.find(D); + if (Pos != DeclComments.end()) + return Pos->second.c_str(); + + // If we have an external AST source and have not yet loaded comments from + // that source, do so now. + if (ExternalSource && !LoadedExternalComments) { + std::vector<SourceRange> LoadedComments; + ExternalSource->ReadComments(LoadedComments); + + if (!LoadedComments.empty()) + Comments.insert(Comments.begin(), LoadedComments.begin(), + LoadedComments.end()); + + LoadedExternalComments = true; + } + + // If there are no comments anywhere, we won't find anything. + if (Comments.empty()) + return 0; + + // If the declaration doesn't map directly to a location in a file, we + // can't find the comment. + SourceLocation DeclStartLoc = D->getLocStart(); + if (DeclStartLoc.isInvalid() || !DeclStartLoc.isFileID()) + return 0; + + // Find the comment that occurs just before this declaration. + std::vector<SourceRange>::iterator LastComment + = std::lower_bound(Comments.begin(), Comments.end(), + SourceRange(DeclStartLoc), + BeforeInTranslationUnit(&SourceMgr)); + + // Decompose the location for the start of the declaration and find the + // beginning of the file buffer. + std::pair<FileID, unsigned> DeclStartDecomp + = SourceMgr.getDecomposedLoc(DeclStartLoc); + const char *FileBufferStart + = SourceMgr.getBufferData(DeclStartDecomp.first).first; + + // First check whether we have a comment for a member. + if (LastComment != Comments.end() && + !isa<TagDecl>(D) && !isa<NamespaceDecl>(D) && + isDoxygenComment(SourceMgr, *LastComment, true)) { + std::pair<FileID, unsigned> LastCommentEndDecomp + = SourceMgr.getDecomposedLoc(LastComment->getEnd()); + if (DeclStartDecomp.first == LastCommentEndDecomp.first && + SourceMgr.getLineNumber(DeclStartDecomp.first, DeclStartDecomp.second) + == SourceMgr.getLineNumber(LastCommentEndDecomp.first, + LastCommentEndDecomp.second)) { + // The Doxygen member comment comes after the declaration starts and + // is on the same line and in the same file as the declaration. This + // is the comment we want. + std::string &Result = DeclComments[D]; + Result.append(FileBufferStart + + SourceMgr.getFileOffset(LastComment->getBegin()), + FileBufferStart + LastCommentEndDecomp.second + 1); + return Result.c_str(); + } + } + + if (LastComment == Comments.begin()) + return 0; + --LastComment; + + // Decompose the end of the comment. + std::pair<FileID, unsigned> LastCommentEndDecomp + = SourceMgr.getDecomposedLoc(LastComment->getEnd()); + + // If the comment and the declaration aren't in the same file, then they + // aren't related. + if (DeclStartDecomp.first != LastCommentEndDecomp.first) + return 0; + + // Check that we actually have a Doxygen comment. + if (!isDoxygenComment(SourceMgr, *LastComment)) + return 0; + + // Compute the starting line for the declaration and for the end of the + // comment (this is expensive). + unsigned DeclStartLine + = SourceMgr.getLineNumber(DeclStartDecomp.first, DeclStartDecomp.second); + unsigned CommentEndLine + = SourceMgr.getLineNumber(LastCommentEndDecomp.first, + LastCommentEndDecomp.second); + + // If the comment does not end on the line prior to the declaration, then + // the comment is not associated with the declaration at all. + if (CommentEndLine + 1 != DeclStartLine) + return 0; + + // We have a comment, but there may be more comments on the previous lines. + // Keep looking so long as the comments are still Doxygen comments and are + // still adjacent. + unsigned ExpectedLine + = SourceMgr.getSpellingLineNumber(LastComment->getBegin()) - 1; + std::vector<SourceRange>::iterator FirstComment = LastComment; + while (FirstComment != Comments.begin()) { + // Look at the previous comment + --FirstComment; + std::pair<FileID, unsigned> Decomp + = SourceMgr.getDecomposedLoc(FirstComment->getEnd()); + + // If this previous comment is in a different file, we're done. + if (Decomp.first != DeclStartDecomp.first) { + ++FirstComment; + break; + } + + // If this comment is not a Doxygen comment, we're done. + if (!isDoxygenComment(SourceMgr, *FirstComment)) { + ++FirstComment; + break; + } + + // If the line number is not what we expected, we're done. + unsigned Line = SourceMgr.getLineNumber(Decomp.first, Decomp.second); + if (Line != ExpectedLine) { + ++FirstComment; + break; + } + + // Set the next expected line number. + ExpectedLine + = SourceMgr.getSpellingLineNumber(FirstComment->getBegin()) - 1; + } + + // The iterator range [FirstComment, LastComment] contains all of the + // BCPL comments that, together, are associated with this declaration. + // Form a single comment block string for this declaration that concatenates + // all of these comments. + std::string &Result = DeclComments[D]; + while (FirstComment != LastComment) { + std::pair<FileID, unsigned> DecompStart + = SourceMgr.getDecomposedLoc(FirstComment->getBegin()); + std::pair<FileID, unsigned> DecompEnd + = SourceMgr.getDecomposedLoc(FirstComment->getEnd()); + Result.append(FileBufferStart + DecompStart.second, + FileBufferStart + DecompEnd.second + 1); + ++FirstComment; + } + + // Append the last comment line. + Result.append(FileBufferStart + + SourceMgr.getFileOffset(LastComment->getBegin()), + FileBufferStart + LastCommentEndDecomp.second + 1); + return Result.c_str(); +} + //===----------------------------------------------------------------------===// // Type Sizing and Analysis //===----------------------------------------------------------------------===// @@ -226,7 +427,7 @@ const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { unsigned ASTContext::getDeclAlignInBytes(const Decl *D) { unsigned Align = Target.getCharWidth(); - if (const AlignedAttr* AA = D->getAttr<AlignedAttr>(*this)) + if (const AlignedAttr* AA = D->getAttr<AlignedAttr>()) Align = std::max(Align, AA->getAlignment()); if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { @@ -449,7 +650,7 @@ ASTContext::getTypeInfo(const Type *T) { case Type::Typedef: { const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); - if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>(*this)) { + if (const AlignedAttr *Aligned = Typedef->getAttr<AlignedAttr>()) { Align = Aligned->getAlignment(); Width = getTypeSize(Typedef->getUnderlyingType().getTypePtr()); } else @@ -513,7 +714,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo, // FIXME: Should this override struct packing? Probably we want to // take the minimum? - if (const PackedAttr *PA = FD->getAttr<PackedAttr>(Context)) + if (const PackedAttr *PA = FD->getAttr<PackedAttr>()) FieldPacking = PA->getAlignment(); if (const Expr *BitWidthExpr = FD->getBitWidth()) { @@ -533,7 +734,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo, FieldAlign = FieldInfo.second; if (FieldPacking) FieldAlign = std::min(FieldAlign, FieldPacking); - if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context)) + if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>()) FieldAlign = std::max(FieldAlign, AA->getAlignment()); // Check if we need to add padding to give the field the correct @@ -573,7 +774,7 @@ void ASTRecordLayout::LayoutField(const FieldDecl *FD, unsigned FieldNo, // is smaller than the specified packing? if (FieldPacking) FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking)); - if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>(Context)) + if (const AlignedAttr *AA = FD->getAttr<AlignedAttr>()) FieldAlign = std::max(FieldAlign, AA->getAlignment()); // Round up the current record size to the field's alignment boundary. @@ -631,8 +832,8 @@ void ASTContext::ShallowCollectObjCIvars(const ObjCInterfaceDecl *OI, void ASTContext::CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { - for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(*this), - E = PD->prop_end(*this); I != E; ++I) + for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(), + E = PD->prop_end(); I != E; ++I) if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) Ivars.push_back(Ivar); @@ -647,8 +848,8 @@ void ASTContext::CollectProtocolSynthesizedIvars(const ObjCProtocolDecl *PD, /// void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars) { - for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(*this), - E = OI->prop_end(*this); I != E; ++I) { + for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(), + E = OI->prop_end(); I != E; ++I) { if (ObjCIvarDecl *Ivar = (*I)->getPropertyIvarDecl()) Ivars.push_back(Ivar); } @@ -663,8 +864,8 @@ void ASTContext::CollectSynthesizedIvars(const ObjCInterfaceDecl *OI, unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) { unsigned count = 0; - for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(*this), - E = PD->prop_end(*this); I != E; ++I) + for (ObjCContainerDecl::prop_iterator I = PD->prop_begin(), + E = PD->prop_end(); I != E; ++I) if ((*I)->getPropertyIvarDecl()) ++count; @@ -678,8 +879,8 @@ unsigned ASTContext::CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD) { unsigned ASTContext::CountSynthesizedIvars(const ObjCInterfaceDecl *OI) { unsigned count = 0; - for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(*this), - E = OI->prop_end(*this); I != E; ++I) { + for (ObjCInterfaceDecl::prop_iterator I = OI->prop_begin(), + E = OI->prop_end(); I != E; ++I) { if ((*I)->getPropertyIvarDecl()) ++count; } @@ -739,10 +940,10 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, } unsigned StructPacking = 0; - if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this)) + if (const PackedAttr *PA = D->getAttr<PackedAttr>()) StructPacking = PA->getAlignment(); - if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this)) + if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) NewEntry->SetAlignment(std::max(NewEntry->getAlignment(), AA->getAlignment())); @@ -786,23 +987,22 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) { Entry = NewEntry; // FIXME: Avoid linear walk through the fields, if possible. - NewEntry->InitializeLayout(std::distance(D->field_begin(*this), - D->field_end(*this))); + NewEntry->InitializeLayout(std::distance(D->field_begin(), D->field_end())); bool IsUnion = D->isUnion(); unsigned StructPacking = 0; - if (const PackedAttr *PA = D->getAttr<PackedAttr>(*this)) + if (const PackedAttr *PA = D->getAttr<PackedAttr>()) StructPacking = PA->getAlignment(); - if (const AlignedAttr *AA = D->getAttr<AlignedAttr>(*this)) + if (const AlignedAttr *AA = D->getAttr<AlignedAttr>()) NewEntry->SetAlignment(std::max(NewEntry->getAlignment(), AA->getAlignment())); // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. unsigned FieldIdx = 0; - for (RecordDecl::field_iterator Field = D->field_begin(*this), - FieldEnd = D->field_end(*this); + for (RecordDecl::field_iterator Field = D->field_begin(), + FieldEnd = D->field_end(); Field != FieldEnd; (void)++Field, ++FieldIdx) NewEntry->LayoutField(*Field, FieldIdx, IsUnion, StructPacking, *this); @@ -1636,13 +1836,6 @@ QualType ASTContext::getObjCQualifiedInterfaceType(ObjCInterfaceDecl *Decl, return QualType(QType, 0); } -/// getObjCQualifiedIdType - Return an ObjCQualifiedIdType for the 'id' decl -/// and the conforming protocol list. -QualType ASTContext::getObjCQualifiedIdType(ObjCProtocolDecl **Protocols, - unsigned NumProtocols) { - return getObjCObjectPointerType(0, Protocols, NumProtocols); -} - /// getTypeOfExprType - Unlike many "get<Type>" functions, we can't unique /// TypeOfExprType AST's (since expression's are never shared). For example, /// multiple declarations that refer to "typeof(x)" all contain different @@ -1813,6 +2006,12 @@ Decl *ASTContext::getCanonicalDecl(Decl *D) { return const_cast<FunctionDecl *>(Function); } + if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) { + while (FunTmpl->getPreviousDeclaration()) + FunTmpl = FunTmpl->getPreviousDeclaration(); + return FunTmpl; + } + if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { while (Var->getPreviousDeclaration()) Var = Var->getPreviousDeclaration(); @@ -2143,7 +2342,7 @@ QualType ASTContext::getCFConstantStringType() { SourceLocation(), 0, FieldTypes[i], /*BitWidth=*/0, /*Mutable=*/false); - CFConstantStringTypeDecl->addDecl(*this, Field); + CFConstantStringTypeDecl->addDecl(Field); } CFConstantStringTypeDecl->completeDefinition(*this); @@ -2179,7 +2378,7 @@ QualType ASTContext::getObjCFastEnumerationStateType() SourceLocation(), 0, FieldTypes[i], /*BitWidth=*/0, /*Mutable=*/false); - ObjCFastEnumerationStateTypeDecl->addDecl(*this, Field); + ObjCFastEnumerationStateTypeDecl->addDecl(Field); } ObjCFastEnumerationStateTypeDecl->completeDefinition(*this); @@ -2306,7 +2505,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, if (const ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(Container)) { for (ObjCCategoryImplDecl::propimpl_iterator - i = CID->propimpl_begin(*this), e = CID->propimpl_end(*this); + i = CID->propimpl_begin(), e = CID->propimpl_end(); i != e; ++i) { ObjCPropertyImplDecl *PID = *i; if (PID->getPropertyDecl() == PD) { @@ -2320,7 +2519,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, } else { const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container); for (ObjCCategoryImplDecl::propimpl_iterator - i = OID->propimpl_begin(*this), e = OID->propimpl_end(*this); + i = OID->propimpl_begin(), e = OID->propimpl_end(); i != e; ++i) { ObjCPropertyImplDecl *PID = *i; if (PID->getPropertyDecl() == PD) { @@ -2611,8 +2810,8 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } if (ExpandStructures) { S += '='; - for (RecordDecl::field_iterator Field = RDecl->field_begin(*this), - FieldEnd = RDecl->field_end(*this); + for (RecordDecl::field_iterator Field = RDecl->field_begin(), + FieldEnd = RDecl->field_end(); Field != FieldEnd; ++Field) { if (FD) { S += '"'; @@ -2834,7 +3033,7 @@ QualType ASTContext::getFromTargetType(unsigned Type) const { bool ASTContext::isObjCNSObjectType(QualType Ty) const { if (TypedefType *TDT = dyn_cast<TypedefType>(Ty)) { if (TypedefDecl *TD = TDT->getDecl()) - if (TD->getAttr<ObjCNSObjectAttr>(*const_cast<ASTContext*>(this))) + if (TD->getAttr<ObjCNSObjectAttr>()) return true; } return false; @@ -3578,7 +3777,7 @@ static QualType DecodeTypeFromStr(const char *&Str, ASTContext &Context, case 'P': { IdentifierInfo *II = &Context.Idents.get("FILE"); DeclContext::lookup_result Lookup - = Context.getTranslationUnitDecl()->lookup(Context, II); + = Context.getTranslationUnitDecl()->lookup(II); if (Lookup.first != Lookup.second && isa<TypeDecl>(*Lookup.first)) { Type = Context.getTypeDeclType(cast<TypeDecl>(*Lookup.first)); break; diff --git a/lib/AST/CFG.cpp b/lib/AST/CFG.cpp index d7a830726fa4..69852f5fea57 100644 --- a/lib/AST/CFG.cpp +++ b/lib/AST/CFG.cpp @@ -556,7 +556,7 @@ CFGBlock* CFGBuilder::VisitNullStmt(NullStmt* Statement) { CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) { - CFGBlock* LastBlock = NULL; + CFGBlock* LastBlock = Block; for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend(); I != E; ++I ) { @@ -1484,10 +1484,11 @@ class VISIBILITY_HIDDEN StmtPrinterHelper : public PrinterHelper { StmtMapTy StmtMap; signed CurrentBlock; unsigned CurrentStmt; - + const LangOptions &LangOpts; public: - StmtPrinterHelper(const CFG* cfg) : CurrentBlock(0), CurrentStmt(0) { + StmtPrinterHelper(const CFG* cfg, const LangOptions &LO) + : CurrentBlock(0), CurrentStmt(0), LangOpts(LO) { for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) { unsigned j = 1; for (CFGBlock::const_iterator BI = I->begin(), BEnd = I->end() ; @@ -1498,6 +1499,7 @@ public: virtual ~StmtPrinterHelper() {} + const LangOptions &getLangOpts() const { return LangOpts; } void setBlockID(signed i) { CurrentBlock = i; } void setStmtID(unsigned i) { CurrentStmt = i; } @@ -1516,7 +1518,10 @@ public: return true; } }; +} // end anonymous namespace + +namespace { class VISIBILITY_HIDDEN CFGBlockTerminatorPrint : public StmtVisitor<CFGBlockTerminatorPrint,void> { @@ -1526,7 +1531,7 @@ class VISIBILITY_HIDDEN CFGBlockTerminatorPrint public: CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper, - const PrintingPolicy &Policy = PrintingPolicy()) + const PrintingPolicy &Policy) : OS(os), Helper(helper), Policy(Policy) {} void VisitIfStmt(IfStmt* I) { @@ -1602,9 +1607,11 @@ public: E->printPretty(OS, Helper, Policy); } }; +} // end anonymous namespace + - -void print_stmt(llvm::raw_ostream&OS, StmtPrinterHelper* Helper, Stmt* Terminator) { +static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper, + Stmt* Terminator) { if (Helper) { // special printing for statement-expressions. if (StmtExpr* SE = dyn_cast<StmtExpr>(Terminator)) { @@ -1629,14 +1636,15 @@ void print_stmt(llvm::raw_ostream&OS, StmtPrinterHelper* Helper, Stmt* Terminato } } - Terminator->printPretty(OS, Helper, /*FIXME:*/PrintingPolicy()); + Terminator->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts())); // Expressions need a newline. if (isa<Expr>(Terminator)) OS << '\n'; } -void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B, - StmtPrinterHelper* Helper, bool print_edges) { +static void print_block(llvm::raw_ostream& OS, const CFG* cfg, + const CFGBlock& B, + StmtPrinterHelper* Helper, bool print_edges) { if (Helper) Helper->setBlockID(B.getBlockID()); @@ -1662,10 +1670,12 @@ void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B, OS << L->getName(); else if (CaseStmt* C = dyn_cast<CaseStmt>(Terminator)) { OS << "case "; - C->getLHS()->printPretty(OS, Helper, /*FIXME:*/PrintingPolicy()); + C->getLHS()->printPretty(OS, Helper, + PrintingPolicy(Helper->getLangOpts())); if (C->getRHS()) { OS << " ... "; - C->getRHS()->printPretty(OS, Helper, /*FIXME:*/PrintingPolicy()); + C->getRHS()->printPretty(OS, Helper, + PrintingPolicy(Helper->getLangOpts())); } } else if (isa<DefaultStmt>(Terminator)) @@ -1703,7 +1713,8 @@ void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B, if (Helper) Helper->setBlockID(-1); - CFGBlockTerminatorPrint TPrinter(OS, Helper, /*FIXME*/PrintingPolicy()); + CFGBlockTerminatorPrint TPrinter(OS, Helper, + PrintingPolicy(Helper->getLangOpts())); TPrinter.Visit(const_cast<Stmt*>(B.getTerminator())); OS << '\n'; } @@ -1741,15 +1752,13 @@ void print_block(llvm::raw_ostream& OS, const CFG* cfg, const CFGBlock& B, } } -} // end anonymous namespace /// dump - A simple pretty printer of a CFG that outputs to stderr. -void CFG::dump() const { print(llvm::errs()); } +void CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); } /// print - A simple pretty printer of a CFG that outputs to an ostream. -void CFG::print(llvm::raw_ostream& OS) const { - - StmtPrinterHelper Helper(this); +void CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const { + StmtPrinterHelper Helper(this, LO); // Print the entry block. print_block(OS, this, getEntry(), &Helper, true); @@ -1769,18 +1778,22 @@ void CFG::print(llvm::raw_ostream& OS) const { } /// dump - A simply pretty printer of a CFGBlock that outputs to stderr. -void CFGBlock::dump(const CFG* cfg) const { print(llvm::errs(), cfg); } +void CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const { + print(llvm::errs(), cfg, LO); +} /// print - A simple pretty printer of a CFGBlock that outputs to an ostream. /// Generally this will only be called from CFG::print. -void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg) const { - StmtPrinterHelper Helper(cfg); +void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg, + const LangOptions &LO) const { + StmtPrinterHelper Helper(cfg, LO); print_block(OS, cfg, *this, &Helper, true); } /// printTerminator - A simple pretty printer of the terminator of a CFGBlock. -void CFGBlock::printTerminator(llvm::raw_ostream& OS) const { - CFGBlockTerminatorPrint TPrinter(OS,NULL); +void CFGBlock::printTerminator(llvm::raw_ostream &OS, + const LangOptions &LO) const { + CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO)); TPrinter.Visit(const_cast<Stmt*>(getTerminator())); } @@ -1872,9 +1885,9 @@ bool CFGBlock::hasBinaryBranchTerminator() const { static StmtPrinterHelper* GraphHelper; #endif -void CFG::viewCFG() const { +void CFG::viewCFG(const LangOptions &LO) const { #ifndef NDEBUG - StmtPrinterHelper H(this); + StmtPrinterHelper H(this, LO); GraphHelper = &H; llvm::ViewGraph(this,"CFG"); GraphHelper = NULL; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 5382ab52ab5b..3d02150b65bf 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -41,7 +41,7 @@ void Attr::Destroy(ASTContext &C) { TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { - return new (C) TranslationUnitDecl(); + return new (C) TranslationUnitDecl(C); } NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC, @@ -226,8 +226,7 @@ std::string NamedDecl::getQualifiedNameAsString() const { if (const ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(Ctx)) { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - PrintingPolicy Policy; - Policy.CPlusPlus = true; + PrintingPolicy Policy(getASTContext().getLangOptions()); std::string TemplateArgsStr = TemplateSpecializationType::PrintTemplateArgumentList( TemplateArgs.getFlatArgumentList(), @@ -372,20 +371,15 @@ void FunctionDecl::Destroy(ASTContext& C) { C.Deallocate(ParamInfo); - if (TemplateSpecializationInfo *Info - = TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>()) - C.Deallocate(Info); - Decl::Destroy(C); } -Stmt *FunctionDecl::getBody(ASTContext &Context, - const FunctionDecl *&Definition) const { +Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { for (const FunctionDecl *FD = this; FD != 0; FD = FD->PreviousDeclaration) { if (FD->Body) { Definition = FD; - return FD->Body.get(Context.getExternalSource()); + return FD->Body.get(getASTContext().getExternalSource()); } } @@ -417,14 +411,14 @@ bool FunctionDecl::isExternC(ASTContext &Context) const { // In C, any non-static, non-overloadable function has external // linkage. if (!Context.getLangOptions().CPlusPlus) - return getStorageClass() != Static && !getAttr<OverloadableAttr>(Context); + return getStorageClass() != Static && !getAttr<OverloadableAttr>(); for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); DC = DC->getParent()) { if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC)) { if (Linkage->getLanguage() == LinkageSpecDecl::lang_c) return getStorageClass() != Static && - !getAttr<OverloadableAttr>(Context); + !getAttr<OverloadableAttr>(); break; } @@ -489,7 +483,7 @@ unsigned FunctionDecl::getBuiltinID(ASTContext &Context) const { if (isa<LinkageSpecDecl>(getDeclContext()) && cast<LinkageSpecDecl>(getDeclContext())->getLanguage() == LinkageSpecDecl::lang_c && - !getAttr<OverloadableAttr>(Context)) + !getAttr<OverloadableAttr>()) return BuiltinID; // Not a builtin @@ -540,12 +534,12 @@ unsigned FunctionDecl::getMinRequiredArguments() const { } bool FunctionDecl::hasActiveGNUInlineAttribute(ASTContext &Context) const { - if (!isInline() || !hasAttr<GNUInlineAttr>(Context)) + if (!isInline() || !hasAttr<GNUInlineAttr>()) return false; for (const FunctionDecl *FD = getPreviousDeclaration(); FD; FD = FD->getPreviousDeclaration()) { - if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>(Context)) + if (FD->isInline() && !FD->hasAttr<GNUInlineAttr>()) return false; } @@ -557,12 +551,24 @@ bool FunctionDecl::isExternGNUInline(ASTContext &Context) const { return false; for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDeclaration()) - if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>(Context)) + if (FD->getStorageClass() == Extern && FD->hasAttr<GNUInlineAttr>()) return true; return false; } +void +FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { + PreviousDeclaration = PrevDecl; + + if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { + FunctionTemplateDecl *PrevFunTmpl + = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; + assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); + FunTmpl->setPreviousDeclaration(PrevFunTmpl); + } +} + /// getOverloadedOperator - Which C++ overloaded operator this /// function represents, if any. OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { @@ -572,18 +578,64 @@ OverloadedOperatorKind FunctionDecl::getOverloadedOperator() const { return OO_None; } +FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { + if (FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo*>()) { + return Info->Template.getPointer(); + } + return 0; +} + +const TemplateArgumentList * +FunctionDecl::getTemplateSpecializationArgs() const { + if (FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo*>()) { + return Info->TemplateArguments; + } + return 0; +} + void FunctionDecl::setFunctionTemplateSpecialization(ASTContext &Context, FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs) { - TemplateSpecializationInfo *Info - = TemplateOrSpecialization.dyn_cast<TemplateSpecializationInfo*>(); + const TemplateArgumentList *TemplateArgs, + void *InsertPos) { + FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); if (!Info) - Info = new (Context) TemplateSpecializationInfo; + Info = new (Context) FunctionTemplateSpecializationInfo; - Info->Template = Template; + Info->Function = this; + Info->Template.setPointer(Template); + Info->Template.setInt(0); // Implicit instantiation, unless told otherwise Info->TemplateArguments = TemplateArgs; TemplateOrSpecialization = Info; + + // Insert this function template specialization into the set of known + // function template specialiations. + Template->getSpecializations().InsertNode(Info, InsertPos); +} + +bool FunctionDecl::isExplicitSpecialization() const { + // FIXME: check this property for explicit specializations of member + // functions of class templates. + FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); + if (!Info) + return false; + + return Info->isExplicitSpecialization(); +} + +void FunctionDecl::setExplicitSpecialization(bool ES) { + // FIXME: set this property for explicit specializations of member functions + // of class templates. + FunctionTemplateSpecializationInfo *Info + = TemplateOrSpecialization.dyn_cast<FunctionTemplateSpecializationInfo*>(); + if (Info) + Info->setExplicitSpecialization(ES); } //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 5815d820aef6..96ba19b9a6b9 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -157,6 +157,25 @@ void Decl::setLexicalDeclContext(DeclContext *DC) { } } +TranslationUnitDecl *Decl::getTranslationUnitDecl() { + if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this)) + return TUD; + + DeclContext *DC = getDeclContext(); + assert(DC && "This decl is not contained in a translation unit!"); + + while (!DC->isTranslationUnit()) { + DC = DC->getParent(); + assert(DC && "This decl is not contained in a translation unit!"); + } + + return cast<TranslationUnitDecl>(DC); +} + +ASTContext &Decl::getASTContext() const { + return getTranslationUnitDecl()->getASTContext(); +} + unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { switch (DeclKind) { default: @@ -226,8 +245,8 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { } } -void Decl::addAttr(ASTContext &Context, Attr *NewAttr) { - Attr *&ExistingAttr = Context.getDeclAttrs(this); +void Decl::addAttr(Attr *NewAttr) { + Attr *&ExistingAttr = getASTContext().getDeclAttrs(this); NewAttr->setNext(ExistingAttr); ExistingAttr = NewAttr; @@ -235,19 +254,19 @@ void Decl::addAttr(ASTContext &Context, Attr *NewAttr) { HasAttrs = true; } -void Decl::invalidateAttrs(ASTContext &Context) { +void Decl::invalidateAttrs() { if (!HasAttrs) return; HasAttrs = false; - Context.eraseDeclAttrs(this); + getASTContext().eraseDeclAttrs(this); } -const Attr *Decl::getAttrsImpl(ASTContext &Context) const { +const Attr *Decl::getAttrsImpl() const { assert(HasAttrs && "getAttrs() should verify this!"); - return Context.getDeclAttrs(this); + return getASTContext().getDeclAttrs(this); } -void Decl::swapAttrs(ASTContext &Context, Decl *RHS) { +void Decl::swapAttrs(Decl *RHS) { bool HasLHSAttr = this->HasAttrs; bool HasRHSAttr = RHS->HasAttrs; @@ -256,7 +275,9 @@ void Decl::swapAttrs(ASTContext &Context, Decl *RHS) { // If 'this' has no attrs, swap the other way. if (!HasLHSAttr) - return RHS->swapAttrs(Context, this); + return RHS->swapAttrs(this); + + ASTContext &Context = getASTContext(); // Handle the case when both decls have attrs. if (HasRHSAttr) { @@ -276,7 +297,7 @@ void Decl::Destroy(ASTContext &C) { // Free attributes for this decl. if (HasAttrs) { C.getDeclAttrs(this)->Destroy(C); - invalidateAttrs(C); + invalidateAttrs(); HasAttrs = false; } @@ -339,12 +360,12 @@ DeclContext *Decl::castToDeclContext(const Decl *D) { } } -CompoundStmt* Decl::getCompoundBody(ASTContext &Context) const { - return dyn_cast_or_null<CompoundStmt>(getBody(Context)); +CompoundStmt* Decl::getCompoundBody() const { + return dyn_cast_or_null<CompoundStmt>(getBody()); } -SourceLocation Decl::getBodyRBrace(ASTContext &Context) const { - Stmt *Body = getBody(Context); +SourceLocation Decl::getBodyRBrace() const { + Stmt *Body = getBody(); if (!Body) return SourceLocation(); if (CompoundStmt *CS = dyn_cast<CompoundStmt>(Body)) @@ -388,7 +409,7 @@ DeclContext::~DeclContext() { } void DeclContext::DestroyDecls(ASTContext &C) { - for (decl_iterator D = decls_begin(C); D != decls_end(C); ) + for (decl_iterator D = decls_begin(); D != decls_end(); ) (*D++)->Destroy(C); } @@ -479,8 +500,8 @@ DeclContext *DeclContext::getNextContext() { /// \brief Load the declarations within this lexical storage from an /// external source. void -DeclContext::LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const { - ExternalASTSource *Source = Context.getExternalSource(); +DeclContext::LoadLexicalDeclsFromExternalStorage() const { + ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalLexicalStorage() && Source && "No external storage?"); llvm::SmallVector<uint32_t, 64> Decls; @@ -517,9 +538,9 @@ DeclContext::LoadLexicalDeclsFromExternalStorage(ASTContext &Context) const { } void -DeclContext::LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const { +DeclContext::LoadVisibleDeclsFromExternalStorage() const { DeclContext *This = const_cast<DeclContext *>(this); - ExternalASTSource *Source = Context.getExternalSource(); + ExternalASTSource *Source = getParentASTContext().getExternalSource(); assert(hasExternalVisibleStorage() && Source && "No external storage?"); llvm::SmallVector<VisibleDeclaration, 64> Decls; @@ -539,30 +560,30 @@ DeclContext::LoadVisibleDeclsFromExternalStorage(ASTContext &Context) const { } } -DeclContext::decl_iterator DeclContext::decls_begin(ASTContext &Context) const { +DeclContext::decl_iterator DeclContext::decls_begin() const { if (hasExternalLexicalStorage()) - LoadLexicalDeclsFromExternalStorage(Context); + LoadLexicalDeclsFromExternalStorage(); // FIXME: Check whether we need to load some declarations from // external storage. return decl_iterator(FirstDecl); } -DeclContext::decl_iterator DeclContext::decls_end(ASTContext &Context) const { +DeclContext::decl_iterator DeclContext::decls_end() const { if (hasExternalLexicalStorage()) - LoadLexicalDeclsFromExternalStorage(Context); + LoadLexicalDeclsFromExternalStorage(); return decl_iterator(); } -bool DeclContext::decls_empty(ASTContext &Context) const { +bool DeclContext::decls_empty() const { if (hasExternalLexicalStorage()) - LoadLexicalDeclsFromExternalStorage(Context); + LoadLexicalDeclsFromExternalStorage(); return !FirstDecl; } -void DeclContext::addDecl(ASTContext &Context, Decl *D) { +void DeclContext::addDecl(Decl *D) { assert(D->getLexicalDeclContext() == this && "Decl inserted into wrong lexical context"); assert(!D->getNextDeclInContext() && D != LastDecl && @@ -576,44 +597,44 @@ void DeclContext::addDecl(ASTContext &Context, Decl *D) { } if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) - ND->getDeclContext()->makeDeclVisibleInContext(Context, ND); + ND->getDeclContext()->makeDeclVisibleInContext(ND); } /// buildLookup - Build the lookup data structure with all of the /// declarations in DCtx (and any other contexts linked to it or /// transparent contexts nested within it). -void DeclContext::buildLookup(ASTContext &Context, DeclContext *DCtx) { +void DeclContext::buildLookup(DeclContext *DCtx) { for (; DCtx; DCtx = DCtx->getNextContext()) { - for (decl_iterator D = DCtx->decls_begin(Context), - DEnd = DCtx->decls_end(Context); + for (decl_iterator D = DCtx->decls_begin(), + DEnd = DCtx->decls_end(); D != DEnd; ++D) { // Insert this declaration into the lookup structure if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) - makeDeclVisibleInContextImpl(Context, ND); + makeDeclVisibleInContextImpl(ND); // If this declaration is itself a transparent declaration context, // add its members (recursively). if (DeclContext *InnerCtx = dyn_cast<DeclContext>(*D)) if (InnerCtx->isTransparentContext()) - buildLookup(Context, InnerCtx->getPrimaryContext()); + buildLookup(InnerCtx->getPrimaryContext()); } } } DeclContext::lookup_result -DeclContext::lookup(ASTContext &Context, DeclarationName Name) { +DeclContext::lookup(DeclarationName Name) { DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) - return PrimaryContext->lookup(Context, Name); + return PrimaryContext->lookup(Name); if (hasExternalVisibleStorage()) - LoadVisibleDeclsFromExternalStorage(Context); + LoadVisibleDeclsFromExternalStorage(); /// If there is no lookup data structure, build one now by walking /// all of the linked DeclContexts (in declaration order!) and /// inserting their values. if (!LookupPtr) { - buildLookup(Context, this); + buildLookup(this); if (!LookupPtr) return lookup_result(0, 0); @@ -623,12 +644,12 @@ DeclContext::lookup(ASTContext &Context, DeclarationName Name) { StoredDeclsMap::iterator Pos = Map->find(Name); if (Pos == Map->end()) return lookup_result(0, 0); - return Pos->second.getLookupResult(Context); + return Pos->second.getLookupResult(getParentASTContext()); } DeclContext::lookup_const_result -DeclContext::lookup(ASTContext &Context, DeclarationName Name) const { - return const_cast<DeclContext*>(this)->lookup(Context, Name); +DeclContext::lookup(DeclarationName Name) const { + return const_cast<DeclContext*>(this)->lookup(Name); } DeclContext *DeclContext::getLookupContext() { @@ -647,7 +668,7 @@ DeclContext *DeclContext::getEnclosingNamespaceContext() { return Ctx->getPrimaryContext(); } -void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) { +void DeclContext::makeDeclVisibleInContext(NamedDecl *D) { // FIXME: This feels like a hack. Should DeclarationName support // template-ids, or is there a better way to keep specializations // from being visible? @@ -656,7 +677,7 @@ void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) { DeclContext *PrimaryContext = getPrimaryContext(); if (PrimaryContext != this) { - PrimaryContext->makeDeclVisibleInContext(Context, D); + PrimaryContext->makeDeclVisibleInContext(D); return; } @@ -664,16 +685,15 @@ void DeclContext::makeDeclVisibleInContext(ASTContext &Context, NamedDecl *D) { // into it. Otherwise, be lazy and don't build that structure until // someone asks for it. if (LookupPtr) - makeDeclVisibleInContextImpl(Context, D); + makeDeclVisibleInContextImpl(D); // If we are a transparent context, insert into our parent context, // too. This operation is recursive. if (isTransparentContext()) - getParent()->makeDeclVisibleInContext(Context, D); + getParent()->makeDeclVisibleInContext(D); } -void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context, - NamedDecl *D) { +void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D) { // Skip unnamed declarations. if (!D->getDeclName()) return; @@ -698,7 +718,7 @@ void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context, // If it is possible that this is a redeclaration, check to see if there is // already a decl for which declarationReplaces returns true. If there is // one, just replace it and return. - if (DeclNameEntries.HandleRedeclaration(Context, D)) + if (DeclNameEntries.HandleRedeclaration(getParentASTContext(), D)) return; // Put this declaration into the appropriate slot. @@ -708,8 +728,8 @@ void DeclContext::makeDeclVisibleInContextImpl(ASTContext &Context, /// Returns iterator range [First, Last) of UsingDirectiveDecls stored within /// this context. DeclContext::udir_iterator_range -DeclContext::getUsingDirectives(ASTContext &Context) const { - lookup_const_result Result = lookup(Context, UsingDirectiveDecl::getName()); +DeclContext::getUsingDirectives() const { + lookup_const_result Result = lookup(UsingDirectiveDecl::getName()); return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.first), reinterpret_cast<udir_iterator>(Result.second)); } diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 752218db042a..b8b29528066d 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -44,11 +44,16 @@ CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC, } CXXRecordDecl::~CXXRecordDecl() { - delete [] Bases; +} + +void CXXRecordDecl::Destroy(ASTContext &C) { + C.Deallocate(Bases); + this->RecordDecl::Destroy(C); } void -CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, +CXXRecordDecl::setBases(ASTContext &C, + CXXBaseSpecifier const * const *Bases, unsigned NumBases) { // C++ [dcl.init.aggr]p1: // An aggregate is an array or a class (clause 9) with [...] @@ -56,10 +61,9 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, Aggregate = false; if (this->Bases) - delete [] this->Bases; + C.Deallocate(this->Bases); - // FIXME: allocate using the ASTContext - this->Bases = new CXXBaseSpecifier[NumBases]; + this->Bases = new(C) CXXBaseSpecifier [NumBases]; this->NumBases = NumBases; for (unsigned i = 0; i < NumBases; ++i) this->Bases[i] = *Bases[i]; @@ -78,7 +82,7 @@ CXXConstructorDecl *CXXRecordDecl::getCopyConstructor(ASTContext &Context, Context.getCanonicalType(ClassType)); unsigned FoundTQs; DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = this->lookup(Context, ConstructorName); + for (llvm::tie(Con, ConEnd) = this->lookup(ConstructorName); Con != ConEnd; ++Con) { if (cast<CXXConstructorDecl>(*Con)->isCopyConstructor(Context, FoundTQs)) { @@ -97,7 +101,7 @@ bool CXXRecordDecl::hasConstCopyAssignment(ASTContext &Context) const { DeclarationName OpName =Context.DeclarationNames.getCXXOperatorName(OO_Equal); DeclContext::lookup_const_iterator Op, OpEnd; - for (llvm::tie(Op, OpEnd) = this->lookup(Context, OpName); + for (llvm::tie(Op, OpEnd) = this->lookup(OpName); Op != OpEnd; ++Op) { // C++ [class.copy]p9: // A user-declared copy assignment operator is a non-static non-template @@ -201,7 +205,7 @@ CXXRecordDecl::getDefaultConstructor(ASTContext &Context) { Context.getCanonicalType(ClassType.getUnqualifiedType())); DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = lookup(Context, ConstructorName); + for (llvm::tie(Con, ConEnd) = lookup(ConstructorName); Con != ConEnd; ++Con) { CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); if (Constructor->isDefaultConstructor()) @@ -218,7 +222,7 @@ CXXRecordDecl::getDestructor(ASTContext &Context) { = Context.DeclarationNames.getCXXDestructorName(ClassType); DeclContext::lookup_iterator I, E; - llvm::tie(I, E) = lookup(Context, Name); + llvm::tie(I, E) = lookup(Name); assert(I != E && "Did not find a destructor!"); const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(*I); @@ -294,8 +298,9 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const { } CXXBaseOrMemberInitializer:: -CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs) - : Args(0), NumArgs(0) { +CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, + SourceLocation L) + : Args(0), NumArgs(0), IdLoc(L) { BaseOrMember = reinterpret_cast<uintptr_t>(BaseType.getTypePtr()); assert((BaseOrMember & 0x01) == 0 && "Invalid base class type pointer"); BaseOrMember |= 0x01; @@ -309,8 +314,9 @@ CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs) } CXXBaseOrMemberInitializer:: -CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs) - : Args(0), NumArgs(0) { +CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, + SourceLocation L) + : Args(0), NumArgs(0), IdLoc(L) { BaseOrMember = reinterpret_cast<uintptr_t>(Member); assert((BaseOrMember & 0x01) == 0 && "Invalid member pointer"); @@ -405,6 +411,27 @@ CXXDestructorDecl::Create(ASTContext &C, CXXRecordDecl *RD, isImplicitlyDeclared); } +void +CXXConstructorDecl::setBaseOrMemberInitializers( + ASTContext &C, + CXXBaseOrMemberInitializer **Initializers, + unsigned NumInitializers) { + if (NumInitializers > 0) { + NumBaseOrMemberInitializers = NumInitializers; + BaseOrMemberInitializers = + new (C, 8) CXXBaseOrMemberInitializer*[NumInitializers]; + for (unsigned Idx = 0; Idx < NumInitializers; ++Idx) + BaseOrMemberInitializers[Idx] = Initializers[Idx]; + } +} + +void +CXXConstructorDecl::Destroy(ASTContext& C) { + C.Deallocate(BaseOrMemberInitializers); + this->~CXXMethodDecl(); + C.Deallocate((void *)this); +} + CXXConversionDecl * CXXConversionDecl::Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, @@ -420,13 +447,9 @@ OverloadedFunctionDecl::Create(ASTContext &C, DeclContext *DC, return new (C) OverloadedFunctionDecl(DC, N); } -void OverloadedFunctionDecl::addOverload(FunctionTemplateDecl *FTD) { - Functions.push_back(FTD); - - // An overloaded function declaration always has the location of - // the most-recently-added function declaration. - if (FTD->getLocation().isValid()) - this->setLocation(FTD->getLocation()); +void OverloadedFunctionDecl::addOverload(AnyFunctionDecl F) { + Functions.push_back(F); + this->setLocation(F.get()->getLocation()); } LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C, diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp index 60a96d0471ab..54f13e14ba65 100644 --- a/lib/AST/DeclObjC.cpp +++ b/lib/AST/DeclObjC.cpp @@ -45,10 +45,9 @@ void ObjCListBase::set(void *const* InList, unsigned Elts, ASTContext &Ctx) { /// getIvarDecl - This method looks up an ivar in this ContextDecl. /// ObjCIvarDecl * -ObjCContainerDecl::getIvarDecl(ASTContext &Context, IdentifierInfo *Id) const { +ObjCContainerDecl::getIvarDecl(IdentifierInfo *Id) const { lookup_const_iterator Ivar, IvarEnd; - for (llvm::tie(Ivar, IvarEnd) = lookup(Context, Id); - Ivar != IvarEnd; ++Ivar) { + for (llvm::tie(Ivar, IvarEnd) = lookup(Id); Ivar != IvarEnd; ++Ivar) { if (ObjCIvarDecl *ivar = dyn_cast<ObjCIvarDecl>(*Ivar)) return ivar; } @@ -57,7 +56,7 @@ ObjCContainerDecl::getIvarDecl(ASTContext &Context, IdentifierInfo *Id) const { // Get the local instance method declared in this interface. ObjCMethodDecl * -ObjCContainerDecl::getInstanceMethod(ASTContext &Context, Selector Sel) const { +ObjCContainerDecl::getInstanceMethod(Selector Sel) const { // Since instance & class methods can have the same name, the loop below // ensures we get the correct method. // @@ -67,8 +66,7 @@ ObjCContainerDecl::getInstanceMethod(ASTContext &Context, Selector Sel) const { // @end // lookup_const_iterator Meth, MethEnd; - for (llvm::tie(Meth, MethEnd) = lookup(Context, Sel); - Meth != MethEnd; ++Meth) { + for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) { ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); if (MD && MD->isInstanceMethod()) return MD; @@ -78,7 +76,7 @@ ObjCContainerDecl::getInstanceMethod(ASTContext &Context, Selector Sel) const { // Get the local class method declared in this interface. ObjCMethodDecl * -ObjCContainerDecl::getClassMethod(ASTContext &Context, Selector Sel) const { +ObjCContainerDecl::getClassMethod(Selector Sel) const { // Since instance & class methods can have the same name, the loop below // ensures we get the correct method. // @@ -88,8 +86,7 @@ ObjCContainerDecl::getClassMethod(ASTContext &Context, Selector Sel) const { // @end // lookup_const_iterator Meth, MethEnd; - for (llvm::tie(Meth, MethEnd) = lookup(Context, Sel); - Meth != MethEnd; ++Meth) { + for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) { ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); if (MD && MD->isClassMethod()) return MD; @@ -102,10 +99,8 @@ ObjCContainerDecl::getClassMethod(ASTContext &Context, Selector Sel) const { /// FIXME: Convert to DeclContext lookup... /// ObjCPropertyDecl * -ObjCContainerDecl::FindPropertyDeclaration(ASTContext &Context, - IdentifierInfo *PropertyId) const { - for (prop_iterator I = prop_begin(Context), E = prop_end(Context); - I != E; ++I) +ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const { + for (prop_iterator I = prop_begin(), E = prop_end(); I != E; ++I) if ((*I)->getIdentifier() == PropertyId) return *I; @@ -113,8 +108,7 @@ ObjCContainerDecl::FindPropertyDeclaration(ASTContext &Context, if (PID) { for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(), E = PID->protocol_end(); I != E; ++I) - if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(Context, - PropertyId)) + if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) return P; } @@ -122,37 +116,33 @@ ObjCContainerDecl::FindPropertyDeclaration(ASTContext &Context, // Look through categories. for (ObjCCategoryDecl *Category = OID->getCategoryList(); Category; Category = Category->getNextClassCategory()) { - if (ObjCPropertyDecl *P = Category->FindPropertyDeclaration(Context, - PropertyId)) + if (ObjCPropertyDecl *P = Category->FindPropertyDeclaration(PropertyId)) return P; } // Look through protocols. for (ObjCInterfaceDecl::protocol_iterator I = OID->protocol_begin(), E = OID->protocol_end(); I != E; ++I) { - if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(Context, - PropertyId)) + if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) return P; } if (OID->getSuperClass()) - return OID->getSuperClass()->FindPropertyDeclaration(Context, - PropertyId); + return OID->getSuperClass()->FindPropertyDeclaration(PropertyId); } else if (const ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(this)) { // Look through protocols. for (ObjCInterfaceDecl::protocol_iterator I = OCD->protocol_begin(), E = OCD->protocol_end(); I != E; ++I) { - if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(Context, - PropertyId)) + if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId)) return P; } } return 0; } -ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable( - ASTContext &Context, IdentifierInfo *ID, ObjCInterfaceDecl *&clsDeclared) { +ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID, + ObjCInterfaceDecl *&clsDeclared) { ObjCInterfaceDecl* ClassDecl = this; while (ClassDecl != NULL) { - if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(Context, ID)) { + if (ObjCIvarDecl *I = ClassDecl->getIvarDecl(ID)) { clsDeclared = ClassDecl; return I; } @@ -177,13 +167,12 @@ ObjCInterfaceDecl *ObjCInterfaceDecl::lookupInheritedClass( /// lookupInstanceMethod - This method returns an instance method by looking in /// the class, its categories, and its super classes (using a linear search). -ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(ASTContext &Context, - Selector Sel) { +ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(Selector Sel) { ObjCInterfaceDecl* ClassDecl = this; ObjCMethodDecl *MethodDecl = 0; while (ClassDecl != NULL) { - if ((MethodDecl = ClassDecl->getInstanceMethod(Context, Sel))) + if ((MethodDecl = ClassDecl->getInstanceMethod(Sel))) return MethodDecl; // Didn't find one yet - look through protocols. @@ -191,13 +180,13 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(ASTContext &Context, ClassDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupInstanceMethod(Context, Sel))) + if ((MethodDecl = (*I)->lookupInstanceMethod(Sel))) return MethodDecl; // Didn't find one yet - now look through categories. ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); while (CatDecl) { - if ((MethodDecl = CatDecl->getInstanceMethod(Context, Sel))) + if ((MethodDecl = CatDecl->getInstanceMethod(Sel))) return MethodDecl; // Didn't find one yet - look through protocols. @@ -205,7 +194,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(ASTContext &Context, CatDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupInstanceMethod(Context, Sel))) + if ((MethodDecl = (*I)->lookupInstanceMethod(Sel))) return MethodDecl; CatDecl = CatDecl->getNextClassCategory(); } @@ -216,25 +205,24 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupInstanceMethod(ASTContext &Context, // lookupClassMethod - This method returns a class method by looking in the // class, its categories, and its super classes (using a linear search). -ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(ASTContext &Context, - Selector Sel) { +ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(Selector Sel) { ObjCInterfaceDecl* ClassDecl = this; ObjCMethodDecl *MethodDecl = 0; while (ClassDecl != NULL) { - if ((MethodDecl = ClassDecl->getClassMethod(Context, Sel))) + if ((MethodDecl = ClassDecl->getClassMethod(Sel))) return MethodDecl; // Didn't find one yet - look through protocols. for (ObjCInterfaceDecl::protocol_iterator I = ClassDecl->protocol_begin(), E = ClassDecl->protocol_end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupClassMethod(Context, Sel))) + if ((MethodDecl = (*I)->lookupClassMethod(Sel))) return MethodDecl; // Didn't find one yet - now look through categories. ObjCCategoryDecl *CatDecl = ClassDecl->getCategoryList(); while (CatDecl) { - if ((MethodDecl = CatDecl->getClassMethod(Context, Sel))) + if ((MethodDecl = CatDecl->getClassMethod(Sel))) return MethodDecl; // Didn't find one yet - look through protocols. @@ -242,7 +230,7 @@ ObjCMethodDecl *ObjCInterfaceDecl::lookupClassMethod(ASTContext &Context, CatDecl->getReferencedProtocols(); for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), E = Protocols.end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupClassMethod(Context, Sel))) + if ((MethodDecl = (*I)->lookupClassMethod(Sel))) return MethodDecl; CatDecl = CatDecl->getNextClassCategory(); } @@ -446,30 +434,28 @@ ObjCProtocolDecl *ObjCProtocolDecl::lookupProtocolNamed(IdentifierInfo *Name) { // lookupInstanceMethod - Lookup a instance method in the protocol and protocols // it inherited. -ObjCMethodDecl *ObjCProtocolDecl::lookupInstanceMethod(ASTContext &Context, - Selector Sel) { +ObjCMethodDecl *ObjCProtocolDecl::lookupInstanceMethod(Selector Sel) { ObjCMethodDecl *MethodDecl = NULL; - if ((MethodDecl = getInstanceMethod(Context, Sel))) + if ((MethodDecl = getInstanceMethod(Sel))) return MethodDecl; for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupInstanceMethod(Context, Sel))) + if ((MethodDecl = (*I)->lookupInstanceMethod(Sel))) return MethodDecl; return NULL; } // lookupInstanceMethod - Lookup a class method in the protocol and protocols // it inherited. -ObjCMethodDecl *ObjCProtocolDecl::lookupClassMethod(ASTContext &Context, - Selector Sel) { +ObjCMethodDecl *ObjCProtocolDecl::lookupClassMethod(Selector Sel) { ObjCMethodDecl *MethodDecl = NULL; - if ((MethodDecl = getClassMethod(Context, Sel))) + if ((MethodDecl = getClassMethod(Sel))) return MethodDecl; for (protocol_iterator I = protocol_begin(), E = protocol_end(); I != E; ++I) - if ((MethodDecl = (*I)->lookupClassMethod(Context, Sel))) + if ((MethodDecl = (*I)->lookupClassMethod(Sel))) return MethodDecl; return NULL; } @@ -555,11 +541,10 @@ ObjCCategoryImplDecl::Create(ASTContext &C, DeclContext *DC, } -void ObjCImplDecl::addPropertyImplementation(ASTContext &Context, - ObjCPropertyImplDecl *property) { +void ObjCImplDecl::addPropertyImplementation(ObjCPropertyImplDecl *property) { // FIXME: The context should be correct before we get here. property->setLexicalDeclContext(this); - addDecl(Context, property); + addDecl(property); } /// FindPropertyImplIvarDecl - This method lookup the ivar in the list of @@ -567,9 +552,8 @@ void ObjCImplDecl::addPropertyImplementation(ASTContext &Context, /// the implemented property that uses it. /// ObjCPropertyImplDecl *ObjCImplDecl:: -FindPropertyImplIvarDecl(ASTContext &Context, IdentifierInfo *ivarId) const { - for (propimpl_iterator i = propimpl_begin(Context), e = propimpl_end(Context); - i != e; ++i){ +FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const { + for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){ ObjCPropertyImplDecl *PID = *i; if (PID->getPropertyIvarDecl() && PID->getPropertyIvarDecl()->getIdentifier() == ivarId) @@ -583,9 +567,8 @@ FindPropertyImplIvarDecl(ASTContext &Context, IdentifierInfo *ivarId) const { /// category @implementation block. /// ObjCPropertyImplDecl *ObjCImplDecl:: -FindPropertyImplDecl(ASTContext &Context, IdentifierInfo *Id) const { - for (propimpl_iterator i = propimpl_begin(Context), e = propimpl_end(Context); - i != e; ++i){ +FindPropertyImplDecl(IdentifierInfo *Id) const { + for (propimpl_iterator i = propimpl_begin(), e = propimpl_end(); i != e; ++i){ ObjCPropertyImplDecl *PID = *i; if (PID->getPropertyDecl()->getIdentifier() == Id) return PID; @@ -596,8 +579,7 @@ FindPropertyImplDecl(ASTContext &Context, IdentifierInfo *Id) const { // getInstanceMethod - This method returns an instance method by looking in // the class implementation. Unlike interfaces, we don't look outside the // implementation. -ObjCMethodDecl *ObjCImplDecl::getInstanceMethod(ASTContext &Context, - Selector Sel) const { +ObjCMethodDecl *ObjCImplDecl::getInstanceMethod(Selector Sel) const { // Since instance & class methods can have the same name, the loop below // ensures we get the correct method. // @@ -607,7 +589,7 @@ ObjCMethodDecl *ObjCImplDecl::getInstanceMethod(ASTContext &Context, // @end // lookup_const_iterator Meth, MethEnd; - for (llvm::tie(Meth, MethEnd) = lookup(Context, Sel); + for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) { ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); if (MD && MD->isInstanceMethod()) @@ -619,8 +601,7 @@ ObjCMethodDecl *ObjCImplDecl::getInstanceMethod(ASTContext &Context, // getClassMethod - This method returns an instance method by looking in // the class implementation. Unlike interfaces, we don't look outside the // implementation. -ObjCMethodDecl *ObjCImplDecl::getClassMethod(ASTContext &Context, - Selector Sel) const { +ObjCMethodDecl *ObjCImplDecl::getClassMethod(Selector Sel) const { // Since instance & class methods can have the same name, the loop below // ensures we get the correct method. // @@ -630,7 +611,7 @@ ObjCMethodDecl *ObjCImplDecl::getClassMethod(ASTContext &Context, // @end // lookup_const_iterator Meth, MethEnd; - for (llvm::tie(Meth, MethEnd) = lookup(Context, Sel); + for (llvm::tie(Meth, MethEnd) = lookup(Sel); Meth != MethEnd; ++Meth) { ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth); if (MD && MD->isClassMethod()) diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 2b06e93295bc..12e89cd80d19 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -74,14 +74,13 @@ namespace { }; } -void Decl::print(llvm::raw_ostream &Out, ASTContext &Context, - unsigned Indentation) { - print(Out, Context, Context.PrintingPolicy, Indentation); +void Decl::print(llvm::raw_ostream &Out, unsigned Indentation) { + print(Out, getASTContext().PrintingPolicy, Indentation); } -void Decl::print(llvm::raw_ostream &Out, ASTContext &Context, - const PrintingPolicy &Policy, unsigned Indentation) { - DeclPrinter Printer(Out, Context, Policy, Indentation); +void Decl::print(llvm::raw_ostream &Out, const PrintingPolicy &Policy, + unsigned Indentation) { + DeclPrinter Printer(Out, getASTContext(), Policy, Indentation); Printer.Visit(this); } @@ -97,6 +96,8 @@ static QualType GetBaseType(QualType T) { BaseType = ATy->getElementType(); else if (const FunctionType* FTy = BaseType->getAsFunctionType()) BaseType = FTy->getResultType(); + else if (const VectorType *VTy = BaseType->getAsVectorType()) + BaseType = VTy->getElementType(); else assert(0 && "Unknown declarator!"); } @@ -112,11 +113,10 @@ static QualType getDeclType(Decl* D) { } void Decl::printGroup(Decl** Begin, unsigned NumDecls, - llvm::raw_ostream &Out, ASTContext &Context, - const PrintingPolicy &Policy, + llvm::raw_ostream &Out, const PrintingPolicy &Policy, unsigned Indentation) { if (NumDecls == 1) { - (*Begin)->print(Out, Context, Policy, Indentation); + (*Begin)->print(Out, Policy, Indentation); return; } @@ -127,7 +127,7 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls, PrintingPolicy SubPolicy(Policy); if (TD && TD->isDefinition()) { - TD->print(Out, Context, Policy, Indentation); + TD->print(Out, Policy, Indentation); Out << " "; SubPolicy.SuppressTag = true; } @@ -142,12 +142,12 @@ void Decl::printGroup(Decl** Begin, unsigned NumDecls, SubPolicy.SuppressSpecifiers = true; } - (*Begin)->print(Out, Context, SubPolicy, Indentation); + (*Begin)->print(Out, SubPolicy, Indentation); } } -void Decl::dump(ASTContext &Context) { - print(llvm::errs(), Context); +void Decl::dump() { + print(llvm::errs()); } llvm::raw_ostream& DeclPrinter::Indent() { @@ -158,8 +158,7 @@ llvm::raw_ostream& DeclPrinter::Indent() { void DeclPrinter::ProcessDeclGroup(llvm::SmallVectorImpl<Decl*>& Decls) { this->Indent(); - Decl::printGroup(Decls.data(), Decls.size(), Out, Context, - Policy, Indentation); + Decl::printGroup(Decls.data(), Decls.size(), Out, Policy, Indentation); Out << ";\n"; Decls.clear(); @@ -174,8 +173,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { Indentation += Policy.Indentation; llvm::SmallVector<Decl*, 2> Decls; - for (DeclContext::decl_iterator D = DC->decls_begin(Context), - DEnd = DC->decls_end(Context); + for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); D != DEnd; ++D) { if (!Policy.Dump) { // Skip over implicit declarations in pretty-printing mode. @@ -364,7 +362,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) { } else Out << ' '; - D->getBody(Context)->printPretty(Out, Context, 0, SubPolicy, Indentation); + D->getBody()->printPretty(Out, Context, 0, SubPolicy, Indentation); Out << '\n'; } } @@ -504,7 +502,7 @@ void DeclPrinter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { VisitDeclContext(D); Indent() << "}"; } else - Visit(*D->decls_begin(Context)); + Visit(*D->decls_begin()); } void DeclPrinter::VisitTemplateDecl(TemplateDecl *D) { diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 165672d50f4e..f1bd1b67d21e 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -81,11 +81,36 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, + TemplateParameterList *Params, NamedDecl *Decl) { return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); } +void FunctionTemplateDecl::Destroy(ASTContext &C) { + if (Common *CommonPtr = CommonOrPrev.dyn_cast<Common*>()) { + for (llvm::FoldingSet<FunctionTemplateSpecializationInfo>::iterator + Spec = CommonPtr->Specializations.begin(), + SpecEnd = CommonPtr->Specializations.end(); + Spec != SpecEnd; ++Spec) + C.Deallocate(&*Spec); + } + + Decl::Destroy(C); +} + +FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() { + // Find the first declaration of this function template. + FunctionTemplateDecl *First = this; + while (First->getPreviousDeclaration()) + First = First->getPreviousDeclaration(); + + if (First->CommonOrPrev.isNull()) { + // FIXME: Allocate with the ASTContext + First->CommonOrPrev = new Common; + } + return First->CommonOrPrev.get<Common*>(); +} + //===----------------------------------------------------------------------===// // ClassTemplateDecl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index fce88cc0da28..482e1062d88c 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -41,8 +41,7 @@ CharacterLiteral* CharacterLiteral::Clone(ASTContext &C) const { } FloatingLiteral* FloatingLiteral::Clone(ASTContext &C) const { - bool exact = IsExact; - return new (C) FloatingLiteral(Value, &exact, getType(), Loc); + return new (C) FloatingLiteral(Value, IsExact, getType(), Loc); } ImaginaryLiteral* ImaginaryLiteral::Clone(ASTContext &C) const { @@ -456,7 +455,7 @@ Stmt *BlockExpr::getBody() { /// with location to warn on and the source range[s] to report with the /// warning. bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, - SourceRange &R2, ASTContext &Context) const { + SourceRange &R2) const { // Don't warn if the expr is type dependent. The type could end up // instantiating to void. if (isTypeDependent()) @@ -469,7 +468,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return true; case ParenExprClass: return cast<ParenExpr>(this)->getSubExpr()-> - isUnusedResultAWarning(Loc, R1, R2, Context); + isUnusedResultAWarning(Loc, R1, R2); case UnaryOperatorClass: { const UnaryOperator *UO = cast<UnaryOperator>(this); @@ -492,7 +491,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return false; break; case UnaryOperator::Extension: - return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context); + return UO->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2); } Loc = UO->getOperatorLoc(); R1 = UO->getSubExpr()->getSourceRange(); @@ -502,8 +501,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, const BinaryOperator *BO = cast<BinaryOperator>(this); // Consider comma to have side effects if the LHS or RHS does. if (BO->getOpcode() == BinaryOperator::Comma) - return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context) || - BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context); + return BO->getRHS()->isUnusedResultAWarning(Loc, R1, R2) || + BO->getLHS()->isUnusedResultAWarning(Loc, R1, R2); if (BO->isAssignmentOp()) return false; @@ -520,9 +519,9 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // warning, warn about them. const ConditionalOperator *Exp = cast<ConditionalOperator>(this); if (Exp->getLHS() && - Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2, Context)) + Exp->getLHS()->isUnusedResultAWarning(Loc, R1, R2)) return true; - return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2, Context); + return Exp->getRHS()->isUnusedResultAWarning(Loc, R1, R2); } case MemberExprClass: @@ -555,8 +554,8 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // If the callee has attribute pure, const, or warn_unused_result, warn // about it. void foo() { strlen("bar"); } should warn. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CalleeDRE->getDecl())) - if (FD->getAttr<WarnUnusedResultAttr>(Context) || - FD->getAttr<PureAttr>(Context) || FD->getAttr<ConstAttr>(Context)) { + if (FD->getAttr<WarnUnusedResultAttr>() || + FD->getAttr<PureAttr>() || FD->getAttr<ConstAttr>()) { Loc = CE->getCallee()->getLocStart(); R1 = CE->getCallee()->getSourceRange(); @@ -579,7 +578,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, const CompoundStmt *CS = cast<StmtExpr>(this)->getSubStmt(); if (!CS->body_empty()) if (const Expr *E = dyn_cast<Expr>(CS->body_back())) - return E->isUnusedResultAWarning(Loc, R1, R2, Context); + return E->isUnusedResultAWarning(Loc, R1, R2); Loc = cast<StmtExpr>(this)->getLParenLoc(); R1 = getSourceRange(); @@ -590,7 +589,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // the cast is unused. if (getType()->isVoidType()) return cast<CastExpr>(this)->getSubExpr() - ->isUnusedResultAWarning(Loc, R1, R2, Context); + ->isUnusedResultAWarning(Loc, R1, R2); Loc = cast<CStyleCastExpr>(this)->getLParenLoc(); R1 = cast<CStyleCastExpr>(this)->getSubExpr()->getSourceRange(); return true; @@ -599,7 +598,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, // the cast is unused. if (getType()->isVoidType()) return cast<CastExpr>(this)->getSubExpr() - ->isUnusedResultAWarning(Loc, R1, R2, Context); + ->isUnusedResultAWarning(Loc, R1, R2); Loc = cast<CXXFunctionalCastExpr>(this)->getTypeBeginLoc(); R1 = cast<CXXFunctionalCastExpr>(this)->getSubExpr()->getSourceRange(); return true; @@ -607,11 +606,11 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, case ImplicitCastExprClass: // Check the operand, since implicit casts are inserted by Sema return cast<ImplicitCastExpr>(this) - ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context); + ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2); case CXXDefaultArgExprClass: return cast<CXXDefaultArgExpr>(this) - ->getExpr()->isUnusedResultAWarning(Loc, R1, R2, Context); + ->getExpr()->isUnusedResultAWarning(Loc, R1, R2); case CXXNewExprClass: // FIXME: In theory, there might be new expressions that don't have side @@ -620,7 +619,7 @@ bool Expr::isUnusedResultAWarning(SourceLocation &Loc, SourceRange &R1, return false; case CXXExprWithTemporariesClass: return cast<CXXExprWithTemporaries>(this) - ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2, Context); + ->getSubExpr()->isUnusedResultAWarning(Loc, R1, R2); } } diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 18c0f77ab29e..399c30255a8f 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -13,6 +13,7 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" using namespace clang; @@ -153,6 +154,65 @@ StmtIterator UnresolvedDeclRefExpr::child_end() { return child_iterator(); } +TemplateIdRefExpr::TemplateIdRefExpr(QualType T, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + TemplateName Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc) + : Expr(TemplateIdRefExprClass, T, + (Template.isDependent() || + TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs, NumTemplateArgs)), + (Template.isDependent() || + TemplateSpecializationType::anyDependentTemplateArguments( + TemplateArgs, NumTemplateArgs))), + Qualifier(Qualifier), QualifierRange(QualifierRange), Template(Template), + TemplateNameLoc(TemplateNameLoc), LAngleLoc(LAngleLoc), + RAngleLoc(RAngleLoc), NumTemplateArgs(NumTemplateArgs) + +{ + TemplateArgument *StoredTemplateArgs + = reinterpret_cast<TemplateArgument *> (this+1); + for (unsigned I = 0; I != NumTemplateArgs; ++I) + new (StoredTemplateArgs + I) TemplateArgument(TemplateArgs[I]); +} + +TemplateIdRefExpr * +TemplateIdRefExpr::Create(ASTContext &Context, QualType T, + NestedNameSpecifier *Qualifier, + SourceRange QualifierRange, + TemplateName Template, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, SourceLocation RAngleLoc) { + void *Mem = Context.Allocate(sizeof(TemplateIdRefExpr) + + sizeof(TemplateArgument) * NumTemplateArgs); + return new (Mem) TemplateIdRefExpr(T, Qualifier, QualifierRange, Template, + TemplateNameLoc, LAngleLoc, TemplateArgs, + NumTemplateArgs, RAngleLoc); +} + +void TemplateIdRefExpr::Destroy(ASTContext &Context) { + const TemplateArgument *TemplateArgs = getTemplateArgs(); + for (unsigned I = 0; I != NumTemplateArgs; ++I) + if (Expr *E = TemplateArgs[I].getAsExpr()) + E->Destroy(Context); +} + +Stmt::child_iterator TemplateIdRefExpr::child_begin() { + // FIXME: Walk the expressions in the template arguments (?) + return Stmt::child_iterator(); +} + +Stmt::child_iterator TemplateIdRefExpr::child_end() { + // FIXME: Walk the expressions in the template arguments (?) + return Stmt::child_iterator(); +} + bool UnaryTypeTraitExpr::EvaluateTrait() const { switch(UTT) { default: assert(false && "Unknown type trait or not implemented"); diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 9d765924e02a..eb6b5b725ff5 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -242,8 +242,8 @@ APValue LValueExprEvaluator::VisitMemberExpr(MemberExpr *E) { // FIXME: This is linear time. unsigned i = 0; - for (RecordDecl::field_iterator Field = RD->field_begin(Info.Ctx), - FieldEnd = RD->field_end(Info.Ctx); + for (RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); Field != FieldEnd; (void)++Field, ++i) { if (*Field == FD) break; @@ -485,6 +485,11 @@ static bool EvaluateVector(const Expr* E, APValue& Result, EvalInfo &Info) { } APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { + const VectorType *VTy = E->getType()->getAsVectorType(); + QualType EltTy = VTy->getElementType(); + unsigned NElts = VTy->getNumElements(); + unsigned EltWidth = Info.Ctx.getTypeSize(EltTy); + const Expr* SE = E->getSubExpr(); QualType SETy = SE->getType(); APValue Result = APValue(); @@ -494,20 +499,62 @@ APValue VectorExprEvaluator::VisitCastExpr(const CastExpr* E) { return this->Visit(const_cast<Expr*>(SE)); } else if (SETy->isIntegerType()) { APSInt IntResult; - if (EvaluateInteger(SE, IntResult, Info)) - Result = APValue(IntResult); + if (!EvaluateInteger(SE, IntResult, Info)) + return APValue(); + Result = APValue(IntResult); } else if (SETy->isRealFloatingType()) { APFloat F(0.0); - if (EvaluateFloat(SE, F, Info)) - Result = APValue(F); + if (!EvaluateFloat(SE, F, Info)) + return APValue(); + Result = APValue(F); + } else + return APValue(); + + // For casts of a scalar to ExtVector, convert the scalar to the element type + // and splat it to all elements. + if (E->getType()->isExtVectorType()) { + if (EltTy->isIntegerType() && Result.isInt()) + Result = APValue(HandleIntToIntCast(EltTy, SETy, Result.getInt(), + Info.Ctx)); + else if (EltTy->isIntegerType()) + Result = APValue(HandleFloatToIntCast(EltTy, SETy, Result.getFloat(), + Info.Ctx)); + else if (EltTy->isRealFloatingType() && Result.isInt()) + Result = APValue(HandleIntToFloatCast(EltTy, SETy, Result.getInt(), + Info.Ctx)); + else if (EltTy->isRealFloatingType()) + Result = APValue(HandleFloatToFloatCast(EltTy, SETy, Result.getFloat(), + Info.Ctx)); + else + return APValue(); + + // Splat and create vector APValue. + llvm::SmallVector<APValue, 4> Elts(NElts, Result); + return APValue(&Elts[0], Elts.size()); } - if (Result.isInt() || Result.isFloat()) { - unsigned NumElts = E->getType()->getAsVectorType()->getNumElements(); - llvm::SmallVector<APValue, 4> Elts(NumElts, Result); - Result = APValue(&Elts[0], Elts.size()); + // For casts of a scalar to regular gcc-style vector type, bitcast the scalar + // to the vector. To construct the APValue vector initializer, bitcast the + // initializing value to an APInt, and shift out the bits pertaining to each + // element. + APSInt Init; + Init = Result.isInt() ? Result.getInt() : Result.getFloat().bitcastToAPInt(); + + llvm::SmallVector<APValue, 4> Elts; + for (unsigned i = 0; i != NElts; ++i) { + APSInt Tmp = Init; + Tmp.extOrTrunc(EltWidth); + + if (EltTy->isIntegerType()) + Elts.push_back(APValue(Tmp)); + else if (EltTy->isRealFloatingType()) + Elts.push_back(APValue(APFloat(Tmp))); + else + return APValue(); + + Init >>= EltWidth; } - return Result; + return APValue(&Elts[0], Elts.size()); } APValue diff --git a/lib/AST/NestedNameSpecifier.cpp b/lib/AST/NestedNameSpecifier.cpp index 09522a20863c..90ec4d33fdfe 100644 --- a/lib/AST/NestedNameSpecifier.cpp +++ b/lib/AST/NestedNameSpecifier.cpp @@ -153,8 +153,6 @@ void NestedNameSpecifier::Destroy(ASTContext &Context) { Context.Deallocate((void *)this); } -void NestedNameSpecifier::dump() { - PrintingPolicy Policy; - Policy.CPlusPlus = true; - print(llvm::errs(), Policy); +void NestedNameSpecifier::dump(const LangOptions &LO) { + print(llvm::errs(), PrintingPolicy(LO)); } diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index b24e912582d5..bc096bf0d9f3 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -41,7 +41,6 @@ namespace { const char *LastLocFilename; unsigned LastLocLine; - PrintingPolicy Policy; public: StmtDumper(SourceManager *sm, FILE *f, unsigned maxDepth) : SM(sm), F(f), IndentLevel(0-1), MaxDepth(maxDepth) { @@ -226,7 +225,8 @@ void StmtDumper::DumpDeclarator(Decl *D) { } std::string Name = VD->getNameAsString(); - VD->getType().getAsStringInternal(Name, Policy); + VD->getType().getAsStringInternal(Name, + PrintingPolicy(VD->getASTContext().getLangOptions())); fprintf(F, "%s", Name.c_str()); // If this is a vardecl with an initializer, emit it. diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index b300940824de..fec17fb22352 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -35,7 +35,7 @@ namespace { public: StmtPrinter(llvm::raw_ostream &os, ASTContext &C, PrinterHelper* helper, - const PrintingPolicy &Policy = PrintingPolicy(), + const PrintingPolicy &Policy, unsigned Indentation = 0) : OS(os), Context(C), IndentLevel(Indentation), Helper(helper), Policy(Policy) {} @@ -114,7 +114,7 @@ void StmtPrinter::PrintRawCompoundStmt(CompoundStmt *Node) { } void StmtPrinter::PrintRawDecl(Decl *D) { - D->print(OS, Context, Policy, IndentLevel); + D->print(OS, Policy, IndentLevel); } void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) { @@ -123,8 +123,7 @@ void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) { for ( ; Begin != End; ++Begin) Decls.push_back(*Begin); - Decl::printGroup(Decls.data(), Decls.size(), OS, Context, Policy, - IndentLevel); + Decl::printGroup(Decls.data(), Decls.size(), OS, Policy, IndentLevel); } void StmtPrinter::VisitNullStmt(NullStmt *Node) { @@ -491,6 +490,18 @@ void StmtPrinter::VisitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *Node) { OS << Node->getDeclName().getAsString(); } +void StmtPrinter::VisitTemplateIdRefExpr(TemplateIdRefExpr *Node) { + if (Node->getQualifier()) + Node->getQualifier()->print(OS, Policy); + Node->getTemplateName().print(OS, Policy, true); + OS << '<'; + OS << TemplateSpecializationType::PrintTemplateArgumentList( + Node->getTemplateArgs(), + Node->getNumTemplateArgs(), + Policy); + OS << '>'; +} + void StmtPrinter::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { if (Node->getBase()) { PrintExpr(Node->getBase()); @@ -861,7 +872,7 @@ void StmtPrinter::VisitDesignatedInitExpr(DesignatedInitExpr *Node) { } void StmtPrinter::VisitImplicitValueInitExpr(ImplicitValueInitExpr *Node) { - if (Policy.CPlusPlus) + if (Policy.LangOpts.CPlusPlus) OS << "/*implicit*/" << Node->getType().getAsString(Policy) << "()"; else { OS << "/*implicit*/(" << Node->getType().getAsString(Policy) << ")"; @@ -1216,7 +1227,8 @@ void StmtPrinter::VisitBlockDeclRefExpr(BlockDeclRefExpr *Node) { //===----------------------------------------------------------------------===// void Stmt::dumpPretty(ASTContext& Context) const { - printPretty(llvm::errs(), Context, 0, PrintingPolicy()); + printPretty(llvm::errs(), Context, 0, + PrintingPolicy(Context.getLangOptions())); } void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context, diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp index 3613da77b342..5b671c111fbf 100644 --- a/lib/AST/TemplateName.cpp +++ b/lib/AST/TemplateName.cpp @@ -15,6 +15,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" +#include "clang/Basic/LangOptions.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -59,7 +60,8 @@ TemplateName::print(llvm::raw_ostream &OS, const PrintingPolicy &Policy, } void TemplateName::dump() const { - PrintingPolicy Policy; - Policy.CPlusPlus = true; - print(llvm::errs(), Policy); + LangOptions LO; // FIXME! + LO.CPlusPlus = true; + LO.Bool = true; + print(llvm::errs(), PrintingPolicy(LO)); } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 41536612fec8..4e061a9fbe62 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -185,6 +185,12 @@ bool Type::isStructureType() const { return RT->getDecl()->isStruct(); return false; } +bool Type::isVoidPointerType() const { + if (const PointerType *PT = getAsPointerType()) + return PT->getPointeeType()->isVoidType(); + return false; +} + bool Type::isUnionType() const { if (const RecordType *RT = getAsRecordType()) return RT->getDecl()->isUnion(); @@ -938,11 +944,11 @@ bool Type::isSpecifierType() const { } } -const char *BuiltinType::getName(bool CPlusPlus) const { +const char *BuiltinType::getName(const LangOptions &LO) const { switch (getKind()) { default: assert(0 && "Unknown builtin type!"); case Void: return "void"; - case Bool: return CPlusPlus? "bool" : "_Bool"; + case Bool: return LO.Bool ? "bool" : "_Bool"; case Char_S: return "char"; case Char_U: return "char"; case SChar: return "signed char"; @@ -1160,9 +1166,9 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, //===----------------------------------------------------------------------===// void QualType::dump(const char *msg) const { - PrintingPolicy Policy; std::string R = "identifier"; - getAsStringInternal(R, Policy); + LangOptions LO; + getAsStringInternal(R, PrintingPolicy(LO)); if (msg) fprintf(stderr, "%s: %s\n", msg, R.c_str()); else @@ -1174,7 +1180,8 @@ void QualType::dump() const { void Type::dump() const { std::string S = "identifier"; - getAsStringInternal(S, PrintingPolicy()); + LangOptions LO; + getAsStringInternal(S, PrintingPolicy(LO)); fprintf(stderr, "%s\n", S.c_str()); } @@ -1193,7 +1200,8 @@ static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { std::string QualType::getAsString() const { std::string S; - getAsStringInternal(S, PrintingPolicy()); + LangOptions LO; + getAsStringInternal(S, PrintingPolicy(LO)); return S; } @@ -1224,11 +1232,11 @@ QualType::getAsStringInternal(std::string &S, void BuiltinType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { if (S.empty()) { - S = getName(Policy.CPlusPlus); + S = getName(Policy.LangOpts); } else { // Prefix the basic type, e.g. 'int X'. S = ' ' + S; - S = getName(Policy.CPlusPlus) + S; + S = getName(Policy.LangOpts) + S; } } @@ -1470,7 +1478,7 @@ void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy if (getNumArgs()) S += ", "; S += "..."; - } else if (getNumArgs() == 0 && !Policy.CPlusPlus) { + } else if (getNumArgs() == 0 && !Policy.LangOpts.CPlusPlus) { // Do not emit int() if we have a proto, emit 'int(void)'. S += "void"; } diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index 8fbce528fa9a..19d641ee9753 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -198,7 +198,7 @@ SVal BasicStoreManager::getLValueElement(const GRState *state, return Base; Loc BaseL = cast<Loc>(Base); - const TypedRegion* BaseR = 0; + const MemRegion* BaseR = 0; switch(BaseL.getSubKind()) { case loc::GotoLabelKind: @@ -216,17 +216,11 @@ SVal BasicStoreManager::getLValueElement(const GRState *state, return Base; } - - if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) { - BaseR = TR; + if (isa<TypedRegion>(R) || isa<SymbolicRegion>(R)) { + BaseR = R; break; } - if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) { - SymbolRef Sym = SR->getSymbol(); - BaseR = MRMgr.getTypedViewRegion(Sym->getType(getContext()), SR); - } - break; } @@ -242,9 +236,10 @@ SVal BasicStoreManager::getLValueElement(const GRState *state, return Base; } - if (BaseR) + if (BaseR) { return ValMgr.makeLoc(MRMgr.getElementRegion(elementType, UnknownVal(), BaseR, getContext())); + } else return UnknownVal(); } @@ -319,54 +314,50 @@ SVal BasicStoreManager::Retrieve(const GRState *state, Loc loc, QualType T) { } Store BasicStoreManager::BindInternal(Store store, Loc loc, SVal V) { - switch (loc.getSubKind()) { - case loc::MemRegionKind: { - const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion(); - ASTContext &C = StateMgr.getContext(); + if (isa<loc::ConcreteInt>(loc)) + return store; + + const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion(); + ASTContext &C = StateMgr.getContext(); - // Special case: handle store of pointer values (Loc) to pointers via - // a cast to intXX_t*, void*, etc. This is needed to handle - // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier. - if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V)) - if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { - // FIXME: Should check for index 0. - QualType T = ER->getLocationType(C); + // Special case: handle store of pointer values (Loc) to pointers via + // a cast to intXX_t*, void*, etc. This is needed to handle + // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier. + if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V)) + if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) { + // FIXME: Should check for index 0. + QualType T = ER->getLocationType(C); - if (isHigherOrderRawPtr(T, C)) - R = ER->getSuperRegion(); - } + if (isHigherOrderRawPtr(T, C)) + R = ER->getSuperRegion(); + } - if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R))) - return store; + if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R))) + return store; - // We only track bindings to self.ivar. - if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) - if (IVR->getSuperRegion() != SelfRegion) - return store; + // We only track bindings to self.ivar. + if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) + if (IVR->getSuperRegion() != SelfRegion) + return store; - if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) { - // Only convert 'V' to a location iff the underlying region type - // is a location as well. - // FIXME: We are allowing a store of an arbitrary location to - // a pointer. We may wish to flag a type error here if the types - // are incompatible. This may also cause lots of breakage - // elsewhere. Food for thought. - if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) { - if (TyR->isBoundable() && - Loc::IsLocType(TyR->getValueType(C))) - V = X->getLoc(); - } - } - - BindingsTy B = GetBindings(store); - return V.isUnknown() - ? VBFactory.Remove(B, R).getRoot() - : VBFactory.Add(B, R, V).getRoot(); + if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) { + // Only convert 'V' to a location iff the underlying region type + // is a location as well. + // FIXME: We are allowing a store of an arbitrary location to + // a pointer. We may wish to flag a type error here if the types + // are incompatible. This may also cause lots of breakage + // elsewhere. Food for thought. + if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) { + if (TyR->isBoundable() && + Loc::IsLocType(TyR->getValueType(C))) + V = X->getLoc(); } - default: - assert ("SetSVal for given Loc type not yet implemented."); - return store; } + + BindingsTy B = GetBindings(store); + return V.isUnknown() + ? VBFactory.Remove(B, R).getRoot() + : VBFactory.Add(B, R, V).getRoot(); } Store BasicStoreManager::Remove(Store store, Loc loc) { @@ -521,7 +512,7 @@ Store BasicStoreManager::getInitialStore() { // Scan the method for ivar references. While this requires an // entire AST scan, the cost should not be high in practice. - St = scanForIvars(MD->getBody(getContext()), PD, St); + St = scanForIvars(MD->getBody(), PD, St); } } } @@ -537,10 +528,9 @@ Store BasicStoreManager::getInitialStore() { // Initialize globals and parameters to symbolic values. // Initialize local variables to undefined. const MemRegion *R = ValMgr.getRegionManager().getVarRegion(VD); - SVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) || - isa<ImplicitParamDecl>(VD)) - ? ValMgr.getRegionValueSymbolVal(R) - : UndefinedVal(); + SVal X = R->hasGlobalsOrParametersStorage() + ? ValMgr.getRegionValueSymbolVal(R) + : UndefinedVal(); St = BindInternal(St, ValMgr.makeLoc(R), X); } @@ -594,7 +584,7 @@ Store BasicStoreManager::BindDeclInternal(Store store, const VarDecl* VD, } else { // Process local scalar variables. QualType T = VD->getType(); - if (Loc::IsLocType(T) || T->isIntegerType()) { + if (ValMgr.getSymbolManager().canSymbolicate(T)) { SVal V = InitVal ? *InitVal : UndefinedVal(); store = BindInternal(store, getLoc(VD), V); } diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index 38ea458a6599..3db96ca9eacb 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -146,7 +146,7 @@ public: ParentMap& getParentMap() { if (PM.get() == 0) - PM.reset(new ParentMap(getCodeDecl().getBody(getASTContext()))); + PM.reset(new ParentMap(getCodeDecl().getBody())); return *PM.get(); } @@ -182,8 +182,7 @@ PathDiagnosticBuilder::ExecutionContinues(const ExplodedNode<GRState>* N) { if (Stmt *S = GetNextStmt(N)) return PathDiagnosticLocation(S, getSourceManager()); - return FullSourceLoc(getCodeDecl().getBodyRBrace(getASTContext()), - getSourceManager()); + return FullSourceLoc(getCodeDecl().getBodyRBrace(), getSourceManager()); } PathDiagnosticLocation @@ -893,7 +892,7 @@ public: // statement (if it doesn't already exist). // FIXME: Should handle CXXTryStmt if analyser starts supporting C++. if (const CompoundStmt *CS = - PDB.getCodeDecl().getCompoundBody(PDB.getASTContext())) + PDB.getCodeDecl().getCompoundBody()) if (!CS->body_empty()) { SourceLocation Loc = (*CS->body_begin())->getLocStart(); rawAddEdge(PathDiagnosticLocation(Loc, PDB.getSourceManager())); diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index f4a28e0c19fd..3cca482633ca 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -156,13 +156,13 @@ static bool followsFundamentalRule(Selector S) { } static const ObjCMethodDecl* -ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD, ASTContext &Context) { +ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD) { ObjCInterfaceDecl *ID = const_cast<ObjCInterfaceDecl*>(MD->getClassInterface()); return MD->isInstanceMethod() - ? ID->lookupInstanceMethod(Context, MD->getSelector()) - : ID->lookupClassMethod(Context, MD->getSelector()); + ? ID->lookupInstanceMethod(MD->getSelector()) + : ID->lookupClassMethod(MD->getSelector()); } namespace { @@ -827,8 +827,7 @@ public: QualType ResultTy = MD->getResultType(); // Resolve the method decl last. - if (const ObjCMethodDecl *InterfaceMD = - ResolveToInterfaceMethodDecl(MD, Ctx)) + if (const ObjCMethodDecl *InterfaceMD = ResolveToInterfaceMethodDecl(MD)) MD = InterfaceMD; if (MD->isInstanceMethod()) @@ -1248,15 +1247,15 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, // Determine if there is a special return effect for this method. if (isTrackedObjCObjectType(RetTy)) { - if (FD->getAttr<NSReturnsRetainedAttr>(Ctx)) { + if (FD->getAttr<NSReturnsRetainedAttr>()) { Summ.setRetEffect(ObjCAllocRetE); } - else if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) { + else if (FD->getAttr<CFReturnsRetainedAttr>()) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } else if (RetTy->getAsPointerType()) { - if (FD->getAttr<CFReturnsRetainedAttr>(Ctx)) { + if (FD->getAttr<CFReturnsRetainedAttr>()) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } @@ -1270,10 +1269,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, // Determine if there is a special return effect for this method. if (isTrackedObjCObjectType(MD->getResultType())) { - if (MD->getAttr<NSReturnsRetainedAttr>(Ctx)) { + if (MD->getAttr<NSReturnsRetainedAttr>()) { Summ.setRetEffect(ObjCAllocRetE); } - else if (MD->getAttr<CFReturnsRetainedAttr>(Ctx)) { + else if (MD->getAttr<CFReturnsRetainedAttr>()) { Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); } } @@ -2632,7 +2631,7 @@ CFRefLeakReport::getEndPath(BugReporterContext& BRC, if (!L.isValid()) { const Decl &D = BRC.getCodeDecl(); - L = PathDiagnosticLocation(D.getBodyRBrace(BRC.getASTContext()), SMgr); + L = PathDiagnosticLocation(D.getBodyRBrace(), SMgr); } std::string sbuf; @@ -2796,7 +2795,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, // to identify conjured symbols by an expression pair: the enclosing // expression (the context) and the expression itself. This should // disambiguate conjured symbols. - + unsigned Count = Builder.getCurrentBlockCount(); const TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion()); if (R) { @@ -2833,7 +2832,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, if (R->isBoundable()) { // Set the value of the variable to be a conjured symbol. - unsigned Count = Builder.getCurrentBlockCount(); + QualType T = R->getValueType(Ctx); if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())){ @@ -2857,20 +2856,31 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, state->getStateManager().getRegionManager(); // Iterate through the fields and construct new symbols. - for (RecordDecl::field_iterator FI=RD->field_begin(Ctx), - FE=RD->field_end(Ctx); FI!=FE; ++FI) { + for (RecordDecl::field_iterator FI=RD->field_begin(), + FE=RD->field_end(); FI!=FE; ++FI) { // For now just handle scalar fields. FieldDecl *FD = *FI; QualType FT = FD->getType(); - + const FieldRegion* FR = MRMgr.getFieldRegion(FD, R); + if (Loc::IsLocType(FT) || (FT->isIntegerType() && FT->isScalarType())) { - const FieldRegion* FR = MRMgr.getFieldRegion(FD, R); - SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count); state = state->bindLoc(ValMgr.makeLoc(FR), V); - } + } + else if (FT->isStructureType()) { + // set the default value of the struct field to conjured + // symbol. Note that the type of the symbol is irrelavant. + // We cannot use the type of the struct otherwise ValMgr won't + // give us the conjured symbol. + StoreManager& StoreMgr = + Eng.getStateManager().getStoreManager(); + SVal V = ValMgr.getConjuredSymbolVal(*I, + Eng.getContext().IntTy, + Count); + state = StoreMgr.setDefaultValue(state, FR, V); + } } } else if (const ArrayType *AT = Ctx.getAsArrayType(T)) { // Set the default value of the array to conjured symbol. @@ -2884,6 +2894,15 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst, } } } + else if (isa<AllocaRegion>(MR->getRegion())) { + // Invalidate the alloca region by setting its default value to + // conjured symbol. The type of the symbol is irrelavant. + SVal V = ValMgr.getConjuredSymbolVal(*I, Eng.getContext().IntTy, + Count); + StoreManager& StoreMgr = + Eng.getStateManager().getStoreManager(); + state = StoreMgr.setDefaultValue(state, MR->getRegion(), V); + } else state = state->bindLoc(*MR, UnknownVal()); } diff --git a/lib/Analysis/CheckDeadStores.cpp b/lib/Analysis/CheckDeadStores.cpp index 0f61a5ee916a..69433d6396a5 100644 --- a/lib/Analysis/CheckDeadStores.cpp +++ b/lib/Analysis/CheckDeadStores.cpp @@ -85,7 +85,7 @@ public: const LiveVariables::AnalysisDataTy& AD, const LiveVariables::ValTy& Live) { - if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>(Ctx)) + if (VD->hasLocalStorage() && !Live(VD, AD) && !VD->getAttr<UnusedAttr>()) Report(VD, dsk, Ex->getSourceRange().getBegin(), Val->getSourceRange()); } @@ -190,7 +190,7 @@ public: // A dead initialization is a variable that is dead after it // is initialized. We don't flag warnings for those variables // marked 'unused'. - if (!Live(V, AD) && V->getAttr<UnusedAttr>(Ctx) == 0) { + if (!Live(V, AD) && V->getAttr<UnusedAttr>() == 0) { // Special case: check for initializations with constants. // // e.g. : int x = 0; diff --git a/lib/Analysis/CheckObjCDealloc.cpp b/lib/Analysis/CheckObjCDealloc.cpp index 2ba7d868e90b..a14ae265128b 100644 --- a/lib/Analysis/CheckObjCDealloc.cpp +++ b/lib/Analysis/CheckObjCDealloc.cpp @@ -109,7 +109,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, QualType T = ID->getType(); if (!Ctx.isObjCObjectPointerType(T) || - ID->getAttr<IBOutletAttr>(Ctx)) // Skip IBOutlets. + ID->getAttr<IBOutletAttr>()) // Skip IBOutlets. continue; containsPointerIvar = true; @@ -147,8 +147,8 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, ObjCMethodDecl* MD = 0; // Scan the instance methods for "dealloc". - for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(Ctx), - E = D->instmeth_end(Ctx); I!=E; ++I) { + for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(), + E = D->instmeth_end(); I!=E; ++I) { if ((*I)->getSelector() == S) { MD = *I; @@ -172,7 +172,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, } // dealloc found. Scan for missing [super dealloc]. - if (MD->getBody(Ctx) && !scan_dealloc(MD->getBody(Ctx), S)) { + if (MD->getBody() && !scan_dealloc(MD->getBody(), S)) { const char* name = LOpts.getGCMode() == LangOptions::NonGC ? "missing [super dealloc]" @@ -198,8 +198,8 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, // Scan for missing and extra releases of ivars used by implementations // of synthesized properties - for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(Ctx), - E = D->propimpl_end(Ctx); I!=E; ++I) { + for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(), + E = D->propimpl_end(); I!=E; ++I) { // We can only check the synthesized properties if((*I)->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize) @@ -223,7 +223,7 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, // ivar must be released if and only if the kind of setter was not 'assign' bool requiresRelease = PD->getSetterKind() != ObjCPropertyDecl::Assign; - if(scan_ivar_release(MD->getBody(Ctx), ID, PD, RS, SelfII, Ctx) + if(scan_ivar_release(MD->getBody(), ID, PD, RS, SelfII, Ctx) != requiresRelease) { const char *name; const char* category = "Memory (Core Foundation/Objective-C)"; diff --git a/lib/Analysis/CheckObjCInstMethSignature.cpp b/lib/Analysis/CheckObjCInstMethSignature.cpp index 9fec7c1dc111..28814867bd58 100644 --- a/lib/Analysis/CheckObjCInstMethSignature.cpp +++ b/lib/Analysis/CheckObjCInstMethSignature.cpp @@ -86,8 +86,8 @@ void clang::CheckObjCInstMethSignature(ObjCImplementationDecl* ID, MapTy IMeths; unsigned NumMethods = 0; - for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(Ctx), - E=ID->instmeth_end(Ctx); I!=E; ++I) { + for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(), + E=ID->instmeth_end(); I!=E; ++I) { ObjCMethodDecl* M = *I; IMeths[M->getSelector()] = M; @@ -97,8 +97,8 @@ void clang::CheckObjCInstMethSignature(ObjCImplementationDecl* ID, // Now recurse the class hierarchy chain looking for methods with the // same signatures. while (C && NumMethods) { - for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(Ctx), - E=C->instmeth_end(Ctx); I!=E; ++I) { + for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(), + E=C->instmeth_end(); I!=E; ++I) { ObjCMethodDecl* M = *I; Selector S = M->getSelector(); diff --git a/lib/Analysis/CheckObjCUnusedIVars.cpp b/lib/Analysis/CheckObjCUnusedIVars.cpp index 21dc658dfa1a..0063c40482a0 100644 --- a/lib/Analysis/CheckObjCUnusedIVars.cpp +++ b/lib/Analysis/CheckObjCUnusedIVars.cpp @@ -59,9 +59,6 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { ObjCInterfaceDecl* ID = D->getClassInterface(); IvarUsageMap M; - - ASTContext &Ctx = BR.getContext(); - // Iterate over the ivars. for (ObjCInterfaceDecl::ivar_iterator I=ID->ivar_begin(), E=ID->ivar_end(); I!=E; ++I) { @@ -73,7 +70,7 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { continue; // Skip IB Outlets. - if (ID->getAttr<IBOutletAttr>(Ctx)) + if (ID->getAttr<IBOutletAttr>()) continue; M[ID] = Unused; @@ -83,14 +80,14 @@ void clang::CheckObjCUnusedIvar(ObjCImplementationDecl* D, BugReporter& BR) { return; // Now scan the methods for accesses. - for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(Ctx), - E = D->instmeth_end(Ctx); I!=E; ++I) - Scan(M, (*I)->getBody(Ctx)); + for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(), + E = D->instmeth_end(); I!=E; ++I) + Scan(M, (*I)->getBody()); // Scan for @synthesized property methods that act as setters/getters // to an ivar. - for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(Ctx), - E = D->propimpl_end(Ctx); I!=E; ++I) + for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(), + E = D->propimpl_end(); I!=E; ++I) Scan(M, *I); // Find ivars that are unused. diff --git a/lib/Analysis/Environment.cpp b/lib/Analysis/Environment.cpp index 2b751df830c2..3f8f14dcb0b4 100644 --- a/lib/Analysis/Environment.cpp +++ b/lib/Analysis/Environment.cpp @@ -143,8 +143,19 @@ EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc, SVal X = I.getData(); // If the block expr's value is a memory region, then mark that region. - if (isa<loc::MemRegionVal>(X)) - DRoots.push_back(cast<loc::MemRegionVal>(X).getRegion()); + if (isa<loc::MemRegionVal>(X)) { + const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); + DRoots.push_back(R); + // Mark the super region of the RX as live. + // e.g.: int x; char *y = (char*) &x; if (*y) ... + // 'y' => element region. 'x' is its super region. + // We only add one level super region for now. + + // FIXME: maybe multiple level of super regions should be added. + if (const SubRegion *SR = dyn_cast<SubRegion>(R)) { + DRoots.push_back(SR->getSuperRegion()); + } + } // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 8b4f5c8f11c1..d9117f5930e6 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1437,8 +1437,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, NodeTy* Pred, SaveAndRestore<bool> OldSink(Builder->BuildSinks); const FunctionDecl* FD = L.getAsFunctionDecl(); if (FD) { - if (FD->getAttr<NoReturnAttr>(getContext()) || - FD->getAttr<AnalyzerNoReturnAttr>(getContext())) + if (FD->getAttr<NoReturnAttr>() || + FD->getAttr<AnalyzerNoReturnAttr>()) Builder->BuildSinks = true; else { // HACK: Some functions are not marked noreturn, and don't return. @@ -3154,7 +3154,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : SourceLocation SLoc = S->getLocStart(); Out << S->getStmtClassName() << ' ' << (void*) S << ' '; - S->printPretty(Out); + LangOptions LO; // FIXME. + S->printPretty(Out, 0, PrintingPolicy(LO)); if (SLoc.isFileID()) { Out << "\\lline=" @@ -3208,7 +3209,8 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : SourceLocation SLoc = T->getLocStart(); Out << "\\|Terminator: "; - E.getSrc()->printTerminator(Out); + LangOptions LO; // FIXME. + E.getSrc()->printTerminator(Out, LO); if (SLoc.isFileID()) { Out << "\\lline=" @@ -3223,11 +3225,12 @@ struct VISIBILITY_HIDDEN DOTGraphTraits<GRExprEngine::NodeTy*> : if (Label) { if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) { Out << "\\lcase "; - C->getLHS()->printPretty(Out); + LangOptions LO; // FIXME. + C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO)); if (Stmt* RHS = C->getRHS()) { Out << " .. "; - RHS->printPretty(Out); + RHS->printPretty(Out, 0, PrintingPolicy(LO)); } Out << ":"; diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp index 76d26dd9f02a..a2ce79a2f390 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -566,7 +566,7 @@ public: if (!FD) return false; - const NonNullAttr* Att = FD->getAttr<NonNullAttr>(BR.getContext()); + const NonNullAttr* Att = FD->getAttr<NonNullAttr>(); if (!Att) return false; diff --git a/lib/Analysis/GRState.cpp b/lib/Analysis/GRState.cpp index 493edc37bacb..54c0afbff33e 100644 --- a/lib/Analysis/GRState.cpp +++ b/lib/Analysis/GRState.cpp @@ -166,7 +166,8 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl, else { Out << nl; } Out << " (" << (void*) I.getKey() << ") "; - I.getKey()->printPretty(Out); + LangOptions LO; // FIXME. + I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : "; I.getData().print(Out); } @@ -183,7 +184,8 @@ void GRState::print(llvm::raw_ostream& Out, const char* nl, else { Out << nl; } Out << " (" << (void*) I.getKey() << ") "; - I.getKey()->printPretty(Out); + LangOptions LO; // FIXME. + I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : "; I.getData().print(Out); } diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index b0eb37b06524..aead7f43ad8f 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/lib/Analysis/LiveVariables.cpp @@ -135,9 +135,10 @@ void TransferFuncs::Visit(Stmt *S) { StmtVisitor<TransferFuncs,void>::Visit(S); } - else + else { // For block-level expressions, mark that they are live. LiveState(S,AD) = Alive; + } } void TransferFuncs::VisitTerminator(CFGBlock* B) { diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp index c8e027579a30..45305403585a 100644 --- a/lib/Analysis/MemRegion.cpp +++ b/lib/Analysis/MemRegion.cpp @@ -143,6 +143,10 @@ void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { // Region pretty-printing. //===----------------------------------------------------------------------===// +void MemRegion::printStdErr() const { + print(llvm::errs()); +} + std::string MemRegion::getString() const { std::string s; llvm::raw_string_ostream os(s); @@ -184,7 +188,8 @@ void FieldRegion::print(llvm::raw_ostream& os) const { } void StringRegion::print(llvm::raw_ostream& os) const { - Str->printPretty(os); + LangOptions LO; // FIXME. + Str->printPretty(os, 0, PrintingPolicy(LO)); } void SymbolicRegion::print(llvm::raw_ostream& os) const { @@ -218,6 +223,10 @@ MemSpaceRegion* MemRegionManager::getStackRegion() { return LazyAllocate(stack); } +MemSpaceRegion* MemRegionManager::getStackArgumentsRegion() { + return LazyAllocate(stackArguments); +} + MemSpaceRegion* MemRegionManager::getGlobalsRegion() { return LazyAllocate(globals); } @@ -327,8 +336,10 @@ const MemSpaceRegion *MemRegion::getMemorySpace() const { } bool MemRegion::hasStackStorage() const { - if (const MemSpaceRegion *MS = getMemorySpace()) - return MS == getMemRegionManager()->getStackRegion(); + if (const MemSpaceRegion *MS = getMemorySpace()) { + MemRegionManager *Mgr = getMemRegionManager(); + return MS == Mgr->getStackRegion() || MS == Mgr->getStackArgumentsRegion(); + } return false; } @@ -343,10 +354,35 @@ bool MemRegion::hasHeapStorage() const { bool MemRegion::hasHeapOrStackStorage() const { if (const MemSpaceRegion *MS = getMemorySpace()) { MemRegionManager *Mgr = getMemRegionManager(); - return MS == Mgr->getHeapRegion() || MS == Mgr->getStackRegion(); + return MS == Mgr->getHeapRegion() + || MS == Mgr->getStackRegion() + || MS == Mgr->getStackArgumentsRegion(); } return false; -} +} + +bool MemRegion::hasGlobalsStorage() const { + if (const MemSpaceRegion *MS = getMemorySpace()) + return MS == getMemRegionManager()->getGlobalsRegion(); + + return false; +} + +bool MemRegion::hasParametersStorage() const { + if (const MemSpaceRegion *MS = getMemorySpace()) + return MS == getMemRegionManager()->getStackArgumentsRegion(); + + return false; +} + +bool MemRegion::hasGlobalsOrParametersStorage() const { + if (const MemSpaceRegion *MS = getMemorySpace()) { + MemRegionManager *Mgr = getMemRegionManager(); + return MS == Mgr->getGlobalsRegion() + || MS == Mgr->getStackArgumentsRegion(); + } + return false; +} //===----------------------------------------------------------------------===// // View handling. diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index d45048de1a42..23e8b738b601 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -347,9 +347,6 @@ public: // FIXME: Remove. ASTContext& getContext() { return StateMgr.getContext(); } - - // FIXME: Use ValueManager? - SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); } }; } // end anonymous namespace @@ -822,12 +819,6 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { const TypedRegion *R = cast<TypedRegion>(MR); assert(R && "bad region"); - if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) - return RetrieveField(state, FR); - - if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) - return RetrieveElement(state, ER); - // FIXME: We should eventually handle funny addressing. e.g.: // // int x = ...; @@ -848,6 +839,12 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { // FIXME: handle Vector types. if (RTy->isVectorType()) return UnknownVal(); + + if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) + return RetrieveField(state, FR); + + if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) + return RetrieveElement(state, ER); RegionBindingsTy B = GetRegionBindings(state->getStore()); RegionBindingsTy::data_type* V = B.lookup(R); @@ -882,14 +879,8 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { if (VD == SelfDecl) return loc::MemRegionVal(getSelfRegion(0)); - if (isa<ParmVarDecl>(VD) || isa<ImplicitParamDecl>(VD) || - VD->hasGlobalStorage()) { - QualType VTy = VD->getType(); - if (Loc::IsLocType(VTy) || VTy->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(VR); - else - return UnknownVal(); - } + if (VR->hasGlobalsOrParametersStorage()) + return ValMgr.getRegionValueSymbolValOrUnknown(VR, VD->getType()); } if (R->hasHeapOrStackStorage()) { @@ -907,23 +898,21 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { RTy = T->getAsPointerType()->getPointeeType(); } - // All other integer values are symbolic. - if (Loc::IsLocType(RTy) || RTy->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(R, RTy); - else - return UnknownVal(); + // All other values are symbolic. + return ValMgr.getRegionValueSymbolValOrUnknown(R, RTy); } SVal RegionStoreManager::RetrieveElement(const GRState* state, const ElementRegion* R) { // Check if the region has a binding. RegionBindingsTy B = GetRegionBindings(state->getStore()); - const SVal* V = B.lookup(R); - if (V) + if (const SVal* V = B.lookup(R)) return *V; + const MemRegion* superR = R->getSuperRegion(); + // Check if the region is an element region of a string literal. - if (const StringRegion *StrR=dyn_cast<StringRegion>(R->getSuperRegion())) { + if (const StringRegion *StrR=dyn_cast<StringRegion>(superR)) { const StringLiteral *Str = StrR->getStringLiteral(); SVal Idx = R->getIndex(); if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Idx)) { @@ -937,18 +926,38 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state, } } - const MemRegion* SuperR = R->getSuperRegion(); - const SVal* D = state->get<RegionDefaultValue>(SuperR); - - if (D) { + // Check if the super region has a default value. + if (const SVal *D = state->get<RegionDefaultValue>(superR)) { if (D->hasConjuredSymbol()) return ValMgr.getRegionValueSymbolVal(R); else return *D; } - if (R->hasHeapOrStackStorage()) + // Check if the super region has a binding. + if (B.lookup(superR)) { + // We do not extract the bit value from super region for now. + return UnknownVal(); + } + + if (R->hasHeapStorage()) { + // FIXME: If the region has heap storage and we know nothing special + // about its bindings, should we instead return UnknownVal? Seems like + // we should only return UndefinedVal in the cases where we know the value + // will be undefined. return UndefinedVal(); + } + + if (R->hasStackStorage() && !R->hasParametersStorage()) { + // Currently we don't reason specially about Clang-style vectors. Check + // if superR is a vector and if so return Unknown. + if (const TypedRegion *typedSuperR = dyn_cast<TypedRegion>(superR)) { + if (typedSuperR->getValueType(getContext())->isVectorType()) + return UnknownVal(); + } + + return UndefinedVal(); + } QualType Ty = R->getValueType(getContext()); @@ -957,10 +966,7 @@ SVal RegionStoreManager::RetrieveElement(const GRState* state, if (const QualType *p = state->get<RegionCasts>(R)) Ty = (*p)->getAsPointerType()->getPointeeType(); - if (Loc::IsLocType(Ty) || Ty->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(R, Ty); - else - return UnknownVal(); + return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty); } SVal RegionStoreManager::RetrieveField(const GRState* state, @@ -969,13 +975,11 @@ SVal RegionStoreManager::RetrieveField(const GRState* state, // Check if the region has a binding. RegionBindingsTy B = GetRegionBindings(state->getStore()); - const SVal* V = B.lookup(R); - if (V) + if (const SVal* V = B.lookup(R)) return *V; - const MemRegion* SuperR = R->getSuperRegion(); - const SVal* D = state->get<RegionDefaultValue>(SuperR); - if (D) { + const MemRegion* superR = R->getSuperRegion(); + if (const SVal* D = state->get<RegionDefaultValue>(superR)) { if (D->hasConjuredSymbol()) return ValMgr.getRegionValueSymbolVal(R); @@ -988,7 +992,11 @@ SVal RegionStoreManager::RetrieveField(const GRState* state, assert(0 && "Unknown default value"); } - if (R->hasHeapOrStackStorage()) + // FIXME: Is this correct? Should it be UnknownVal? + if (R->hasHeapStorage()) + return UndefinedVal(); + + if (R->hasStackStorage() && !R->hasParametersStorage()) return UndefinedVal(); // If the region is already cast to another type, use that type to create the @@ -998,11 +1006,8 @@ SVal RegionStoreManager::RetrieveField(const GRState* state, Ty = tmp->getAsPointerType()->getPointeeType(); } - // All other integer values are symbolic. - if (Loc::IsLocType(Ty) || Ty->isIntegerType()) - return ValMgr.getRegionValueSymbolVal(R, Ty); - else - return UnknownVal(); + // All other values are symbolic. + return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty); } SVal RegionStoreManager::RetrieveStruct(const GRState *state, @@ -1018,8 +1023,7 @@ SVal RegionStoreManager::RetrieveStruct(const GRState *state, // FIXME: We shouldn't use a std::vector. If RecordDecl doesn't have a // reverse iterator, we should implement one. - std::vector<FieldDecl *> Fields(RD->field_begin(getContext()), - RD->field_end(getContext())); + std::vector<FieldDecl *> Fields(RD->field_begin(), RD->field_end()); for (std::vector<FieldDecl *>::reverse_iterator Field = Fields.rbegin(), FieldEnd = Fields.rend(); @@ -1074,6 +1078,9 @@ Store RegionStoreManager::Remove(Store store, Loc L) { } const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) { + if (isa<loc::ConcreteInt>(L)) + return state; + // If we get here, the location should be a region. const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion(); @@ -1204,8 +1211,7 @@ RegionStoreManager::BindStruct(const GRState *state, const TypedRegion* R, RecordDecl::field_iterator FI, FE; - for (FI = RD->field_begin(getContext()), FE = RD->field_end(getContext()); - FI != FE; ++FI, ++VI) { + for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI, ++VI) { if (VI == VE) break; @@ -1357,8 +1363,9 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, IntermediateRoots.pop_back(); if (const VarRegion* VR = dyn_cast<VarRegion>(R)) { - if (SymReaper.isLive(Loc, VR->getDecl())) + if (SymReaper.isLive(Loc, VR->getDecl())) { RegionRoots.push_back(VR); // This is a live "root". + } } else if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) { if (SymReaper.isLive(SR->getSymbol())) @@ -1366,19 +1373,19 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, } else { // Get the super region for R. - const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion(); + const MemRegion* superR = cast<SubRegion>(R)->getSuperRegion(); // Get the current set of subregions for SuperR. - const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR); + const SubRegionsTy* SRptr = SubRegMap.lookup(superR); SubRegionsTy SRs = SRptr ? *SRptr : SubRegF.GetEmptySet(); // Add R to the subregions of SuperR. - SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SRs, R)); + SubRegMap = SubRegMapF.Add(SubRegMap, superR, SubRegF.Add(SRs, R)); // Super region may be VarRegion or subregion of another VarRegion. Add it // to the work list. - if (isa<SubRegion>(SuperR)) - IntermediateRoots.push_back(SuperR); + if (isa<SubRegion>(superR)) + IntermediateRoots.push_back(superR); } } @@ -1409,9 +1416,19 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, SVal X = *Xptr; UpdateLiveSymbols(X, SymReaper); // Update the set of live symbols. - // If X is a region, then add it the RegionRoots. - if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X)) - RegionRoots.push_back(RegionX->getRegion()); + // If X is a region, then add it to the RegionRoots. + if (const MemRegion *RX = X.getAsRegion()) { + RegionRoots.push_back(RX); + + // Mark the super region of the RX as live. + // e.g.: int x; char *y = (char*) &x; if (*y) ... + // 'y' => element region. 'x' is its super region. + // We only add one level super region for now. + // FIXME: maybe multiple level of super regions should be added. + if (const SubRegion *SR = dyn_cast<SubRegion>(RX)) { + RegionRoots.push_back(SR->getSuperRegion()); + } + } } // Get the subregions of R. These are RegionRoots as well since they @@ -1422,6 +1439,7 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, for (SubRegionsTy::iterator I=SR.begin(), E=SR.end(); I!=E; ++I) RegionRoots.push_back(*I); + } // We have now scanned the store, marking reachable regions and symbols @@ -1429,7 +1447,6 @@ Store RegionStoreManager::RemoveDeadBindings(const GRState *state, Stmt* Loc, // as well as update DSymbols with the set symbols that are now dead. for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { const MemRegion* R = I.getKey(); - // If this region live? Is so, none of its symbols are dead. if (Marked.count(R)) continue; diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp index 7d1850d73095..d711ce0a225e 100644 --- a/lib/Analysis/SVals.cpp +++ b/lib/Analysis/SVals.cpp @@ -114,6 +114,13 @@ const SymExpr *SVal::getAsSymbolicExpression() const { return getAsSymbol(); } +const MemRegion *SVal::getAsRegion() const { + if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) + return X->getRegion(); + + return 0; +} + bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const { return itr == X.itr; } diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp index 5aa756e14be3..cb099862f055 100644 --- a/lib/Analysis/Store.cpp +++ b/lib/Analysis/Store.cpp @@ -88,10 +88,10 @@ StoreManager::CastRegion(const GRState* state, const MemRegion* R, // If the super region is an element region, strip it away. // FIXME: Is this the right thing to do in all cases? - const TypedRegion *Base = isa<ElementRegion>(TR) ? - cast<TypedRegion>(TR->getSuperRegion()) : TR; + const MemRegion *Base = isa<ElementRegion>(TR) ? TR->getSuperRegion() + : TR; ElementRegion* ER = MRMgr.getElementRegion(Pointee, Idx, Base, - StateMgr.getContext()); + StateMgr.getContext()); return CastResult(state, ER); } } diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index d13ffa38213e..3810c49f71f3 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -89,7 +89,7 @@ static void AddKeyword(const char *Keyword, unsigned KWLen, else if (LangOpts.C99 && (Flags & KEYC99)) AddResult = 2; else if (LangOpts.GNUMode && (Flags & KEYGNU)) AddResult = 1; else if (LangOpts.Microsoft && (Flags & KEYMS)) AddResult = 1; - else if (LangOpts.OpenCL && (Flags & BOOLSUPPORT)) AddResult = 2; + else if (LangOpts.Bool && (Flags & BOOLSUPPORT)) AddResult = 2; // Don't add this keyword if disabled in this language. if (AddResult == 0) return; diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index a513cb16886e..ba7f190408b2 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -41,6 +41,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) { UIntMaxType = UnsignedLongLong; IntPtrType = SignedLong; WCharType = SignedInt; + Int64Type = SignedLongLong; FloatFormat = &llvm::APFloat::IEEEsingle; DoubleFormat = &llvm::APFloat::IEEEdouble; LongDoubleFormat = &llvm::APFloat::IEEEdouble; diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 9910e28fcda9..3f7d9a31c61e 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -61,55 +61,24 @@ static void DefineStd(std::vector<char> &Buf, const char *MacroName, //===----------------------------------------------------------------------===// // Defines specific to certain operating systems. //===----------------------------------------------------------------------===// - -static void getSolarisDefines(const LangOptions &Opts, std::vector<char> &Defs) { - DefineStd(Defs, "sun", Opts); - DefineStd(Defs, "unix", Opts); - Define(Defs, "__ELF__"); - Define(Defs, "__svr4__"); - Define(Defs, "__SVR4"); -} - -static void getFreeBSDDefines(const LangOptions &Opts, bool is64Bit, - const char *Triple, std::vector<char> &Defs) { - // FreeBSD defines; list based off of gcc output - - const char *FreeBSD = strstr(Triple, "-freebsd"); - FreeBSD += strlen("-freebsd"); - char release[] = "X"; - release[0] = FreeBSD[0]; - char version[] = "X00001"; - version[0] = FreeBSD[0]; - - Define(Defs, "__FreeBSD__", release); - Define(Defs, "__FreeBSD_cc_version", version); - Define(Defs, "__KPRINTF_ATTRIBUTE__"); - DefineStd(Defs, "unix", Opts); - Define(Defs, "__ELF__", "1"); - if (is64Bit) { - Define(Defs, "__LP64__"); +namespace { +template<typename TgtInfo> +class OSTargetInfo : public TgtInfo { +protected: + virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + std::vector<char> &Defines) const=0; +public: + OSTargetInfo(const std::string& triple) : TgtInfo(triple) {} + virtual void getTargetDefines(const LangOptions &Opts, + std::vector<char> &Defines) const { + TgtInfo::getTargetDefines(Opts, Defines); + getOSDefines(Opts, TgtInfo::getTargetTriple(), Defines); } -} - -static void getDragonFlyDefines(const LangOptions &Opts, - std::vector<char> &Defs) { - // DragonFly defines; list based off of gcc output - Define(Defs, "__DragonFly__"); - Define(Defs, "__DragonFly_cc_version", "100001"); - Define(Defs, "__ELF__"); - Define(Defs, "__KPRINTF_ATTRIBUTE__"); - Define(Defs, "__tune_i386__"); - DefineStd(Defs, "unix", Opts); -} -static void getLinuxDefines(const LangOptions &Opts, std::vector<char> &Defs) { - // Linux defines; list based off of gcc output - DefineStd(Defs, "unix", Opts); - DefineStd(Defs, "linux", Opts); - Define(Defs, "__gnu_linux__"); - Define(Defs, "__ELF__", "1"); +}; } +namespace { /// getDarwinNumber - Parse the 'darwin number' out of the specific targe /// triple. For example, if we have darwin8.5 return 8,5,0. If any entry is /// not defined, return 0's. Return true if we have -darwin in the string or @@ -235,15 +204,160 @@ static void GetDarwinLanguageOptions(LangOptions &Opts, if (!getDarwinNumber(Triple, Maj, Min, Rev)) return; - // Blocks default to on for 10.6 (darwin10) and beyond. - // As does nonfragile-abi for 64bit mode - if (Maj > 9) + // Blocks and stack protectors default to on for 10.6 (darwin10) and beyond. + if (Maj > 9) { Opts.Blocks = 1; + Opts.setStackProtectorMode(LangOptions::SSPOn); + } + // Non-fragile ABI (in 64-bit mode) default to on for 10.5 (darwin9) and + // beyond. if (Maj >= 9 && Opts.ObjC1 && !strncmp(Triple, "x86_64", 6)) Opts.ObjCNonFragileABI = 1; } +template<typename Target> +class DarwinTargetInfo : public OSTargetInfo<Target> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + std::vector<char> &Defines) const { + getDarwinDefines(Defines, Opts); + getDarwinOSXDefines(Defines, Triple); + } + + /// getDefaultLangOptions - Allow the target to specify default settings for + /// various language options. These may be overridden by command line + /// options. + virtual void getDefaultLangOptions(LangOptions &Opts) { + TargetInfo::getDefaultLangOptions(Opts); + GetDarwinLanguageOptions(Opts, TargetInfo::getTargetTriple()); + } +public: + DarwinTargetInfo(const std::string& triple) : + OSTargetInfo<Target>(triple) { + this->TLSSupported = false; + } + + virtual const char *getCFStringSymbolPrefix() const { + return "\01L_unnamed_cfstring_"; + } + + virtual const char *getStringSymbolPrefix(bool IsConstant) const { + return IsConstant ? "\01LC" : "\01lC"; + } + + virtual const char *getUnicodeStringSymbolPrefix() const { + return "__utf16_string_"; + } + + virtual const char *getUnicodeStringSection() const { + return "__TEXT,__ustring"; + } +}; + +// DragonFlyBSD Target +template<typename Target> +class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + std::vector<char> &Defs) const { + // DragonFly defines; list based off of gcc output + Define(Defs, "__DragonFly__"); + Define(Defs, "__DragonFly_cc_version", "100001"); + Define(Defs, "__ELF__"); + Define(Defs, "__KPRINTF_ATTRIBUTE__"); + Define(Defs, "__tune_i386__"); + DefineStd(Defs, "unix", Opts); + } +public: + DragonFlyBSDTargetInfo(const std::string &triple) + : OSTargetInfo<Target>(triple) {} +}; + +// FreeBSD Target +template<typename Target> +class FreeBSDTargetInfo : public OSTargetInfo<Target> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + std::vector<char> &Defs) const { + // FreeBSD defines; list based off of gcc output + + const char *FreeBSD = strstr(Triple, "-freebsd"); + FreeBSD += strlen("-freebsd"); + char release[] = "X"; + release[0] = FreeBSD[0]; + char version[] = "X00001"; + version[0] = FreeBSD[0]; + + Define(Defs, "__FreeBSD__", release); + Define(Defs, "__FreeBSD_cc_version", version); + Define(Defs, "__KPRINTF_ATTRIBUTE__"); + DefineStd(Defs, "unix", Opts); + Define(Defs, "__ELF__", "1"); + } +public: + FreeBSDTargetInfo(const std::string &triple) + : OSTargetInfo<Target>(triple) {} +}; + +// Linux target +template<typename Target> +class LinuxTargetInfo : public OSTargetInfo<Target> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + std::vector<char> &Defs) const { + // Linux defines; list based off of gcc output + DefineStd(Defs, "unix", Opts); + DefineStd(Defs, "linux", Opts); + Define(Defs, "__gnu_linux__"); + Define(Defs, "__ELF__", "1"); + } +public: + LinuxTargetInfo(const std::string& triple) + : OSTargetInfo<Target>(triple) { + this->UserLabelPrefix = ""; + } +}; + +// OpenBSD Target +template<typename Target> +class OpenBSDTargetInfo : public OSTargetInfo<Target> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + std::vector<char> &Defs) const { + // OpenBSD defines; list based off of gcc output + + Define(Defs, "__OpenBSD__", "1"); + DefineStd(Defs, "unix", Opts); + Define(Defs, "__ELF__", "1"); + } +public: + OpenBSDTargetInfo(const std::string &triple) + : OSTargetInfo<Target>(triple) {} +}; + +// Solaris target +template<typename Target> +class SolarisTargetInfo : public OSTargetInfo<Target> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + std::vector<char> &Defs) const { + DefineStd(Defs, "sun", Opts); + DefineStd(Defs, "unix", Opts); + Define(Defs, "__ELF__"); + Define(Defs, "__svr4__"); + Define(Defs, "__SVR4"); + } +public: + SolarisTargetInfo(const std::string& triple) + : OSTargetInfo<Target>(triple) { + this->UserLabelPrefix = ""; + this->WCharType = this->SignedLong; + // FIXME: WIntType should be SignedLong + } +}; +} // end anonymous namespace. + /// GetWindowsLanguageOptions - Set the default language options for Windows. static void GetWindowsLanguageOptions(LangOptions &Opts, const char *Triple) { @@ -435,55 +549,15 @@ class PPC64TargetInfo : public PPCTargetInfo { public: PPC64TargetInfo(const std::string& triple) : PPCTargetInfo(triple) { LongWidth = LongAlign = PointerWidth = PointerAlign = 64; + IntMaxType = SignedLong; + UIntMaxType = UnsignedLong; + Int64Type = SignedLong; DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:64:64-f32:32:32-f64:64:64-v128:128:128"; } }; } // end anonymous namespace. - -namespace { -class DarwinPPCTargetInfo : public PPC32TargetInfo { -public: - DarwinPPCTargetInfo(const std::string& triple) : PPC32TargetInfo(triple) {} - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - PPC32TargetInfo::getTargetDefines(Opts, Defines); - getDarwinDefines(Defines, Opts); - getDarwinOSXDefines(Defines, getTargetTriple()); - } - - /// getDefaultLangOptions - Allow the target to specify default settings for - /// various language options. These may be overridden by command line - /// options. - virtual void getDefaultLangOptions(LangOptions &Opts) { - PPC32TargetInfo::getDefaultLangOptions(Opts); - GetDarwinLanguageOptions(Opts, getTargetTriple()); - } -}; -} // end anonymous namespace. - -namespace { -class DarwinPPC64TargetInfo : public PPC64TargetInfo { -public: - DarwinPPC64TargetInfo(const std::string& triple) : PPC64TargetInfo(triple) {} - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - PPC64TargetInfo::getTargetDefines(Opts, Defines); - getDarwinDefines(Defines, Opts); - getDarwinOSXDefines(Defines, getTargetTriple()); - } - - /// getDefaultLangOptions - Allow the target to specify default settings for - /// various language options. These may be overridden by command line - /// options. - virtual void getDefaultLangOptions(LangOptions &Opts) { - PPC64TargetInfo::getDefaultLangOptions(Opts); - GetDarwinLanguageOptions(Opts, getTargetTriple()); - } -}; -} // end anonymous namespace. - namespace { // Namespace for x86 abstract base class const Builtin::Info BuiltinInfo[] = { @@ -815,10 +889,10 @@ public: } // end anonymous namespace namespace { -// x86-32 Darwin (OS X) target -class DarwinI386TargetInfo : public X86_32TargetInfo { +class DarwinI386TargetInfo : public DarwinTargetInfo<X86_32TargetInfo> { public: - DarwinI386TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) { + DarwinI386TargetInfo(const std::string& triple) : + DarwinTargetInfo<X86_32TargetInfo>(triple) { LongDoubleWidth = 128; LongDoubleAlign = 128; SizeType = UnsignedLong; @@ -826,104 +900,12 @@ public: DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-" "a0:0:64-f80:128:128"; - TLSSupported = false; - } - - virtual const char *getStringSymbolPrefix(bool IsConstant) const { - return IsConstant ? "\01LC" : "\01lC"; - } - - virtual const char *getUnicodeStringSymbolPrefix() const { - return "__utf16_string_"; - } - - virtual const char *getUnicodeStringSection() const { - return "__TEXT,__ustring"; - } - - virtual const char *getCFStringSymbolPrefix() const { - return "\01LC"; - } - - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_32TargetInfo::getTargetDefines(Opts, Defines); - getDarwinDefines(Defines, Opts); - getDarwinOSXDefines(Defines, getTargetTriple()); - } - - /// getDefaultLangOptions - Allow the target to specify default settings for - /// various language options. These may be overridden by command line - /// options. - virtual void getDefaultLangOptions(LangOptions &Opts) { - X86_32TargetInfo::getDefaultLangOptions(Opts); - GetDarwinLanguageOptions(Opts, getTargetTriple()); } -}; -} // end anonymous namespace -namespace { -// x86-32 FreeBSD target -class FreeBSDX86_32TargetInfo : public X86_32TargetInfo { -public: - FreeBSDX86_32TargetInfo(const std::string& triple) : - X86_32TargetInfo(triple) { } - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_32TargetInfo::getTargetDefines(Opts, Defines); - getFreeBSDDefines(Opts, 0, getTargetTriple(), Defines); - } }; } // end anonymous namespace namespace { -// x86-32 DragonFly target -class DragonFlyX86_32TargetInfo : public X86_32TargetInfo { -public: - DragonFlyX86_32TargetInfo(const std::string& triple) : - X86_32TargetInfo(triple) { } - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_32TargetInfo::getTargetDefines(Opts, Defines); - getDragonFlyDefines(Opts, Defines); - } -}; -} // end anonymous namespace - -namespace { -// x86-32 Linux target -class LinuxX86_32TargetInfo : public X86_32TargetInfo { -public: - LinuxX86_32TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) { - UserLabelPrefix = ""; - } - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_32TargetInfo::getTargetDefines(Opts, Defines); - getLinuxDefines(Opts, Defines); - } -}; -} // end anonymous namespace - -namespace { -// x86-32 Solaris target -class SolarisX86_32TargetInfo : public X86_32TargetInfo { -public: - SolarisX86_32TargetInfo(const std::string& triple) : X86_32TargetInfo(triple) { - UserLabelPrefix = ""; - WCharType = SignedLong; - // FIXME: WIntType should be SignedLong - } - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_32TargetInfo::getTargetDefines(Opts, Defines); - getSolarisDefines(Opts, Defines); - } -}; -} // end anonymous namespace - - -namespace { // x86-32 Windows target class WindowsX86_32TargetInfo : public X86_32TargetInfo { public: @@ -961,11 +943,11 @@ class X86_64TargetInfo : public X86TargetInfo { public: X86_64TargetInfo(const std::string &triple) : X86TargetInfo(triple) { LongWidth = LongAlign = PointerWidth = PointerAlign = 64; - DoubleAlign = LongLongAlign = 64; LongDoubleWidth = 128; LongDoubleAlign = 128; IntMaxType = SignedLong; UIntMaxType = UnsignedLong; + Int64Type = SignedLong; RegParmMax = 6; DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-" @@ -978,96 +960,23 @@ public: " unsigned fp_offset;" " void* overflow_arg_area;" " void* reg_save_area;" - "} __builtin_va_list[1];"; + "} __va_list_tag;" + "typedef __va_list_tag __builtin_va_list[1];"; } }; } // end anonymous namespace namespace { -// x86-64 FreeBSD target -class FreeBSDX86_64TargetInfo : public X86_64TargetInfo { +class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> { public: - FreeBSDX86_64TargetInfo(const std::string &triple) - : X86_64TargetInfo(triple) {} - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_64TargetInfo::getTargetDefines(Opts, Defines); - getFreeBSDDefines(Opts, 1, getTargetTriple(), Defines); + DarwinX86_64TargetInfo(const std::string& triple) + : DarwinTargetInfo<X86_64TargetInfo>(triple) { + Int64Type = SignedLongLong; } }; } // end anonymous namespace namespace { -// x86-64 Linux target -class LinuxX86_64TargetInfo : public X86_64TargetInfo { -public: - LinuxX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) { - UserLabelPrefix = ""; - } - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_64TargetInfo::getTargetDefines(Opts, Defines); - getLinuxDefines(Opts, Defines); - } -}; -} // end anonymous namespace - -namespace { -// x86-64 Solaris target -class SolarisX86_64TargetInfo : public X86_64TargetInfo { -public: - SolarisX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) { - UserLabelPrefix = ""; - } - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_64TargetInfo::getTargetDefines(Opts, Defines); - getSolarisDefines(Opts, Defines); - } -}; -} // end anonymous namespace - -namespace { -// x86-64 Darwin (OS X) target -class DarwinX86_64TargetInfo : public X86_64TargetInfo { -public: - DarwinX86_64TargetInfo(const std::string& triple) : X86_64TargetInfo(triple) { - TLSSupported = false; - } - - virtual const char *getStringSymbolPrefix(bool IsConstant) const { - return IsConstant ? "\01LC" : "\01lC"; - } - - virtual const char *getUnicodeStringSymbolPrefix() const { - return "__utf16_string_"; - } - - virtual const char *getUnicodeStringSection() const { - return "__TEXT,__ustring"; - } - - virtual const char *getCFStringSymbolPrefix() const { - return "\01L_unnamed_cfstring_"; - } - - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - X86_64TargetInfo::getTargetDefines(Opts, Defines); - getDarwinDefines(Defines, Opts); - getDarwinOSXDefines(Defines, getTargetTriple()); - } - - /// getDefaultLangOptions - Allow the target to specify default settings for - /// various language options. These may be overridden by command line - /// options. - virtual void getDefaultLangOptions(LangOptions &Opts) { - GetDarwinLanguageOptions(Opts, getTargetTriple()); - } -}; -} // end anonymous namespace. - -namespace { class ARMTargetInfo : public TargetInfo { enum { Armv4t, @@ -1171,33 +1080,20 @@ public: namespace { -class DarwinARMTargetInfo : public ARMTargetInfo { -public: - DarwinARMTargetInfo(const std::string& triple) : ARMTargetInfo(triple) { - TLSSupported = false; - } - - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - ARMTargetInfo::getTargetDefines(Opts, Defines); +class DarwinARMTargetInfo : + public DarwinTargetInfo<ARMTargetInfo> { +protected: + virtual void getOSDefines(const LangOptions &Opts, const char *Triple, + std::vector<char> &Defines) const { getDarwinDefines(Defines, Opts); - getDarwinIPhoneOSDefines(Defines, getTargetTriple()); + getDarwinIPhoneOSDefines(Defines, Triple); } -}; -} // end anonymous namespace. -namespace { -// arm FreeBSD target -class FreeBSDARMTargetInfo : public ARMTargetInfo { public: - FreeBSDARMTargetInfo(const std::string& triple) : ARMTargetInfo(triple) {} - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - ARMTargetInfo::getTargetDefines(Opts, Defines); - getFreeBSDDefines(Opts, 0, getTargetTriple(), Defines); - } + DarwinARMTargetInfo(const std::string& triple) + : DarwinTargetInfo<ARMTargetInfo>(triple) {} }; -} // end anonymous namespace +} // end anonymous namespace. namespace { class SparcV8TargetInfo : public TargetInfo { @@ -1296,21 +1192,12 @@ void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases, } // end anonymous namespace. namespace { -class SolarisSparcV8TargetInfo : public SparcV8TargetInfo { +class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> { public: SolarisSparcV8TargetInfo(const std::string& triple) : - SparcV8TargetInfo(triple) { + SolarisTargetInfo<SparcV8TargetInfo>(triple) { SizeType = UnsignedInt; PtrDiffType = SignedInt; - WCharType = SignedLong; - // FIXME: WIntType should be SignedLong - UserLabelPrefix = ""; - } - - virtual void getTargetDefines(const LangOptions &Opts, - std::vector<char> &Defines) const { - SparcV8TargetInfo::getTargetDefines(Opts, Defines); - getSolarisDefines(Opts, Defines); } }; } // end anonymous namespace. @@ -1454,6 +1341,7 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { // Additions and corrections are welcome. bool isDarwin = T.find("-darwin") != std::string::npos; bool isDragonFly = T.find("-dragonfly") != std::string::npos; + bool isOpenBSD = T.find("-openbsd") != std::string::npos; bool isFreeBSD = T.find("-freebsd") != std::string::npos; bool isSolaris = T.find("-solaris") != std::string::npos; bool isLinux = T.find("-linux") != std::string::npos; @@ -1463,13 +1351,13 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { if (T.find("ppc-") == 0 || T.find("powerpc-") == 0) { if (isDarwin) - return new DarwinPPCTargetInfo(T); + return new DarwinTargetInfo<PPCTargetInfo>(T); return new PPC32TargetInfo(T); } if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0) { if (isDarwin) - return new DarwinPPC64TargetInfo(T); + return new DarwinTargetInfo<PPC64TargetInfo>(T); return new PPC64TargetInfo(T); } @@ -1477,7 +1365,7 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { if (isDarwin) return new DarwinARMTargetInfo(T); if (isFreeBSD) - return new FreeBSDARMTargetInfo(T); + return new FreeBSDTargetInfo<ARMTargetInfo>(T); return new ARMTargetInfo(T); } @@ -1491,11 +1379,13 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { if (isDarwin) return new DarwinX86_64TargetInfo(T); if (isLinux) - return new LinuxX86_64TargetInfo(T); + return new LinuxTargetInfo<X86_64TargetInfo>(T); + if (isOpenBSD) + return new OpenBSDTargetInfo<X86_64TargetInfo>(T); if (isFreeBSD) - return new FreeBSDX86_64TargetInfo(T); + return new FreeBSDTargetInfo<X86_64TargetInfo>(T); if (isSolaris) - return new SolarisX86_64TargetInfo(T); + return new SolarisTargetInfo<X86_64TargetInfo>(T); return new X86_64TargetInfo(T); } @@ -1509,13 +1399,15 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { if (isDarwin) return new DarwinI386TargetInfo(T); if (isLinux) - return new LinuxX86_32TargetInfo(T); + return new LinuxTargetInfo<X86_32TargetInfo>(T); if (isDragonFly) - return new DragonFlyX86_32TargetInfo(T); + return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(T); + if (isOpenBSD) + return new OpenBSDTargetInfo<X86_32TargetInfo>(T); if (isFreeBSD) - return new FreeBSDX86_32TargetInfo(T); + return new FreeBSDTargetInfo<X86_32TargetInfo>(T); if (isSolaris) - return new SolarisX86_32TargetInfo(T); + return new SolarisTargetInfo<X86_32TargetInfo>(T); if (isWindows) return new WindowsX86_32TargetInfo(T); return new X86_32TargetInfo(T); diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 66b1f17368ea..a919dfa2e32c 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -522,7 +522,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BIsqrtf: case Builtin::BIsqrtl: { // Rewrite sqrt to intrinsic if allowed. - if (!FD->hasAttr<ConstAttr>(getContext())) + if (!FD->hasAttr<ConstAttr>()) break; Value *Arg0 = EmitScalarExpr(E->getArg(0)); const llvm::Type *ArgType = Arg0->getType(); @@ -534,7 +534,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, case Builtin::BIpowf: case Builtin::BIpowl: { // Rewrite sqrt to intrinsic if allowed. - if (!FD->hasAttr<ConstAttr>(getContext())) + if (!FD->hasAttr<ConstAttr>()) break; Value *Base = EmitScalarExpr(E->getArg(0)); Value *Exponent = EmitScalarExpr(E->getArg(1)); diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 4f9a4caee695..5f3acea767d5 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -323,8 +323,8 @@ static bool canGenerateCXXstructor(const CXXRecordDecl *RD, if (RD->getNumBases() > 0) return false; - for (CXXRecordDecl::field_iterator I = RD->field_begin(Context), - E = RD->field_end(Context); I != E; ++I) { + for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); + I != E; ++I) { // We don't support ctors for fields that aren't POD. if (!I->getType()->isPODType()) return false; diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index 30c5d28c227e..97391bc620be 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -142,8 +142,8 @@ void CodeGenTypes::GetExpandedTypes(QualType Ty, assert(!RD->hasFlexibleArrayMember() && "Cannot expand structure with flexible array."); - for (RecordDecl::field_iterator i = RD->field_begin(Context), - e = RD->field_end(Context); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) { const FieldDecl *FD = *i; assert(!FD->isBitField() && "Cannot expand structure with bit-field members."); @@ -167,8 +167,8 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV, assert(LV.isSimple() && "Unexpected non-simple lvalue during struct expansion."); llvm::Value *Addr = LV.getAddress(); - for (RecordDecl::field_iterator i = RD->field_begin(getContext()), - e = RD->field_end(getContext()); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) { FieldDecl *FD = *i; QualType FT = FD->getType(); @@ -194,8 +194,8 @@ CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV, RecordDecl *RD = RT->getDecl(); assert(RV.isAggregate() && "Unexpected rvalue during struct expansion"); llvm::Value *Addr = RV.getAggregateAddr(); - for (RecordDecl::field_iterator i = RD->field_begin(getContext()), - e = RD->field_end(getContext()); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) { FieldDecl *FD = *i; QualType FT = FD->getType(); @@ -377,13 +377,13 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, // FIXME: handle sseregparm someday... if (TargetDecl) { - if (TargetDecl->hasAttr<NoThrowAttr>(getContext())) + if (TargetDecl->hasAttr<NoThrowAttr>()) FuncAttrs |= llvm::Attribute::NoUnwind; - if (TargetDecl->hasAttr<NoReturnAttr>(getContext())) + if (TargetDecl->hasAttr<NoReturnAttr>()) FuncAttrs |= llvm::Attribute::NoReturn; - if (TargetDecl->hasAttr<ConstAttr>(getContext())) + if (TargetDecl->hasAttr<ConstAttr>()) FuncAttrs |= llvm::Attribute::ReadNone; - else if (TargetDecl->hasAttr<PureAttr>(getContext())) + else if (TargetDecl->hasAttr<PureAttr>()) FuncAttrs |= llvm::Attribute::ReadOnly; } @@ -392,6 +392,11 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, if (CompileOpts.NoImplicitFloat) FuncAttrs |= llvm::Attribute::NoImplicitFloat; + if (Features.getStackProtectorMode() == LangOptions::SSPOn) + FuncAttrs |= llvm::Attribute::StackProtect; + else if (Features.getStackProtectorMode() == LangOptions::SSPReq) + FuncAttrs |= llvm::Attribute::StackProtectReq; + QualType RetTy = FI.getReturnType(); unsigned Index = 1; const ABIArgInfo &RetAI = FI.getReturnInfo(); @@ -433,7 +438,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI, signed RegParm = 0; if (TargetDecl) if (const RegparmAttr *RegParmAttr - = TargetDecl->getAttr<RegparmAttr>(getContext())) + = TargetDecl->getAttr<RegparmAttr>()) RegParm = RegParmAttr->getNumParams(); unsigned PointerWidth = getContext().Target.getPointerWidth(0); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 5e872c290dfa..2bf8a222a253 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -151,7 +151,7 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT, uint64_t Offset = 0; return DebugFactory.CreateBasicType(Unit, - BT->getName(M->getContext().getLangOptions().CPlusPlus), + BT->getName(M->getContext().getLangOptions()), Unit, 0, Size, Align, Offset, /*flags*/ 0, Encoding); } @@ -437,8 +437,8 @@ llvm::DIType CGDebugInfo::CreateType(const RecordType *Ty, const ASTRecordLayout &RL = M->getContext().getASTRecordLayout(Decl); unsigned FieldNo = 0; - for (RecordDecl::field_iterator I = Decl->field_begin(M->getContext()), - E = Decl->field_end(M->getContext()); + for (RecordDecl::field_iterator I = Decl->field_begin(), + E = Decl->field_end(); I != E; ++I, ++FieldNo) { FieldDecl *Field = *I; llvm::DIType FieldTy = getOrCreateType(Field->getType(), Unit); @@ -638,8 +638,7 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty, // Create DIEnumerator elements for each enumerator. for (EnumDecl::enumerator_iterator - Enum = Decl->enumerator_begin(M->getContext()), - EnumEnd = Decl->enumerator_end(M->getContext()); + Enum = Decl->enumerator_begin(), EnumEnd = Decl->enumerator_end(); Enum != EnumEnd; ++Enum) { Enumerators.push_back(DebugFactory.CreateEnumerator(Enum->getNameAsString(), Enum->getInitVal().getZExtValue())); diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index f97c62f9d142..2ae7e225ebbf 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -60,7 +60,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { /// EmitBlockVarDecl - This method handles emission of any variable declaration /// inside a function, including static vars etc. void CodeGenFunction::EmitBlockVarDecl(const VarDecl &D) { - if (D.hasAttr<AsmLabelAttr>(getContext())) + if (D.hasAttr<AsmLabelAttr>()) CGM.ErrorUnsupported(&D, "__asm__"); switch (D.getStorageClass()) { @@ -171,7 +171,7 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { } // FIXME: Merge attribute handling. - if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>(getContext())) { + if (const AnnotateAttr *AA = D.getAttr<AnnotateAttr>()) { SourceManager &SM = CGM.getContext().getSourceManager(); llvm::Constant *Ann = CGM.EmitAnnotateAttr(GV, AA, @@ -179,10 +179,10 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const VarDecl &D) { CGM.AddAnnotation(Ann); } - if (const SectionAttr *SA = D.getAttr<SectionAttr>(getContext())) + if (const SectionAttr *SA = D.getAttr<SectionAttr>()) GV->setSection(SA->getName()); - if (D.hasAttr<UsedAttr>(getContext())) + if (D.hasAttr<UsedAttr>()) CGM.AddUsedGlobal(GV); // We may have to cast the constant because of the initializer @@ -244,7 +244,7 @@ const llvm::Type *CodeGenFunction::BuildByRefType(QualType Ty, /// These turn into simple stack objects, or GlobalValues depending on target. void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { QualType Ty = D.getType(); - bool isByRef = D.hasAttr<BlocksAttr>(getContext()); + bool isByRef = D.hasAttr<BlocksAttr>(); bool needsDispose = false; unsigned Align = 0; @@ -414,7 +414,7 @@ void CodeGenFunction::EmitLocalBlockVarDecl(const VarDecl &D) { } // Handle the cleanup attribute - if (const CleanupAttr *CA = D.getAttr<CleanupAttr>(getContext())) { + if (const CleanupAttr *CA = D.getAttr<CleanupAttr>()) { const FunctionDecl *FD = CA->getFunctionDecl(); llvm::Constant* F = CGM.GetAddrOfFunction(GlobalDecl(FD)); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index a21140765c20..0951019f0108 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -670,7 +670,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { isa<ImplicitParamDecl>(VD))) { LValue LV; bool NonGCable = VD->hasLocalStorage() && - !VD->hasAttr<BlocksAttr>(getContext()); + !VD->hasAttr<BlocksAttr>(); if (VD->hasExternalStorage()) { llvm::Value *V = CGM.GetAddrOfGlobalVar(VD); if (VD->getType()->isReferenceType()) @@ -686,7 +686,7 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { // local static? if (!NonGCable) attr = getContext().getObjCGCAttrKind(E->getType()); - if (VD->hasAttr<BlocksAttr>(getContext())) { + if (VD->hasAttr<BlocksAttr>()) { bool needsCopyDispose = BlockRequiresCopying(VD->getType()); const llvm::Type *PtrStructTy = V->getType(); const llvm::Type *Ty = PtrStructTy; diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 4268ae3b1701..412a06594f53 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -436,8 +436,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { #ifndef NDEBUG // Make sure that it's really an empty and not a failure of // semantic analysis. - for (RecordDecl::field_iterator Field = SD->field_begin(CGF.getContext()), - FieldEnd = SD->field_end(CGF.getContext()); + for (RecordDecl::field_iterator Field = SD->field_begin(), + FieldEnd = SD->field_end(); Field != FieldEnd; ++Field) assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed"); #endif @@ -461,8 +461,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // Here we iterate over the fields; this makes it simpler to both // default-initialize fields and skip over unnamed fields. - for (RecordDecl::field_iterator Field = SD->field_begin(CGF.getContext()), - FieldEnd = SD->field_end(CGF.getContext()); + for (RecordDecl::field_iterator Field = SD->field_begin(), + FieldEnd = SD->field_end(); Field != FieldEnd; ++Field) { // We're done once we hit the flexible array member if (Field->getType()->isIncompleteArrayType()) diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 0b109f9bee42..37c9c366fee6 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -199,8 +199,8 @@ public: // Copy initializer elements. Skip padding fields. unsigned EltNo = 0; // Element no in ILE bool RewriteType = false; - for (RecordDecl::field_iterator Field = RD->field_begin(CGM.getContext()), - FieldEnd = RD->field_end(CGM.getContext()); + for (RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); EltNo < ILE->getNumInits() && Field != FieldEnd; ++Field) { if (Field->isBitField()) { if (!Field->getIdentifier()) @@ -263,8 +263,8 @@ public: // Make sure that it's really an empty and not a failure of // semantic analysis. RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl(); - for (RecordDecl::field_iterator Field = RD->field_begin(CGM.getContext()), - FieldEnd = RD->field_end(CGM.getContext()); + for (RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) assert(Field->isUnnamedBitfield() && "Only unnamed bitfields allowed"); #endif diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index e7cf8e6e653a..33cb5bca3869 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -126,11 +126,11 @@ void CodeGenFunction::StartObjCMethod(const ObjCMethodDecl *OMD, /// its pointer, name, and types registered in the class struture. void CodeGenFunction::GenerateObjCMethod(const ObjCMethodDecl *OMD) { // Check if we should generate debug info for this method. - if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>(getContext())) + if (CGM.getDebugInfo() && !OMD->hasAttr<NodebugAttr>()) DebugInfo = CGM.getDebugInfo(); StartObjCMethod(OMD, OMD->getClassInterface()); - EmitStmt(OMD->getBody(getContext())); - FinishFunction(OMD->getBodyRBrace(getContext())); + EmitStmt(OMD->getBody()); + FinishFunction(OMD->getBodyRBrace()); } // FIXME: I wasn't sure about the synthesis approach. If we end up generating an diff --git a/lib/CodeGen/CGObjCGNU.cpp b/lib/CodeGen/CGObjCGNU.cpp index 4f96b8baec06..6554da9cf98c 100644 --- a/lib/CodeGen/CGObjCGNU.cpp +++ b/lib/CodeGen/CGObjCGNU.cpp @@ -180,7 +180,7 @@ void CGObjCGNU::EmitClassRef(const std::string &className){ std::string symbolName = "__objc_class_name_" + className; llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName); if (!ClassSymbol) { - ClassSymbol = new llvm::GlobalVariable(LongTy, false, + ClassSymbol = new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage, 0, symbolName, &TheModule); } new llvm::GlobalVariable(ClassSymbol->getType(), true, @@ -739,8 +739,8 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { Protocols.push_back((*PI)->getNameAsString()); llvm::SmallVector<llvm::Constant*, 16> InstanceMethodNames; llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; - for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(Context), - E = PD->instmeth_end(Context); iter != E; iter++) { + for (ObjCProtocolDecl::instmeth_iterator iter = PD->instmeth_begin(), + E = PD->instmeth_end(); iter != E; iter++) { std::string TypeStr; Context.getObjCEncodingForMethodDecl(*iter, TypeStr); InstanceMethodNames.push_back( @@ -751,8 +751,8 @@ void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) { llvm::SmallVector<llvm::Constant*, 16> ClassMethodNames; llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; for (ObjCProtocolDecl::classmeth_iterator - iter = PD->classmeth_begin(Context), - endIter = PD->classmeth_end(Context) ; iter != endIter ; iter++) { + iter = PD->classmeth_begin(), endIter = PD->classmeth_end(); + iter != endIter ; iter++) { std::string TypeStr; Context.getObjCEncodingForMethodDecl((*iter),TypeStr); ClassMethodNames.push_back( @@ -794,8 +794,7 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { llvm::SmallVector<Selector, 16> InstanceMethodSels; llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; for (ObjCCategoryImplDecl::instmeth_iterator - iter = OCD->instmeth_begin(CGM.getContext()), - endIter = OCD->instmeth_end(CGM.getContext()); + iter = OCD->instmeth_begin(), endIter = OCD->instmeth_end(); iter != endIter ; iter++) { InstanceMethodSels.push_back((*iter)->getSelector()); std::string TypeStr; @@ -807,8 +806,7 @@ void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) { llvm::SmallVector<Selector, 16> ClassMethodSels; llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; for (ObjCCategoryImplDecl::classmeth_iterator - iter = OCD->classmeth_begin(CGM.getContext()), - endIter = OCD->classmeth_end(CGM.getContext()); + iter = OCD->classmeth_begin(), endIter = OCD->classmeth_end(); iter != endIter ; iter++) { ClassMethodSels.push_back((*iter)->getSelector()); std::string TypeStr; @@ -861,9 +859,14 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { std::string ClassName = ClassDecl->getNameAsString(); // Emit the symbol that is used to generate linker errors if this class is // referenced in other modules but not declared. - new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage, - llvm::ConstantInt::get(LongTy, 0), "__objc_class_name_" + ClassName, - &TheModule); + std::string classSymbolName = "__objc_class_name_" + ClassName; + if (llvm::GlobalVariable *symbol = + TheModule.getGlobalVariable(classSymbolName)) { + symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0)); + } else { + new llvm::GlobalVariable(LongTy, false, llvm::GlobalValue::ExternalLinkage, + llvm::ConstantInt::get(LongTy, 0), classSymbolName, &TheModule); + } // Get the size of instances. int instanceSize = Context.getASTObjCImplementationLayout(OID).getSize() / 8; @@ -906,8 +909,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { llvm::SmallVector<Selector, 16> InstanceMethodSels; llvm::SmallVector<llvm::Constant*, 16> InstanceMethodTypes; for (ObjCImplementationDecl::instmeth_iterator - iter = OID->instmeth_begin(CGM.getContext()), - endIter = OID->instmeth_end(CGM.getContext()); + iter = OID->instmeth_begin(), endIter = OID->instmeth_end(); iter != endIter ; iter++) { InstanceMethodSels.push_back((*iter)->getSelector()); std::string TypeStr; @@ -915,8 +917,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { InstanceMethodTypes.push_back(CGM.GetAddrOfConstantCString(TypeStr)); } for (ObjCImplDecl::propimpl_iterator - iter = OID->propimpl_begin(CGM.getContext()), - endIter = OID->propimpl_end(CGM.getContext()); + iter = OID->propimpl_begin(), endIter = OID->propimpl_end(); iter != endIter ; iter++) { ObjCPropertyDecl *property = (*iter)->getPropertyDecl(); if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) { @@ -937,8 +938,7 @@ void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) { llvm::SmallVector<Selector, 16> ClassMethodSels; llvm::SmallVector<llvm::Constant*, 16> ClassMethodTypes; for (ObjCImplementationDecl::classmeth_iterator - iter = OID->classmeth_begin(CGM.getContext()), - endIter = OID->classmeth_end(CGM.getContext()); + iter = OID->classmeth_begin(), endIter = OID->classmeth_end(); iter != endIter ; iter++) { ClassMethodSels.push_back((*iter)->getSelector()); std::string TypeStr; @@ -1163,9 +1163,8 @@ llvm::Function *CGObjCGNU::ModuleInitFunction() { // Create the load function calling the runtime entry point with the module // structure - std::vector<const llvm::Type*> VoidArgs; llvm::Function * LoadFunction = llvm::Function::Create( - llvm::FunctionType::get(llvm::Type::VoidTy, VoidArgs, false), + llvm::FunctionType::get(llvm::Type::VoidTy, false), llvm::GlobalValue::InternalLinkage, ".objc_load_function", &TheModule); llvm::BasicBlock *EntryBB = llvm::BasicBlock::Create("entry", LoadFunction); @@ -1250,7 +1249,7 @@ void CGObjCGNU::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, // Pointer to the personality function llvm::Constant *Personality = CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty, - std::vector<const llvm::Type*>(), true), + true), "__gnu_objc_personality_v0"); Personality = llvm::ConstantExpr::getBitCast(Personality, PtrTy); std::vector<const llvm::Type*> Params; diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 865e8c240be2..c3354574c775 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -690,7 +690,6 @@ public: llvm::Value *getEHPersonalityPtr() { llvm::Constant *Personality = CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::Int32Ty, - std::vector<const llvm::Type*>(), true), "__objc_personality_v0"); return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy); @@ -705,9 +704,8 @@ public: } llvm::Constant *getObjCEndCatchFn() { - std::vector<const llvm::Type*> Params; return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::VoidTy, - Params, false), + false), "objc_end_catch"); } @@ -1360,7 +1358,7 @@ static llvm::Constant *getConstantGEP(llvm::Constant *C, /// class has the __objc_exception__ attribute. static bool hasObjCExceptionAttribute(ASTContext &Context, const ObjCInterfaceDecl *OID) { - if (OID->hasAttr<ObjCExceptionAttr>(Context)) + if (OID->hasAttr<ObjCExceptionAttr>()) return true; if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) return hasObjCExceptionAttribute(Context, Super); @@ -1585,8 +1583,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { std::vector<llvm::Constant*> InstanceMethods, ClassMethods; std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; for (ObjCProtocolDecl::instmeth_iterator - i = PD->instmeth_begin(CGM.getContext()), - e = PD->instmeth_end(CGM.getContext()); i != e; ++i) { + i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { @@ -1597,8 +1594,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { } for (ObjCProtocolDecl::classmeth_iterator - i = PD->classmeth_begin(CGM.getContext()), - e = PD->classmeth_end(CGM.getContext()); i != e; ++i) { + i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { @@ -1772,8 +1768,8 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name, const ObjCContainerDecl *OCD, const ObjCCommonTypesHelper &ObjCTypes) { std::vector<llvm::Constant*> Properties, Prop(2); - for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(CGM.getContext()), - E = OCD->prop_end(CGM.getContext()); I != E; ++I) { + for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(), + E = OCD->prop_end(); I != E; ++I) { const ObjCPropertyDecl *PD = *I; Prop[0] = GetPropertyName(PD->getIdentifier()); Prop[1] = GetPropertyTypeString(PD, Container); @@ -1865,14 +1861,12 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { std::vector<llvm::Constant*> InstanceMethods, ClassMethods; for (ObjCCategoryImplDecl::instmeth_iterator - i = OCD->instmeth_begin(CGM.getContext()), - e = OCD->instmeth_end(CGM.getContext()); i != e; ++i) { + i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { // Instance methods should always be defined. InstanceMethods.push_back(GetMethodConstant(*i)); } for (ObjCCategoryImplDecl::classmeth_iterator - i = OCD->classmeth_begin(CGM.getContext()), - e = OCD->classmeth_end(CGM.getContext()); i != e; ++i) { + i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { // Class methods should always be defined. ClassMethods.push_back(GetMethodConstant(*i)); } @@ -1969,21 +1963,18 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { std::vector<llvm::Constant*> InstanceMethods, ClassMethods; for (ObjCImplementationDecl::instmeth_iterator - i = ID->instmeth_begin(CGM.getContext()), - e = ID->instmeth_end(CGM.getContext()); i != e; ++i) { + i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { // Instance methods should always be defined. InstanceMethods.push_back(GetMethodConstant(*i)); } for (ObjCImplementationDecl::classmeth_iterator - i = ID->classmeth_begin(CGM.getContext()), - e = ID->classmeth_end(CGM.getContext()); i != e; ++i) { + i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { // Class methods should always be defined. ClassMethods.push_back(GetMethodConstant(*i)); } for (ObjCImplementationDecl::propimpl_iterator - i = ID->propimpl_begin(CGM.getContext()), - e = ID->propimpl_end(CGM.getContext()); i != e; ++i) { + i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { ObjCPropertyImplDecl *PID = *i; if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) { @@ -2983,8 +2974,7 @@ void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT, bool &HasUnion) { const RecordDecl *RD = RT->getDecl(); // FIXME - Use iterator. - llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(CGM.getContext()), - RD->field_end(CGM.getContext())); + llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end()); const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); const llvm::StructLayout *RecLayout = CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty)); @@ -3528,9 +3518,9 @@ ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm) RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0, SourceLocation(), &Ctx.Idents.get("_objc_super")); - RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, Ctx.getObjCIdType(), 0, false)); - RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, Ctx.getObjCClassType(), 0, false)); RD->completeDefinition(Ctx); @@ -3987,9 +3977,9 @@ ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModul RecordDecl *RD = RecordDecl::Create(Ctx, TagDecl::TK_struct, 0, SourceLocation(), &Ctx.Idents.get("_message_ref_t")); - RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, Ctx.VoidPtrTy, 0, false)); - RD->addDecl(Ctx, FieldDecl::Create(Ctx, RD, SourceLocation(), 0, + RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0, Ctx.getObjCSelType(), 0, false)); RD->completeDefinition(Ctx); @@ -4190,22 +4180,19 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( if (flags & CLS_META) { MethodListName += "CLASS_METHODS_" + ID->getNameAsString(); for (ObjCImplementationDecl::classmeth_iterator - i = ID->classmeth_begin(CGM.getContext()), - e = ID->classmeth_end(CGM.getContext()); i != e; ++i) { + i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { // Class methods should always be defined. Methods.push_back(GetMethodConstant(*i)); } } else { MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString(); for (ObjCImplementationDecl::instmeth_iterator - i = ID->instmeth_begin(CGM.getContext()), - e = ID->instmeth_end(CGM.getContext()); i != e; ++i) { + i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) { // Instance methods should always be defined. Methods.push_back(GetMethodConstant(*i)); } for (ObjCImplementationDecl::propimpl_iterator - i = ID->propimpl_begin(CGM.getContext()), - e = ID->propimpl_end(CGM.getContext()); i != e; ++i) { + i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) { ObjCPropertyImplDecl *PID = *i; if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){ @@ -4298,7 +4285,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const { - return OD->getClassMethod(CGM.getContext(), GetNullarySelector("load")) != 0; + return OD->getClassMethod(GetNullarySelector("load")) != 0; } void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, @@ -4478,8 +4465,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { "_$_" + OCD->getNameAsString(); for (ObjCCategoryImplDecl::instmeth_iterator - i = OCD->instmeth_begin(CGM.getContext()), - e = OCD->instmeth_end(CGM.getContext()); i != e; ++i) { + i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) { // Instance methods should always be defined. Methods.push_back(GetMethodConstant(*i)); } @@ -4493,8 +4479,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { OCD->getNameAsString(); Methods.clear(); for (ObjCCategoryImplDecl::classmeth_iterator - i = OCD->classmeth_begin(CGM.getContext()), - e = OCD->classmeth_end(CGM.getContext()); i != e; ++i) { + i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) { // Class methods should always be defined. Methods.push_back(GetMethodConstant(*i)); } @@ -4782,9 +4767,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( std::vector<llvm::Constant*> InstanceMethods, ClassMethods; std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; for (ObjCProtocolDecl::instmeth_iterator - i = PD->instmeth_begin(CGM.getContext()), - e = PD->instmeth_end(CGM.getContext()); - i != e; ++i) { + i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { @@ -4795,9 +4778,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( } for (ObjCProtocolDecl::classmeth_iterator - i = PD->classmeth_begin(CGM.getContext()), - e = PD->classmeth_end(CGM.getContext()); - i != e; ++i) { + i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; llvm::Constant *C = GetMethodDescriptionConstant(MD); if (MD->getImplementationControl() == ObjCMethodDecl::Optional) { diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index f10a08f9db86..c3f9364e7ae4 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -199,7 +199,7 @@ void CodeGenFunction::StartFunction(const Decl *D, QualType RetTy, void CodeGenFunction::GenerateCode(const FunctionDecl *FD, llvm::Function *Fn) { // Check if we should generate debug info for this function. - if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>(getContext())) + if (CGM.getDebugInfo() && !FD->hasAttr<NodebugAttr>()) DebugInfo = CGM.getDebugInfo(); FunctionArgList Args; @@ -226,7 +226,7 @@ void CodeGenFunction::GenerateCode(const FunctionDecl *FD, } // FIXME: Support CXXTryStmt here, too. - if (const CompoundStmt *S = FD->getCompoundBody(getContext())) { + if (const CompoundStmt *S = FD->getCompoundBody()) { StartFunction(FD, FD->getResultType(), Fn, Args, S->getLBracLoc()); EmitStmt(S); FinishFunction(S->getRBracLoc()); diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 0a531e9b21a6..d88a37a45b23 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -102,7 +102,7 @@ CodeGenModule::getDeclVisibilityMode(const Decl *D) const { if (VD->getStorageClass() == VarDecl::PrivateExtern) return LangOptions::Hidden; - if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>(getContext())) { + if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) { switch (attr->getVisibility()) { default: assert(0 && "Unknown visibility!"); case VisibilityAttr::DefaultVisibility: @@ -243,12 +243,20 @@ void CodeGenModule::EmitAnnotations() { static CodeGenModule::GVALinkage GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD, const LangOptions &Features) { + // The kind of external linkage this function will have, if it is not + // inline or static. + CodeGenModule::GVALinkage External = CodeGenModule::GVA_StrongExternal; + if (Context.getLangOptions().CPlusPlus && + (FD->getPrimaryTemplate() || FD->getInstantiatedFromMemberFunction()) && + !FD->isExplicitSpecialization()) + External = CodeGenModule::GVA_TemplateInstantiation; + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { // C++ member functions defined inside the class are always inline. if (MD->isInline() || !MD->isOutOfLine()) return CodeGenModule::GVA_CXXInline; - return CodeGenModule::GVA_StrongExternal; + return External; } // "static" functions get internal linkage. @@ -256,7 +264,7 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD, return CodeGenModule::GVA_Internal; if (!FD->isInline()) - return CodeGenModule::GVA_StrongExternal; + return External; // If the inline function explicitly has the GNU inline attribute on it, or if // this is C89 mode, we use to GNU semantics. @@ -273,7 +281,7 @@ GetLinkageForFunction(ASTContext &Context, const FunctionDecl *FD, if (FD->isExternGNUInline(Context)) return CodeGenModule::GVA_C99Inline; // Normal inline is a strong symbol. - return CodeGenModule::GVA_StrongExternal; + return External; } // The definition of inline changes based on the language. Note that we @@ -298,15 +306,15 @@ void CodeGenModule::SetFunctionDefinitionAttributes(const FunctionDecl *D, if (Linkage == GVA_Internal) { GV->setLinkage(llvm::Function::InternalLinkage); - } else if (D->hasAttr<DLLExportAttr>(getContext())) { + } else if (D->hasAttr<DLLExportAttr>()) { GV->setLinkage(llvm::Function::DLLExportLinkage); - } else if (D->hasAttr<WeakAttr>(getContext())) { + } else if (D->hasAttr<WeakAttr>()) { GV->setLinkage(llvm::Function::WeakAnyLinkage); } else if (Linkage == GVA_C99Inline) { // In C99 mode, 'inline' functions are guaranteed to have a strong // definition somewhere else, so we can use available_externally linkage. GV->setLinkage(llvm::Function::AvailableExternallyLinkage); - } else if (Linkage == GVA_CXXInline) { + } else if (Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) { // In C++, the compiler has to emit a definition in every translation unit // that references the function. We should use linkonce_odr because // a) if all references in this translation unit are optimized away, we @@ -333,10 +341,10 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D, AttributeList.size())); // Set the appropriate calling convention for the Function. - if (D->hasAttr<FastCallAttr>(getContext())) + if (D->hasAttr<FastCallAttr>()) F->setCallingConv(llvm::CallingConv::X86_FastCall); - if (D->hasAttr<StdCallAttr>(getContext())) + if (D->hasAttr<StdCallAttr>()) F->setCallingConv(llvm::CallingConv::X86_StdCall); } @@ -345,10 +353,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D, if (!Features.Exceptions && !Features.ObjCNonFragileABI) F->addFnAttr(llvm::Attribute::NoUnwind); - if (D->hasAttr<AlwaysInlineAttr>(getContext())) + if (D->hasAttr<AlwaysInlineAttr>()) F->addFnAttr(llvm::Attribute::AlwaysInline); - if (D->hasAttr<NoinlineAttr>(getContext())) + if (D->hasAttr<NoinlineAttr>()) F->addFnAttr(llvm::Attribute::NoInline); } @@ -356,10 +364,10 @@ void CodeGenModule::SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV) { setGlobalVisibility(GV, D); - if (D->hasAttr<UsedAttr>(getContext())) + if (D->hasAttr<UsedAttr>()) AddUsedGlobal(GV); - if (const SectionAttr *SA = D->getAttr<SectionAttr>(getContext())) + if (const SectionAttr *SA = D->getAttr<SectionAttr>()) GV->setSection(SA->getName()); } @@ -383,10 +391,10 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, // Only a few attributes are set on declarations; these may later be // overridden by a definition. - if (FD->hasAttr<DLLImportAttr>(getContext())) { + if (FD->hasAttr<DLLImportAttr>()) { F->setLinkage(llvm::Function::DLLImportLinkage); - } else if (FD->hasAttr<WeakAttr>(getContext()) || - FD->hasAttr<WeakImportAttr>(getContext())) { + } else if (FD->hasAttr<WeakAttr>() || + FD->hasAttr<WeakImportAttr>()) { // "extern_weak" is overloaded in LLVM; we probably should have // separate linkage types for this. F->setLinkage(llvm::Function::ExternalWeakLinkage); @@ -394,7 +402,7 @@ void CodeGenModule::SetFunctionAttributes(const FunctionDecl *FD, F->setLinkage(llvm::Function::ExternalLinkage); } - if (const SectionAttr *SA = FD->getAttr<SectionAttr>(getContext())) + if (const SectionAttr *SA = FD->getAttr<SectionAttr>()) F->setSection(SA->getName()); } @@ -508,13 +516,13 @@ llvm::Constant *CodeGenModule::EmitAnnotateAttr(llvm::GlobalValue *GV, bool CodeGenModule::MayDeferGeneration(const ValueDecl *Global) { // Never defer when EmitAllDecls is specified or the decl has // attribute used. - if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>(getContext())) + if (Features.EmitAllDecls || Global->hasAttr<UsedAttr>()) return false; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Global)) { // Constructors and destructors should never be deferred. - if (FD->hasAttr<ConstructorAttr>(getContext()) || - FD->hasAttr<DestructorAttr>(getContext())) + if (FD->hasAttr<ConstructorAttr>() || + FD->hasAttr<DestructorAttr>()) return false; GVALinkage Linkage = GetLinkageForFunction(getContext(), FD, Features); @@ -538,7 +546,7 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) { // If this is an alias definition (which otherwise looks like a declaration) // emit it now. - if (Global->hasAttr<AliasAttr>(getContext())) + if (Global->hasAttr<AliasAttr>()) return EmitAliasDefinition(Global); // Ignore declarations, they will be emitted on their first use. @@ -727,8 +735,8 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMGlobal(const char *MangledName, if (D->getStorageClass() == VarDecl::PrivateExtern) GV->setVisibility(llvm::GlobalValue::HiddenVisibility); - if (D->hasAttr<WeakAttr>(getContext()) || - D->hasAttr<WeakImportAttr>(getContext())) + if (D->hasAttr<WeakAttr>() || + D->hasAttr<WeakImportAttr>()) GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); GV->setThreadLocal(D->isThreadSpecified()); @@ -848,7 +856,7 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { cast<llvm::GlobalValue>(Entry)->eraseFromParent(); } - if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>(getContext())) { + if (const AnnotateAttr *AA = D->getAttr<AnnotateAttr>()) { SourceManager &SM = Context.getSourceManager(); AddAnnotation(EmitAnnotateAttr(GV, AA, SM.getInstantiationLineNumber(D->getLocation()))); @@ -861,11 +869,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { // Set the llvm linkage type as appropriate. if (D->getStorageClass() == VarDecl::Static) GV->setLinkage(llvm::Function::InternalLinkage); - else if (D->hasAttr<DLLImportAttr>(getContext())) + else if (D->hasAttr<DLLImportAttr>()) GV->setLinkage(llvm::Function::DLLImportLinkage); - else if (D->hasAttr<DLLExportAttr>(getContext())) + else if (D->hasAttr<DLLExportAttr>()) GV->setLinkage(llvm::Function::DLLExportLinkage); - else if (D->hasAttr<WeakAttr>(getContext())) + else if (D->hasAttr<WeakAttr>()) GV->setLinkage(llvm::GlobalVariable::WeakAnyLinkage); else if (!CompileOpts.NoCommon && (!D->hasExternalStorage() && !D->getInit())) @@ -1028,14 +1036,14 @@ void CodeGenModule::EmitGlobalFunctionDefinition(GlobalDecl GD) { SetFunctionDefinitionAttributes(D, Fn); SetLLVMFunctionAttributesForDefinition(D, Fn); - if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>(getContext())) + if (const ConstructorAttr *CA = D->getAttr<ConstructorAttr>()) AddGlobalCtor(Fn, CA->getPriority()); - if (const DestructorAttr *DA = D->getAttr<DestructorAttr>(getContext())) + if (const DestructorAttr *DA = D->getAttr<DestructorAttr>()) AddGlobalDtor(Fn, DA->getPriority()); } void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) { - const AliasAttr *AA = D->getAttr<AliasAttr>(getContext()); + const AliasAttr *AA = D->getAttr<AliasAttr>(); assert(AA && "Not an alias?"); const llvm::Type *DeclTy = getTypes().ConvertTypeForMem(D->getType()); @@ -1091,16 +1099,16 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) { // Set attributes which are particular to an alias; this is a // specialization of the attributes which may be set on a global // variable/function. - if (D->hasAttr<DLLExportAttr>(getContext())) { + if (D->hasAttr<DLLExportAttr>()) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // The dllexport attribute is ignored for undefined symbols. - if (FD->getBody(getContext())) + if (FD->getBody()) GA->setLinkage(llvm::Function::DLLExportLinkage); } else { GA->setLinkage(llvm::Function::DLLExportLinkage); } - } else if (D->hasAttr<WeakAttr>(getContext()) || - D->hasAttr<WeakImportAttr>(getContext())) { + } else if (D->hasAttr<WeakAttr>() || + D->hasAttr<WeakImportAttr>()) { GA->setLinkage(llvm::Function::WeakAnyLinkage); } @@ -1254,7 +1262,7 @@ GetAddrOfConstantCFString(const StringLiteral *Literal) { cast<llvm::StructType>(getTypes().ConvertType(CFTy)); std::vector<llvm::Constant*> Fields; - RecordDecl::field_iterator Field = CFRD->field_begin(getContext()); + RecordDecl::field_iterator Field = CFRD->field_begin(); // Class pointer. FieldDecl *CurField = *Field++; @@ -1424,8 +1432,7 @@ llvm::Constant *CodeGenModule::GetAddrOfConstantCString(const std::string &str, void CodeGenModule::EmitObjCPropertyImplementations(const ObjCImplementationDecl *D) { for (ObjCImplementationDecl::propimpl_iterator - i = D->propimpl_begin(getContext()), - e = D->propimpl_end(getContext()); i != e; ++i) { + i = D->propimpl_begin(), e = D->propimpl_end(); i != e; ++i) { ObjCPropertyImplDecl *PID = *i; // Dynamic is just for type-checking. @@ -1437,11 +1444,11 @@ void CodeGenModule::EmitObjCPropertyImplementations(const // we want, that just indicates if the decl came from a // property. What we want to know is if the method is defined in // this implementation. - if (!D->getInstanceMethod(getContext(), PD->getGetterName())) + if (!D->getInstanceMethod(PD->getGetterName())) CodeGenFunction(*this).GenerateObjCGetter( const_cast<ObjCImplementationDecl *>(D), PID); if (!PD->isReadOnly() && - !D->getInstanceMethod(getContext(), PD->getSetterName())) + !D->getInstanceMethod(PD->getSetterName())) CodeGenFunction(*this).GenerateObjCSetter( const_cast<ObjCImplementationDecl *>(D), PID); } @@ -1450,8 +1457,7 @@ void CodeGenModule::EmitObjCPropertyImplementations(const /// EmitNamespace - Emit all declarations in a namespace. void CodeGenModule::EmitNamespace(const NamespaceDecl *ND) { - for (RecordDecl::decl_iterator I = ND->decls_begin(getContext()), - E = ND->decls_end(getContext()); + for (RecordDecl::decl_iterator I = ND->decls_begin(), E = ND->decls_end(); I != E; ++I) EmitTopLevelDecl(*I); } @@ -1463,8 +1469,7 @@ void CodeGenModule::EmitLinkageSpec(const LinkageSpecDecl *LSD) { return; } - for (RecordDecl::decl_iterator I = LSD->decls_begin(getContext()), - E = LSD->decls_end(getContext()); + for (RecordDecl::decl_iterator I = LSD->decls_begin(), E = LSD->decls_end(); I != E; ++I) EmitTopLevelDecl(*I); } @@ -1477,9 +1482,19 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { if (Diags.hasErrorOccurred()) return; + // Ignore dependent declarations. + if (D->getDeclContext() && D->getDeclContext()->isDependentContext()) + return; + switch (D->getKind()) { case Decl::CXXMethod: case Decl::Function: + // Skip function templates + if (cast<FunctionDecl>(D)->getDescribedFunctionTemplate()) + return; + + // Fall through + case Decl::Var: EmitGlobal(GlobalDecl(cast<ValueDecl>(D))); break; @@ -1490,6 +1505,8 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { break; // No code generation needed. case Decl::Using: + case Decl::ClassTemplate: + case Decl::FunctionTemplate: break; case Decl::CXXConstructor: EmitCXXConstructors(cast<CXXConstructorDecl>(D)); @@ -1530,7 +1547,7 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) { case Decl::ObjCMethod: { ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(D); // If this is not a prototype, emit the body. - if (OMD->getBody(getContext())) + if (OMD->getBody()) CodeGenFunction(*this).GenerateObjCMethod(OMD); break; } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index 4d50e8946bd6..ba9f1b28a07d 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -373,7 +373,8 @@ public: GVA_Internal, GVA_C99Inline, GVA_CXXInline, - GVA_StrongExternal + GVA_StrongExternal, + GVA_TemplateInstantiation }; private: diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index f31c610bf97d..1a30ea37fbbc 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -449,7 +449,7 @@ const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) { const RecordDecl *RD = cast<const RecordDecl>(TD); // There isn't any extra information for empty structures/unions. - if (RD->field_empty(getContext())) { + if (RD->field_empty()) { ResultType = llvm::StructType::get(std::vector<const llvm::Type*>()); } else { // Layout fields. @@ -532,8 +532,8 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) { std::vector<const llvm::Type*> LLVMFields; unsigned curField = 0; - for (RecordDecl::field_iterator Field = RD.field_begin(CGT.getContext()), - FieldEnd = RD.field_end(CGT.getContext()); + for (RecordDecl::field_iterator Field = RD.field_begin(), + FieldEnd = RD.field_end(); Field != FieldEnd; ++Field) { uint64_t offset = RL.getFieldOffset(curField); const llvm::Type *Ty = CGT.ConvertTypeForMemRecursive(Field->getType()); @@ -578,8 +578,8 @@ void RecordOrganizer::layoutStructFields(const ASTRecordLayout &RL) { /// all fields are added. void RecordOrganizer::layoutUnionFields(const ASTRecordLayout &RL) { unsigned curField = 0; - for (RecordDecl::field_iterator Field = RD.field_begin(CGT.getContext()), - FieldEnd = RD.field_end(CGT.getContext()); + for (RecordDecl::field_iterator Field = RD.field_begin(), + FieldEnd = RD.field_end(); Field != FieldEnd; ++Field) { // The offset should usually be zero, but bitfields could be strange uint64_t offset = RL.getFieldOffset(curField); diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index b5ad5acc0162..8018b4f45a84 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -87,7 +87,7 @@ static bool isInCLinkageSpecification(const Decl *D) { bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) { // Clang's "overloadable" attribute extension to C/C++ implies // name mangling (always). - if (!FD->hasAttr<OverloadableAttr>(Context)) { + if (!FD->hasAttr<OverloadableAttr>()) { // C functions are not mangled, and "main" is never mangled. if (!Context.getLangOptions().CPlusPlus || FD->isMain()) return false; @@ -111,7 +111,7 @@ bool CXXNameMangler::mangleFunctionDecl(const FunctionDecl *FD) { bool CXXNameMangler::mangle(const NamedDecl *D) { // Any decl can be declared with __asm("foo") on it, and this takes // precedence over all other naming in the .o file. - if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>(Context)) { + if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { // If we have an asm name, then we use it as the mangling. Out << '\01'; // LLVM IR Marker for __asm("foo") Out << ALA->getLabel(); @@ -170,7 +170,29 @@ void CXXNameMangler::mangleGuardVariable(const VarDecl *D) void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { // <encoding> ::= <function name> <bare-function-type> mangleName(FD); - mangleBareFunctionType(FD->getType()->getAsFunctionType(), false); + + // Whether the mangling of a function type includes the return type depends + // on the context and the nature of the function. The rules for deciding + // whether the return type is included are: + // + // 1. Template functions (names or types) have return types encoded, with + // the exceptions listed below. + // 2. Function types not appearing as part of a function name mangling, + // e.g. parameters, pointer types, etc., have return type encoded, with the + // exceptions listed below. + // 3. Non-template function names do not have return types encoded. + // + // The exceptions mentioned in (1) and (2) above, for which the return + // type is never included, are + // 1. Constructors. + // 2. Destructors. + // 3. Conversion operator functions, e.g. operator int. + bool MangleReturnType = false; + if (FD->getPrimaryTemplate() && + !(isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD) || + isa<CXXConversionDecl>(FD))) + MangleReturnType = true; + mangleBareFunctionType(FD->getType()->getAsFunctionType(), MangleReturnType); } static bool isStdNamespace(const DeclContext *DC) { @@ -253,6 +275,12 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { assert(false && "Can't mangle a using directive name!"); break; } + + if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) { + if (const TemplateArgumentList *TemplateArgs + = Function->getTemplateSpecializationArgs()) + mangleTemplateArgumentList(*TemplateArgs); + } } void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { diff --git a/lib/CodeGen/ModuleBuilder.cpp b/lib/CodeGen/ModuleBuilder.cpp index 9b85df61da05..4835454b47df 100644 --- a/lib/CodeGen/ModuleBuilder.cpp +++ b/lib/CodeGen/ModuleBuilder.cpp @@ -19,6 +19,7 @@ #include "clang/AST/Expr.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/TargetInfo.h" +#include "llvm/LLVMContext.h" #include "llvm/Module.h" #include "llvm/Target/TargetData.h" #include "llvm/Support/Compiler.h" @@ -37,8 +38,8 @@ namespace { llvm::OwningPtr<CodeGen::CodeGenModule> Builder; public: CodeGeneratorImpl(Diagnostic &diags, const std::string& ModuleName, - const CompileOptions &CO) - : Diags(diags), CompileOpts(CO), M(new llvm::Module(ModuleName)) {} + const CompileOptions &CO, llvm::LLVMContext& C) + : Diags(diags), CompileOpts(CO), M(new llvm::Module(ModuleName, C)) {} virtual ~CodeGeneratorImpl() {} @@ -95,6 +96,7 @@ namespace { CodeGenerator *clang::CreateLLVMCodeGen(Diagnostic &Diags, const std::string& ModuleName, - const CompileOptions &CO) { - return new CodeGeneratorImpl(Diags, ModuleName, CO); + const CompileOptions &CO, + llvm::LLVMContext& C) { + return new CodeGeneratorImpl(Diags, ModuleName, CO, C); } diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp index 361e5c0005cc..896dbd685037 100644 --- a/lib/CodeGen/TargetABIInfo.cpp +++ b/lib/CodeGen/TargetABIInfo.cpp @@ -74,8 +74,8 @@ static bool isEmptyRecord(ASTContext &Context, QualType T) { const RecordDecl *RD = RT->getDecl(); if (RD->hasFlexibleArrayMember()) return false; - for (RecordDecl::field_iterator i = RD->field_begin(Context), - e = RD->field_end(Context); i != e; ++i) + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) if (!isEmptyField(Context, *i)) return false; return true; @@ -99,8 +99,8 @@ static const Type *isSingleElementStruct(QualType T, ASTContext &Context) { return 0; const Type *Found = 0; - for (RecordDecl::field_iterator i = RD->field_begin(Context), - e = RD->field_end(Context); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) { const FieldDecl *FD = *i; QualType FT = FD->getType(); @@ -142,8 +142,8 @@ static bool is32Or64BitBasicType(QualType Ty, ASTContext &Context) { static bool areAllFields32Or64BitBasicType(const RecordDecl *RD, ASTContext &Context) { - for (RecordDecl::field_iterator i = RD->field_begin(Context), - e = RD->field_end(Context); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) { const FieldDecl *FD = *i; if (!is32Or64BitBasicType(FD->getType(), Context)) @@ -160,8 +160,8 @@ static bool areAllFields32Or64BitBasicType(const RecordDecl *RD, } static bool typeContainsSSEVector(const RecordDecl *RD, ASTContext &Context) { - for (RecordDecl::field_iterator i = RD->field_begin(Context), - e = RD->field_end(Context); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) { const FieldDecl *FD = *i; if (FD->getType()->isVectorType() && @@ -269,8 +269,8 @@ bool X86_32ABIInfo::shouldReturnTypeInRegister(QualType Ty, // Structure types are passed in register if all fields would be // passed in a register. - for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(Context), - e = RT->getDecl()->field_end(Context); i != e; ++i) { + for (RecordDecl::field_iterator i = RT->getDecl()->field_begin(), + e = RT->getDecl()->field_end(); i != e; ++i) { const FieldDecl *FD = *i; // Empty fields are ignored. @@ -707,8 +707,8 @@ void X86_64ABIInfo::classify(QualType Ty, // Reset Lo class, this will be recomputed. Current = NoClass; unsigned idx = 0; - for (RecordDecl::field_iterator i = RD->field_begin(Context), - e = RD->field_end(Context); i != e; ++i, ++idx) { + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i, ++idx) { uint64_t Offset = OffsetBase + Layout.getFieldOffset(idx); bool BitField = i->isBitField(); diff --git a/lib/Driver/ArgList.cpp b/lib/Driver/ArgList.cpp index 593694cfbbf6..54dd4bb77538 100644 --- a/lib/Driver/ArgList.cpp +++ b/lib/Driver/ArgList.cpp @@ -49,6 +49,35 @@ Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, bool Claim) const { return Res; } +Arg *ArgList::getLastArg(options::ID Id0, options::ID Id1, options::ID Id2, + bool Claim) const { + Arg *Res = 0; + Arg *A0 = getLastArg(Id0, false); + Arg *A1 = getLastArg(Id1, false); + Arg *A2 = getLastArg(Id2, false); + + int A0Idx = A0 ? A0->getIndex() : -1; + int A1Idx = A1 ? A1->getIndex() : -1; + int A2Idx = A2 ? A2->getIndex() : -1; + + if (A0Idx > A1Idx) { + if (A0Idx > A2Idx) + Res = A0; + else if (A2Idx != -1) + Res = A2; + } else { + if (A1Idx > A2Idx) + Res = A1; + else if (A2Idx != -1) + Res = A2; + } + + if (Claim && Res) + Res->claim(); + + return Res; +} + bool ArgList::hasFlag(options::ID Pos, options::ID Neg, bool Default) const { if (Arg *A = getLastArg(Pos, Neg)) return A->getOption().matches(Pos); diff --git a/lib/Driver/Compilation.cpp b/lib/Driver/Compilation.cpp index 1e044c6b8fdc..7e29b67769d3 100644 --- a/lib/Driver/Compilation.cpp +++ b/lib/Driver/Compilation.cpp @@ -21,8 +21,8 @@ #include <errno.h> using namespace clang::driver; -Compilation::Compilation(Driver &D, - ToolChain &_DefaultToolChain, +Compilation::Compilation(const Driver &D, + const ToolChain &_DefaultToolChain, InputArgList *_Args) : TheDriver(D), DefaultToolChain(_DefaultToolChain), Args(_Args) { } @@ -105,7 +105,8 @@ bool Compilation::CleanupFileList(const ArgStringList &Files, return Success; } -int Compilation::ExecuteCommand(const Command &C) const { +int Compilation::ExecuteCommand(const Command &C, + const Command *&FailingCommand) const { llvm::sys::Path Prog(C.getExecutable()); const char **Argv = new const char*[C.getArguments().size() + 2]; Argv[0] = C.getExecutable(); @@ -126,49 +127,31 @@ int Compilation::ExecuteCommand(const Command &C) const { getDriver().Diag(clang::diag::err_drv_command_failure) << Error; } + if (Res) + FailingCommand = &C; + delete[] Argv; return Res; } -int Compilation::ExecuteJob(const Job &J) const { +int Compilation::ExecuteJob(const Job &J, + const Command *&FailingCommand) const { if (const Command *C = dyn_cast<Command>(&J)) { - return ExecuteCommand(*C); + return ExecuteCommand(*C, FailingCommand); } else if (const PipedJob *PJ = dyn_cast<PipedJob>(&J)) { // Piped commands with a single job are easy. if (PJ->size() == 1) - return ExecuteCommand(**PJ->begin()); + return ExecuteCommand(**PJ->begin(), FailingCommand); + FailingCommand = *PJ->begin(); getDriver().Diag(clang::diag::err_drv_unsupported_opt) << "-pipe"; return 1; } else { const JobList *Jobs = cast<JobList>(&J); for (JobList::const_iterator it = Jobs->begin(), ie = Jobs->end(); it != ie; ++it) - if (int Res = ExecuteJob(**it)) + if (int Res = ExecuteJob(**it, FailingCommand)) return Res; return 0; } } - -int Compilation::Execute() const { - // Just print if -### was present. - if (getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { - PrintJob(llvm::errs(), Jobs, "\n", true); - return 0; - } - - // If there were errors building the compilation, quit now. - if (getDriver().getDiags().getNumErrors()) - return 1; - - int Res = ExecuteJob(Jobs); - - // Remove temp files. - CleanupFileList(TempFiles); - - // If the compilation failed, remove result files as well. - if (Res != 0 && !getArgs().hasArg(options::OPT_save_temps)) - CleanupFileList(ResultFiles, true); - - return Res; -} diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 8c2676b8cd7d..1b0b5615dfbc 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -217,6 +217,54 @@ Compilation *Driver::BuildCompilation(int argc, const char **argv) { return C; } +int Driver::ExecuteCompilation(const Compilation &C) const { + // Just print if -### was present. + if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { + C.PrintJob(llvm::errs(), C.getJobs(), "\n", true); + return 0; + } + + // If there were errors building the compilation, quit now. + if (getDiags().getNumErrors()) + return 1; + + const Command *FailingCommand = 0; + int Res = C.ExecuteJob(C.getJobs(), FailingCommand); + + // Remove temp files. + C.CleanupFileList(C.getTempFiles()); + + // If the compilation failed, remove result files as well. + if (Res != 0 && !C.getArgs().hasArg(options::OPT_save_temps)) + C.CleanupFileList(C.getResultFiles(), true); + + // Print extra information about abnormal failures, if possible. + if (Res) { + // This is ad-hoc, but we don't want to be excessively noisy. If the result + // status was 1, assume the command failed normally. In particular, if it + // was the compiler then assume it gave a reasonable error code. Failures in + // other tools are less common, and they generally have worse diagnostics, + // so always print the diagnostic there. + const Action &Source = FailingCommand->getSource(); + bool IsFriendlyTool = (isa<PreprocessJobAction>(Source) || + isa<PrecompileJobAction>(Source) || + isa<AnalyzeJobAction>(Source) || + isa<CompileJobAction>(Source)); + + if (!IsFriendlyTool || Res != 1) { + // FIXME: See FIXME above regarding result code interpretation. + if (Res < 0) + Diag(clang::diag::err_drv_command_signalled) + << Source.getClassName() << -Res; + else + Diag(clang::diag::err_drv_command_failed) + << Source.getClassName() << Res; + } + } + + return Res; +} + void Driver::PrintOptions(const ArgList &Args) const { unsigned i = 0; for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); @@ -1205,6 +1253,8 @@ const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { return createDarwinHostInfo(*this, Triple); case llvm::Triple::DragonFly: return createDragonFlyHostInfo(*this, Triple); + case llvm::Triple::OpenBSD: + return createOpenBSDHostInfo(*this, Triple); case llvm::Triple::FreeBSD: return createFreeBSDHostInfo(*this, Triple); case llvm::Triple::Linux: diff --git a/lib/Driver/HostInfo.cpp b/lib/Driver/HostInfo.cpp index 831e11b98e42..602a97713505 100644 --- a/lib/Driver/HostInfo.cpp +++ b/lib/Driver/HostInfo.cpp @@ -234,6 +234,57 @@ ToolChain *UnknownHostInfo::getToolChain(const ArgList &Args, return TC; } +// OpenBSD Host Info + +/// OpenBSDHostInfo - OpenBSD host information implementation. +class OpenBSDHostInfo : public HostInfo { + /// Cache of tool chains we have created. + mutable llvm::StringMap<ToolChain*> ToolChains; + +public: + OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple) + : HostInfo(D, Triple) {} + ~OpenBSDHostInfo(); + + virtual bool useDriverDriver() const; + + virtual types::ID lookupTypeForExtension(const char *Ext) const { + return types::lookupTypeForExtension(Ext); + } + + virtual ToolChain *getToolChain(const ArgList &Args, + const char *ArchName) const; +}; + +OpenBSDHostInfo::~OpenBSDHostInfo() { + for (llvm::StringMap<ToolChain*>::iterator + it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) + delete it->second; +} + +bool OpenBSDHostInfo::useDriverDriver() const { + return false; +} + +ToolChain *OpenBSDHostInfo::getToolChain(const ArgList &Args, + const char *ArchName) const { + assert(!ArchName && + "Unexpected arch name on platform without driver driver support."); + + std::string Arch = getArchName(); + ArchName = Arch.c_str(); + + ToolChain *&TC = ToolChains[ArchName]; + if (!TC) { + llvm::Triple TCTriple(getTriple()); + TCTriple.setArchName(ArchName); + + TC = new toolchains::OpenBSD(*this, TCTriple); + } + + return TC; +} + // FreeBSD Host Info /// FreeBSDHostInfo - FreeBSD host information implementation. @@ -417,6 +468,12 @@ clang::driver::createDarwinHostInfo(const Driver &D, } const HostInfo * +clang::driver::createOpenBSDHostInfo(const Driver &D, + const llvm::Triple& Triple) { + return new OpenBSDHostInfo(D, Triple); +} + +const HostInfo * clang::driver::createFreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple) { return new FreeBSDHostInfo(D, Triple); diff --git a/lib/Driver/Job.cpp b/lib/Driver/Job.cpp index 222cf15db60f..1b0ea18453d0 100644 --- a/lib/Driver/Job.cpp +++ b/lib/Driver/Job.cpp @@ -14,8 +14,10 @@ using namespace clang::driver; Job::~Job() {} -Command::Command(const char *_Executable, const ArgStringList &_Arguments) - : Job(CommandClass), Executable(_Executable), Arguments(_Arguments) { +Command::Command(const Action &_Source, const char *_Executable, + const ArgStringList &_Arguments) + : Job(CommandClass), Source(_Source), Executable(_Executable), + Arguments(_Arguments) { } PipedJob::PipedJob() : Job(PipedJobClass) {} diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index 436d343dd021..f663ed49536e 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -384,6 +384,36 @@ DerivedArgList *Generic_GCC::TranslateArgs(InputArgList &Args) const { return new DerivedArgList(Args, true); } +/// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. + +OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple) + : Generic_GCC(Host, Triple) { + getFilePaths().push_back(getHost().getDriver().Dir + "/../lib"); + getFilePaths().push_back("/usr/lib"); +} + +Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA) const { + Action::ActionClass Key; + if (getHost().getDriver().ShouldUseClangCompiler(C, JA, getArchName())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); + + Tool *&T = Tools[Key]; + if (!T) { + switch (Key) { + case Action::AssembleJobClass: + T = new tools::openbsd::Assemble(*this); break; + case Action::LinkJobClass: + T = new tools::openbsd::Link(*this); break; + default: + T = &Generic_GCC::SelectTool(C, JA); + } + } + + return *T; +} + /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32) diff --git a/lib/Driver/ToolChains.h b/lib/Driver/ToolChains.h index 3ecd1715da96..c921d52864f0 100644 --- a/lib/Driver/ToolChains.h +++ b/lib/Driver/ToolChains.h @@ -107,6 +107,13 @@ public: virtual const char *GetDefaultRelocationModel() const { return "pic"; } }; +class VISIBILITY_HIDDEN OpenBSD : public Generic_GCC { +public: + OpenBSD(const HostInfo &Host, const llvm::Triple& Triple); + + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA) const; +}; + class VISIBILITY_HIDDEN FreeBSD : public Generic_GCC { public: FreeBSD(const HostInfo &Host, const llvm::Triple& Triple, bool Lib32); diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index bfc247a015ff..d198a54cf7dd 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -498,6 +498,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fvisibility_EQ); Args.AddLastArg(CmdArgs, options::OPT_fwritable_strings); + // Forward stack protector flags. + if (Arg *A = Args.getLastArg(options::OPT_fno_stack_protector, + options::OPT_fstack_protector_all, + options::OPT_fstack_protector)) { + if (A->getOption().matches(options::OPT_fno_stack_protector)) + CmdArgs.push_back("--stack-protector=0"); + else if (A->getOption().matches(options::OPT_fstack_protector)) + CmdArgs.push_back("--stack-protector=1"); + else + CmdArgs.push_back("--stack-protector=2"); + } + // Forward -f options with positive and negative forms; we translate // these by hand. @@ -616,7 +628,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, "clang-cc").c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); // Explicitly warn that these options are unsupported, even though // we are allowing compilation to continue. @@ -747,7 +759,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, getToolChain().getHost().getDriver().CCCGenericGCCName.c_str(); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, GCCName).c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } void gcc::Preprocess::RenderExtraToolArgs(ArgStringList &CmdArgs) const { @@ -1123,7 +1135,7 @@ void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA, const char *CC1Name = getCC1Name(Inputs[0].getType()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name).c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, @@ -1211,7 +1223,7 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, const char *CC1Name = getCC1Name(Inputs[0].getType()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, CC1Name).c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, @@ -1264,7 +1276,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } /// Helper routine for seeing if we should use dsymutil; this is a @@ -1688,7 +1700,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); // Find the first non-empty base input (we want to ignore linker // inputs). @@ -1718,7 +1730,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(getToolChain().GetProgramPath(C, "dsymutil").c_str()); ArgStringList CmdArgs; CmdArgs.push_back(Output.getFilename()); - C.getJobs().addCommand(new Command(Exec, CmdArgs)); + C.getJobs().addCommand(new Command(JA, Exec, CmdArgs)); } } } @@ -1744,9 +1756,121 @@ void darwin::Lipo::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, "lipo").c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); +} + +void openbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const +{ + ArgStringList CmdArgs; + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, + options::OPT_Xassembler); + + CmdArgs.push_back("-o"); + if (Output.isPipe()) + CmdArgs.push_back("-"); + else + CmdArgs.push_back(Output.getFilename()); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + if (II.isPipe()) + CmdArgs.push_back("-"); + else + CmdArgs.push_back(II.getFilename()); + } + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str()); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } +void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const Driver &D = getToolChain().getHost().getDriver(); + ArgStringList CmdArgs; + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-Bstatic"); + } else { + CmdArgs.push_back("--eh-frame-hdr"); + if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-Bshareable"); + } else { + CmdArgs.push_back("-dynamic-linker"); + CmdArgs.push_back("/usr/libexec/ld.so"); + } + } + + if (Output.isPipe()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back("-"); + } else if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Invalid output."); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o").c_str())); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o").c_str())); + } else { + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o").c_str())); + } + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + Args.AddAllArgs(CmdArgs, options::OPT_e); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + + // Don't try to pass LLVM inputs to a generic gcc. + if (II.getType() == types::TY_LLVMBC) + D.Diag(clang::diag::err_drv_no_linker_llvm_support) + << getToolChain().getTripleString().c_str(); + + if (II.isPipe()) + CmdArgs.push_back("-"); + else if (II.isFilename()) + CmdArgs.push_back(II.getFilename()); + else + II.getInputArg().renderAsInput(Args, CmdArgs); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + + if (Args.hasArg(options::OPT_pthread)) + CmdArgs.push_back("-pthread"); + CmdArgs.push_back("-lc"); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o").c_str())); + else + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o").c_str())); + } + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str()); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); +} void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, Job &Dest, const InputInfo &Output, @@ -1781,7 +1905,7 @@ void freebsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -1892,7 +2016,7 @@ void freebsd::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } /// DragonFly Tools @@ -1931,7 +2055,7 @@ void dragonfly::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, "as").c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, @@ -2055,5 +2179,5 @@ void dragonfly::Link::ConstructJob(Compilation &C, const JobAction &JA, const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(C, "ld").c_str()); - Dest.addCommand(new Command(Exec, CmdArgs)); + Dest.addCommand(new Command(JA, Exec, CmdArgs)); } diff --git a/lib/Driver/Tools.h b/lib/Driver/Tools.h index db108db2b4d7..ab7349600907 100644 --- a/lib/Driver/Tools.h +++ b/lib/Driver/Tools.h @@ -241,6 +241,40 @@ namespace darwin { }; } + /// openbsd -- Directly call GNU Binutils assembler and linker +namespace openbsd { + class VISIBILITY_HIDDEN Assemble : public Tool { + public: + Assemble(const ToolChain &TC) : Tool("openbsd::Assemble", TC) {} + + virtual bool acceptsPipedInput() const { return true; } + virtual bool canPipeOutput() const { return true; } + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; + class VISIBILITY_HIDDEN Link : public Tool { + public: + Link(const ToolChain &TC) : Tool("openbsd::Link", TC) {} + + virtual bool acceptsPipedInput() const { return true; } + virtual bool canPipeOutput() const { return true; } + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + Job &Dest, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; +} + /// freebsd -- Directly call GNU Binutils assembler and linker namespace freebsd { class VISIBILITY_HIDDEN Assemble : public Tool { diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index 5844be826cf7..8f0ad13319eb 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -44,7 +44,7 @@ namespace { virtual void HandleTranslationUnit(ASTContext &Context) { PrintingPolicy Policy = Context.PrintingPolicy; Policy.Dump = Dump; - Context.getTranslationUnitDecl()->print(Out, Context, Policy); + Context.getTranslationUnitDecl()->print(Out, Policy); } }; } // end anonymous namespace @@ -70,8 +70,8 @@ namespace { virtual void HandleTranslationUnit(ASTContext &Ctx) { Doc.addSubNode("TranslationUnit"); for (DeclContext::decl_iterator - D = Ctx.getTranslationUnitDecl()->decls_begin(Ctx), - DEnd = Ctx.getTranslationUnitDecl()->decls_end(Ctx); + D = Ctx.getTranslationUnitDecl()->decls_begin(), + DEnd = Ctx.getTranslationUnitDecl()->decls_end(); D != DEnd; ++D) { @@ -114,7 +114,7 @@ namespace { void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - FD->print(llvm::errs(), *Context); + FD->print(llvm::errs()); if (FD->getBodyIfAvailable()) { llvm::cerr << '\n'; @@ -125,7 +125,7 @@ void ASTViewer::HandleTopLevelSingleDecl(Decl *D) { } if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { - MD->print(llvm::errs(), *Context); + MD->print(llvm::errs()); if (MD->getBody()) { llvm::cerr << '\n'; @@ -340,10 +340,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << "\n"; // Print decls in the DeclContext. - // FIXME: Should not use a NULL DeclContext! - ASTContext *Context = 0; - for (DeclContext::decl_iterator I = DC->decls_begin(*Context), - E = DC->decls_end(*Context); + for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { for (unsigned i = 0; i < Indentation; ++i) Out << " "; diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp index d8fa141d8cb6..06af2d9a4e58 100644 --- a/lib/Frontend/AnalysisConsumer.cpp +++ b/lib/Frontend/AnalysisConsumer.cpp @@ -307,7 +307,7 @@ void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) { Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName()) break; - Stmt* Body = FD->getBody(*Ctx); + Stmt* Body = FD->getBody(); if (Body) HandleCode(FD, Body, FunctionActions); break; } @@ -341,8 +341,8 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { if (!ObjCImplementationActions.empty()) { TranslationUnitDecl *TUD = C.getTranslationUnitDecl(); - for (DeclContext::decl_iterator I = TUD->decls_begin(C), - E = TUD->decls_end(C); + for (DeclContext::decl_iterator I = TUD->decls_begin(), + E = TUD->decls_end(); I != E; ++I) if (ObjCImplementationDecl* ID = dyn_cast<ObjCImplementationDecl>(*I)) HandleCode(ID, 0, ObjCImplementationActions); @@ -479,14 +479,16 @@ static void ActionDisplayLiveVariables(AnalysisManager& mgr) { static void ActionCFGDump(AnalysisManager& mgr) { if (CFG* c = mgr.getCFG()) { mgr.DisplayFunction(); - c->dump(); + LangOptions LO; // FIXME! + c->dump(LO); } } static void ActionCFGView(AnalysisManager& mgr) { if (CFG* c = mgr.getCFG()) { mgr.DisplayFunction(); - c->viewCFG(); + LangOptions LO; // FIXME! + c->viewCFG(LO); } } diff --git a/lib/Frontend/Backend.cpp b/lib/Frontend/Backend.cpp index d8f8625d6740..1c536b07cee2 100644 --- a/lib/Frontend/Backend.cpp +++ b/lib/Frontend/Backend.cpp @@ -75,13 +75,14 @@ namespace { public: BackendConsumer(BackendAction action, Diagnostic &Diags, const LangOptions &langopts, const CompileOptions &compopts, - const std::string &infile, llvm::raw_ostream* OS) : + const std::string &infile, llvm::raw_ostream* OS, + LLVMContext& C) : Action(action), CompileOpts(compopts), AsmOutStream(OS), LLVMIRGeneration("LLVM IR Generation Time"), CodeGenerationTime("Code Generation Time"), - Gen(CreateLLVMCodeGen(Diags, infile, compopts)), + Gen(CreateLLVMCodeGen(Diags, infile, compopts, C)), TheModule(0), TheTargetData(0), ModuleProvider(0), CodeGenPasses(0), PerModulePasses(0), PerFunctionPasses(0) { @@ -359,6 +360,8 @@ ASTConsumer *clang::CreateBackendConsumer(BackendAction Action, const LangOptions &LangOpts, const CompileOptions &CompileOpts, const std::string& InFile, - llvm::raw_ostream* OS) { - return new BackendConsumer(Action, Diags, LangOpts, CompileOpts, InFile, OS); + llvm::raw_ostream* OS, + LLVMContext& C) { + return new BackendConsumer(Action, Diags, LangOpts, CompileOpts, + InFile, OS, C); } diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp index 5c21999bfa05..68f931fb6c69 100644 --- a/lib/Frontend/DeclXML.cpp +++ b/lib/Frontend/DeclXML.cpp @@ -34,8 +34,8 @@ class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> void addSubNodes(RecordDecl* RD) { - for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i) - { + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i) { Visit(*i); Doc.toParent(); } @@ -43,8 +43,8 @@ class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> void addSubNodes(EnumDecl* ED) { - for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i) - { + for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(), + e = ED->enumerator_end(); i != e; ++i) { Visit(*i); Doc.toParent(); } @@ -147,7 +147,7 @@ void DocumentXML::writeDeclToXML(Decl *D) DeclPrinter(*this).Visit(D); if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - if (Stmt *Body = FD->getBody(*Ctx)) { + if (Stmt *Body = FD->getBody()) { addSubNode("Body"); PrintStmt(Body); toParent(); diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 7a2b3a7317b4..8c80786210ff 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -178,6 +178,14 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang) { AddPath("/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4/backward", System, true, false, false); + // Gentoo amd64 stable + AddPath("/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4", System, + true, false, false); + AddPath("/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/" + "i686-pc-linux-gnu", System, true, false, false); + AddPath("/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4/backward", + System, true, false, false); + // DragonFly AddPath("/usr/include/c++/4.1", System, true, false, false); diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 730414e44822..e41dfdda07e9 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -383,7 +383,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI, // 16-bit targets doesn't necessarily have a 64-bit type. if (TI.getLongLongWidth() == 64) - DefineBuiltinMacro(Buf, "__INT64_TYPE__=long long"); + DefineType("__INT64_TYPE__", TI.getInt64Type(), Buf); // Add __builtin_va_list typedef. { @@ -423,7 +423,12 @@ static void InitializePredefinedMacros(const TargetInfo &TI, sprintf(MacroBuf, "__DECIMAL_DIG__=%d", PickFP(&TI.getLongDoubleFormat(), -1/*FIXME*/, 17, 21, 33, 36)); DefineBuiltinMacro(Buf, MacroBuf); - + + if (LangOpts.getStackProtectorMode() == LangOptions::SSPOn) + DefineBuiltinMacro(Buf, "__SSP__=1"); + else if (LangOpts.getStackProtectorMode() == LangOptions::SSPReq) + DefineBuiltinMacro(Buf, "__SSP_ALL__=2"); + // Get other target #defines. TI.getTargetDefines(LangOpts, Buf); } diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index 765655b01dd0..95b166159e7d 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -344,7 +344,8 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context) IdentifierOffsets(0), MethodPoolLookupTable(0), MethodPoolLookupTableData(0), TotalSelectorsInMethodPool(0), SelectorOffsets(0), - TotalNumSelectors(0), NumStatHits(0), NumStatMisses(0), + TotalNumSelectors(0), Comments(0), NumComments(0), + NumStatHits(0), NumStatMisses(0), NumSLocEntriesRead(0), NumStatementsRead(0), NumMacrosRead(0), NumMethodPoolSelectorsRead(0), NumMethodPoolMisses(0), NumLexicalDeclContextsRead(0), NumVisibleDeclContextsRead(0) { } @@ -1350,6 +1351,11 @@ PCHReader::ReadPCHBlock() { case pch::ORIGINAL_FILE_NAME: OriginalFileName.assign(BlobStart, BlobLen); break; + + case pch::COMMENT_RANGES: + Comments = (SourceRange *)BlobStart; + NumComments = BlobLen / sizeof(SourceRange); + break; } } Error("premature end of bitstream in PCH file"); @@ -1664,6 +1670,12 @@ bool PCHReader::ParseLanguageOptions( return false; } +void PCHReader::ReadComments(std::vector<SourceRange> &Comments) { + Comments.resize(NumComments); + std::copy(this->Comments, this->Comments + NumComments, + Comments.begin()); +} + /// \brief Read and return the type at the given offset. /// /// This routine actually reads the record corresponding to the type diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 3f6ae354dc3f..15b54a2d4fc6 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -80,7 +80,7 @@ void PCHDeclReader::VisitDecl(Decl *D) { D->setLocation(SourceLocation::getFromRawEncoding(Record[Idx++])); D->setInvalidDecl(Record[Idx++]); if (Record[Idx++]) - D->addAttr(*Reader.getContext(), Reader.ReadAttributes()); + D->addAttr(Reader.ReadAttributes()); D->setImplicit(Record[Idx++]); D->setUsed(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); diff --git a/lib/Frontend/PCHReaderStmt.cpp b/lib/Frontend/PCHReaderStmt.cpp index d09638806169..eccb53bf8189 100644 --- a/lib/Frontend/PCHReaderStmt.cpp +++ b/lib/Frontend/PCHReaderStmt.cpp @@ -1133,6 +1133,5 @@ Stmt *PCHReader::ReadStmt(llvm::BitstreamCursor &Cursor) { StmtStack.push_back(S); } assert(StmtStack.size() == 1 && "Extra expressions on stack!"); - SwitchCaseStmts.clear(); return StmtStack.back(); } diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index e93219e01d5c..3bfc9e89d10a 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -374,7 +374,8 @@ void PCHWriter::WriteBlockInfoBlock() { RECORD(STAT_CACHE); RECORD(EXT_VECTOR_DECLS); RECORD(OBJC_CATEGORY_IMPLEMENTATIONS); - + RECORD(COMMENT_RANGES); + // SourceManager Block. BLOCK(SOURCE_MANAGER_BLOCK); RECORD(SM_SLOC_FILE_ENTRY); @@ -989,6 +990,24 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) { Stream.ExitBlock(); } +void PCHWriter::WriteComments(ASTContext &Context) { + using namespace llvm; + + if (Context.Comments.empty()) + return; + + BitCodeAbbrev *CommentAbbrev = new BitCodeAbbrev(); + CommentAbbrev->Add(BitCodeAbbrevOp(pch::COMMENT_RANGES)); + CommentAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + unsigned CommentCode = Stream.EmitAbbrev(CommentAbbrev); + + RecordData Record; + Record.push_back(pch::COMMENT_RANGES); + Stream.EmitRecordWithBlob(CommentCode, Record, + (const char*)&Context.Comments[0], + Context.Comments.size() * sizeof(SourceRange)); +} + //===----------------------------------------------------------------------===// // Type Serialization //===----------------------------------------------------------------------===// @@ -1064,14 +1083,13 @@ void PCHWriter::WriteTypesBlock(ASTContext &Context) { /// bistream, or 0 if no block was written. uint64_t PCHWriter::WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC) { - if (DC->decls_empty(Context)) + if (DC->decls_empty()) return 0; uint64_t Offset = Stream.GetCurrentBitNo(); RecordData Record; - for (DeclContext::decl_iterator D = DC->decls_begin(Context), - DEnd = DC->decls_end(Context); - D != DEnd; ++D) + for (DeclContext::decl_iterator D = DC->decls_begin(), DEnd = DC->decls_end(); + D != DEnd; ++D) AddDeclRef(*D, Record); ++NumLexicalDeclContexts; @@ -1097,7 +1115,7 @@ uint64_t PCHWriter::WriteDeclContextVisibleBlock(ASTContext &Context, return 0; // Force the DeclContext to build a its name-lookup table. - DC->lookup(Context, DeclarationName()); + DC->lookup(DeclarationName()); // Serialize the contents of the mapping used for lookup. Note that, // although we have two very different code paths, the serialized @@ -1747,7 +1765,8 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls) { WriteStatCache(*StatCalls); WriteSourceManagerBlock(Context.getSourceManager(), PP); WritePreprocessor(PP); - + WriteComments(Context); + // Keep writing types and declarations until all types and // declarations have been written. do { diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index 44da4d72f2df..a6843e1b9efd 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -146,7 +146,7 @@ void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { VisitValueDecl(D); Record.push_back(D->isThisDeclarationADefinition()); if (D->isThisDeclarationADefinition()) - Writer.AddStmt(D->getBody(Context)); + Writer.AddStmt(D->getBody()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->isInline()); @@ -172,7 +172,7 @@ void PCHDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { // Unlike C/C++, method bodies will never be in header files. Record.push_back(D->getBody() != 0); if (D->getBody() != 0) { - Writer.AddStmt(D->getBody(Context)); + Writer.AddStmt(D->getBody()); Writer.AddDeclRef(D->getSelfDecl(), Record); Writer.AddDeclRef(D->getCmdDecl(), Record); } @@ -520,7 +520,7 @@ void PCHWriter::WriteDeclsBlock(ASTContext &Context) { // If the declaration had any attributes, write them now. if (D->hasAttrs()) - WriteAttributeRecord(D->getAttrs(Context)); + WriteAttributeRecord(D->getAttrs()); // Flush any expressions that were written as part of this declaration. FlushStmts(); diff --git a/lib/Frontend/PCHWriterStmt.cpp b/lib/Frontend/PCHWriterStmt.cpp index c63c03c8823f..5235326e9ffd 100644 --- a/lib/Frontend/PCHWriterStmt.cpp +++ b/lib/Frontend/PCHWriterStmt.cpp @@ -826,5 +826,4 @@ void PCHWriter::FlushStmts() { } StmtsToEmit.clear(); - SwitchCaseIDs.clear(); } diff --git a/lib/Frontend/ResolveLocation.cpp b/lib/Frontend/ResolveLocation.cpp index a5f0d1f16365..d7a9b4852a96 100644 --- a/lib/Frontend/ResolveLocation.cpp +++ b/lib/Frontend/ResolveLocation.cpp @@ -163,7 +163,7 @@ void StmtLocResolver::VisitStmt(Stmt *Node) { void DeclLocResolver::VisitDeclContext(DeclContext *DC) { DeclLocResolver DLR(Ctx, Loc); for (DeclContext::decl_iterator - I = DC->decls_begin(Ctx), E = DC->decls_end(Ctx); I != E; ++I) { + I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { DLR.Visit(*I); if (DLR.Finished()) { if (DLR.FoundIt()) @@ -211,7 +211,7 @@ void DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) { // Finally, search through the body of the function. if (D->isThisDeclarationADefinition()) { StmtLocResolver SLR(Ctx, Loc); - SLR.Visit(D->getBody(Ctx)); + SLR.Visit(D->getBody()); if (SLR.FoundIt()) { llvm::tie(Dcl, Stm) = SLR.getResult(); // If we didn't find a more immediate 'parent' declaration for the @@ -287,7 +287,7 @@ void LocResolverBase::FixRange(SourceRange &Range) { void LocResolverBase::print(Decl *D) { llvm::raw_ostream &OS = llvm::outs(); OS << "#### DECL ####\n"; - D->print(OS, Ctx); + D->print(OS); OS << " <"; D->getLocStart().print(OS, Ctx.getSourceManager()); OS << " > - <"; @@ -299,7 +299,7 @@ void LocResolverBase::print(Decl *D) { void LocResolverBase::print(Stmt *Node) { llvm::raw_ostream &OS = llvm::outs(); OS << "#### STMT ####\n"; - Node->printPretty(OS, Ctx); + Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions())); OS << " <"; Node->getLocStart().print(OS, Ctx.getSourceManager()); OS << " > - <"; diff --git a/lib/Frontend/RewriteBlocks.cpp b/lib/Frontend/RewriteBlocks.cpp index d20d5cd152c4..bc855fa87912 100644 --- a/lib/Frontend/RewriteBlocks.cpp +++ b/lib/Frontend/RewriteBlocks.cpp @@ -306,39 +306,33 @@ void RewriteBlocks::RewriteMethodDecl(ObjCMethodDecl *Method) { void RewriteBlocks::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { for (ObjCInterfaceDecl::instmeth_iterator - I = ClassDecl->instmeth_begin(*Context), - E = ClassDecl->instmeth_end(*Context); + I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); I != E; ++I) RewriteMethodDecl(*I); for (ObjCInterfaceDecl::classmeth_iterator - I = ClassDecl->classmeth_begin(*Context), - E = ClassDecl->classmeth_end(*Context); + I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); I != E; ++I) RewriteMethodDecl(*I); } void RewriteBlocks::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { for (ObjCCategoryDecl::instmeth_iterator - I = CatDecl->instmeth_begin(*Context), - E = CatDecl->instmeth_end(*Context); + I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); I != E; ++I) RewriteMethodDecl(*I); for (ObjCCategoryDecl::classmeth_iterator - I = CatDecl->classmeth_begin(*Context), - E = CatDecl->classmeth_end(*Context); + I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); I != E; ++I) RewriteMethodDecl(*I); } void RewriteBlocks::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { for (ObjCProtocolDecl::instmeth_iterator - I = PDecl->instmeth_begin(*Context), - E = PDecl->instmeth_end(*Context); + I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); I != E; ++I) RewriteMethodDecl(*I); for (ObjCProtocolDecl::classmeth_iterator - I = PDecl->classmeth_begin(*Context), - E = PDecl->classmeth_end(*Context); + I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); I != E; ++I) RewriteMethodDecl(*I); } @@ -724,7 +718,8 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) { BlockCall += "((struct __block_impl *)"; std::string closureExprBufStr; llvm::raw_string_ostream closureExprBuf(closureExprBufStr); - Exp->getCallee()->printPretty(closureExprBuf, *Context); + Exp->getCallee()->printPretty(closureExprBuf, *Context, 0, + PrintingPolicy(LangOpts)); BlockCall += closureExprBuf.str(); BlockCall += ")->FuncPtr)"; @@ -735,7 +730,7 @@ std::string RewriteBlocks::SynthesizeBlockCall(CallExpr *Exp) { E = Exp->arg_end(); I != E; ++I) { std::string syncExprBufS; llvm::raw_string_ostream Buf(syncExprBufS); - (*I)->printPretty(Buf, *Context); + (*I)->printPretty(Buf, *Context, 0, PrintingPolicy(LangOpts)); BlockCall += ", " + Buf.str(); } return BlockCall; @@ -1088,7 +1083,7 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) { RewriteFunctionProtoType(FD->getType(), FD); // FIXME: Handle CXXTryStmt - if (CompoundStmt *Body = FD->getCompoundBody(*Context)) { + if (CompoundStmt *Body = FD->getCompoundBody()) { CurFunctionDef = FD; FD->setBody(cast_or_null<CompoundStmt>(RewriteFunctionBody(Body))); // This synthesizes and inserts the block "impl" struct, invoke function, @@ -1100,7 +1095,7 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) { } if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { RewriteMethodDecl(MD); - if (Stmt *Body = MD->getBody(*Context)) { + if (Stmt *Body = MD->getBody()) { CurMethodDef = MD; RewriteFunctionBody(Body); InsertBlockLiteralsWithinMethod(MD); @@ -1112,7 +1107,7 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) { RewriteBlockPointerDecl(VD); if (VD->getInit()) { if (BlockExpr *CBE = dyn_cast<BlockExpr>(VD->getInit())) { - RewriteFunctionBody(CBE->getBody(*Context)); + RewriteFunctionBody(CBE->getBody()); // We've just rewritten the block body in place. // Now we snarf the rewritten text and stash it away for later use. @@ -1146,8 +1141,8 @@ void RewriteBlocks::HandleDeclInMainFile(Decl *D) { } if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { if (RD->isDefinition()) { - for (RecordDecl::field_iterator i = RD->field_begin(*Context), - e = RD->field_end(*Context); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i) { FieldDecl *FD = *i; if (isBlockPointerType(FD->getType())) RewriteBlockPointerDecl(FD); diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index dce271070e03..cf31f2b2deab 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -171,7 +171,7 @@ namespace { // Get the new text. std::string SStr; llvm::raw_string_ostream S(SStr); - New->printPretty(S, *Context); + New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts)); const std::string &Str = S.str(); // If replacement succeeded or warning disabled return with no warning. @@ -597,8 +597,8 @@ void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) { RewriteForwardProtocolDecl(FP); } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { // Recurse into linkage specifications - for (DeclContext::decl_iterator DI = LSD->decls_begin(*Context), - DIEnd = LSD->decls_end(*Context); + for (DeclContext::decl_iterator DI = LSD->decls_begin(), + DIEnd = LSD->decls_end(); DI != DIEnd; ++DI) HandleTopLevelSingleDecl(*DI); } @@ -789,13 +789,11 @@ void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) { ReplaceText(LocStart, 0, "// ", 3); for (ObjCCategoryDecl::instmeth_iterator - I = CatDecl->instmeth_begin(*Context), - E = CatDecl->instmeth_end(*Context); + I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); for (ObjCCategoryDecl::classmeth_iterator - I = CatDecl->classmeth_begin(*Context), - E = CatDecl->classmeth_end(*Context); + I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); @@ -812,13 +810,11 @@ void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) { ReplaceText(LocStart, 0, "// ", 3); for (ObjCProtocolDecl::instmeth_iterator - I = PDecl->instmeth_begin(*Context), - E = PDecl->instmeth_end(*Context); + I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); for (ObjCProtocolDecl::classmeth_iterator - I = PDecl->classmeth_begin(*Context), - E = PDecl->classmeth_end(*Context); + I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); @@ -986,14 +982,14 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { InsertText(CID->getLocStart(), "// ", 3); for (ObjCCategoryImplDecl::instmeth_iterator - I = IMD ? IMD->instmeth_begin(*Context) : CID->instmeth_begin(*Context), - E = IMD ? IMD->instmeth_end(*Context) : CID->instmeth_end(*Context); + I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(), + E = IMD ? IMD->instmeth_end() : CID->instmeth_end(); I != E; ++I) { std::string ResultStr; ObjCMethodDecl *OMD = *I; RewriteObjCMethodDecl(OMD, ResultStr); SourceLocation LocStart = OMD->getLocStart(); - SourceLocation LocEnd = OMD->getCompoundBody(*Context)->getLocStart(); + SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); @@ -1002,14 +998,14 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { } for (ObjCCategoryImplDecl::classmeth_iterator - I = IMD ? IMD->classmeth_begin(*Context) : CID->classmeth_begin(*Context), - E = IMD ? IMD->classmeth_end(*Context) : CID->classmeth_end(*Context); + I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(), + E = IMD ? IMD->classmeth_end() : CID->classmeth_end(); I != E; ++I) { std::string ResultStr; ObjCMethodDecl *OMD = *I; RewriteObjCMethodDecl(OMD, ResultStr); SourceLocation LocStart = OMD->getLocStart(); - SourceLocation LocEnd = OMD->getCompoundBody(*Context)->getLocStart(); + SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart(); const char *startBuf = SM->getCharacterData(LocStart); const char *endBuf = SM->getCharacterData(LocEnd); @@ -1017,8 +1013,8 @@ void RewriteObjC::RewriteImplementationDecl(Decl *OID) { ResultStr.c_str(), ResultStr.size()); } for (ObjCCategoryImplDecl::propimpl_iterator - I = IMD ? IMD->propimpl_begin(*Context) : CID->propimpl_begin(*Context), - E = IMD ? IMD->propimpl_end(*Context) : CID->propimpl_end(*Context); + I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(), + E = IMD ? IMD->propimpl_end() : CID->propimpl_end(); I != E; ++I) { RewritePropertyImplDecl(*I, IMD, CID); } @@ -1047,17 +1043,15 @@ void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) { } SynthesizeObjCInternalStruct(ClassDecl, ResultStr); - for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(*Context), - E = ClassDecl->prop_end(*Context); I != E; ++I) + for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(), + E = ClassDecl->prop_end(); I != E; ++I) RewriteProperty(*I); for (ObjCInterfaceDecl::instmeth_iterator - I = ClassDecl->instmeth_begin(*Context), - E = ClassDecl->instmeth_end(*Context); + I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); for (ObjCInterfaceDecl::classmeth_iterator - I = ClassDecl->classmeth_begin(*Context), - E = ClassDecl->classmeth_end(*Context); + I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end(); I != E; ++I) RewriteMethodDeclaration(*I); @@ -1149,8 +1143,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, dyn_cast<ObjCInterfaceType>(pType->getPointeeType()); // lookup which class implements the instance variable. ObjCInterfaceDecl *clsDeclared = 0; - iFaceDecl->getDecl()->lookupInstanceVariable(*Context, - D->getIdentifier(), + iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), clsDeclared); assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); @@ -1195,8 +1188,7 @@ Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, ObjCInterfaceType *iFaceDecl = dyn_cast<ObjCInterfaceType>(pType->getPointeeType()); // lookup which class implements the instance variable. ObjCInterfaceDecl *clsDeclared = 0; - iFaceDecl->getDecl()->lookupInstanceVariable(*Context, - D->getIdentifier(), + iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(), clsDeclared); assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class"); @@ -1514,7 +1506,8 @@ Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) { SourceLocation()); std::string syncExprBufS; llvm::raw_string_ostream syncExprBuf(syncExprBufS); - syncExpr->printPretty(syncExprBuf, *Context); + syncExpr->printPretty(syncExprBuf, *Context, 0, + PrintingPolicy(LangOpts)); buf += syncExprBuf.str(); buf += ");\n"; buf += " if (_rethrow) objc_exception_throw(_rethrow);\n"; @@ -2143,7 +2136,8 @@ Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) { // The pretty printer for StringLiteral handles escape characters properly. std::string prettyBufS; llvm::raw_string_ostream prettyBuf(prettyBufS); - Exp->getString()->printPretty(prettyBuf, *Context); + Exp->getString()->printPretty(prettyBuf, *Context, 0, + PrintingPolicy(LangOpts)); Preamble += prettyBuf.str(); Preamble += ","; // The minus 2 removes the begin/end double quotes. @@ -2192,8 +2186,7 @@ QualType RewriteObjC::getSuperStructType() { // Create fields for (unsigned i = 0; i < 2; ++i) { - SuperStructDecl->addDecl(*Context, - FieldDecl::Create(*Context, SuperStructDecl, + SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl, SourceLocation(), 0, FieldTypes[i], /*BitWidth=*/0, /*Mutable=*/false)); @@ -2222,8 +2215,7 @@ QualType RewriteObjC::getConstantStringStructType() { // Create fields for (unsigned i = 0; i < 4; ++i) { - ConstantStringDecl->addDecl(*Context, - FieldDecl::Create(*Context, + ConstantStringDecl->addDecl(FieldDecl::Create(*Context, ConstantStringDecl, SourceLocation(), 0, FieldTypes[i], @@ -2889,9 +2881,9 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, if (ObjCSynthesizedProtocols.count(PDecl)) return; - if (PDecl->instmeth_begin(*Context) != PDecl->instmeth_end(*Context)) { - unsigned NumMethods = std::distance(PDecl->instmeth_begin(*Context), - PDecl->instmeth_end(*Context)); + if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { + unsigned NumMethods = std::distance(PDecl->instmeth_begin(), + PDecl->instmeth_end()); /* struct _objc_protocol_method_list { int protocol_method_count; struct protocol_methods protocols[]; @@ -2908,10 +2900,9 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, // Output instance methods declared in this protocol. for (ObjCProtocolDecl::instmeth_iterator - I = PDecl->instmeth_begin(*Context), - E = PDecl->instmeth_end(*Context); + I = PDecl->instmeth_begin(), E = PDecl->instmeth_end(); I != E; ++I) { - if (I == PDecl->instmeth_begin(*Context)) + if (I == PDecl->instmeth_begin()) Result += "\t ,{{(struct objc_selector *)\""; else Result += "\t ,{(struct objc_selector *)\""; @@ -2926,8 +2917,8 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, } // Output class methods declared in this protocol. - unsigned NumMethods = std::distance(PDecl->classmeth_begin(*Context), - PDecl->classmeth_end(*Context)); + unsigned NumMethods = std::distance(PDecl->classmeth_begin(), + PDecl->classmeth_end()); if (NumMethods > 0) { /* struct _objc_protocol_method_list { int protocol_method_count; @@ -2947,10 +2938,9 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, // Output instance methods declared in this protocol. for (ObjCProtocolDecl::classmeth_iterator - I = PDecl->classmeth_begin(*Context), - E = PDecl->classmeth_end(*Context); + I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); I != E; ++I) { - if (I == PDecl->classmeth_begin(*Context)) + if (I == PDecl->classmeth_begin()) Result += "\t ,{{(struct objc_selector *)\""; else Result += "\t ,{(struct objc_selector *)\""; @@ -2993,14 +2983,14 @@ RewriteObjCProtocolMetaData(ObjCProtocolDecl *PDecl, const char *prefix, "{\n\t0, \""; Result += PDecl->getNameAsString(); Result += "\", 0, "; - if (PDecl->instmeth_begin(*Context) != PDecl->instmeth_end(*Context)) { + if (PDecl->instmeth_begin() != PDecl->instmeth_end()) { Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_INSTANCE_METHODS_"; Result += PDecl->getNameAsString(); Result += ", "; } else Result += "0, "; - if (PDecl->classmeth_begin(*Context) != PDecl->classmeth_end(*Context)) { + if (PDecl->classmeth_begin() != PDecl->classmeth_end()) { Result += "(struct _objc_protocol_method_list *)&_OBJC_PROTOCOL_CLASS_METHODS_"; Result += PDecl->getNameAsString(); Result += "\n"; @@ -3076,13 +3066,12 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, // Build _objc_method_list for class's instance methods if needed llvm::SmallVector<ObjCMethodDecl *, 32> - InstanceMethods(IDecl->instmeth_begin(*Context), - IDecl->instmeth_end(*Context)); + InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); // If any of our property implementations have associated getters or // setters, produce metadata for them as well. - for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(*Context), - PropEnd = IDecl->propimpl_end(*Context); + for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), + PropEnd = IDecl->propimpl_end(); Prop != PropEnd; ++Prop) { if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; @@ -3103,8 +3092,7 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, Result); // Build _objc_method_list for class's class methods if needed - RewriteObjCMethodsMetaData(IDecl->classmeth_begin(*Context), - IDecl->classmeth_end(*Context), + RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), false, "CATEGORY_", FullCategoryName.c_str(), Result); @@ -3147,7 +3135,7 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, Result += ClassDecl->getNameAsString(); Result += "\"\n"; - if (IDecl->instmeth_begin(*Context) != IDecl->instmeth_end(*Context)) { + if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { Result += "\t, (struct _objc_method_list *)" "&_OBJC_CATEGORY_INSTANCE_METHODS_"; Result += FullCategoryName; @@ -3155,7 +3143,7 @@ void RewriteObjC::RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *IDecl, } else Result += "\t, 0\n"; - if (IDecl->classmeth_begin(*Context) != IDecl->classmeth_end(*Context)) { + if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { Result += "\t, (struct _objc_method_list *)" "&_OBJC_CATEGORY_CLASS_METHODS_"; Result += FullCategoryName; @@ -3210,8 +3198,8 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, } // Build _objc_ivar_list metadata for classes ivars if needed - unsigned NumIvars = !IDecl->ivar_empty(*Context) - ? IDecl->ivar_size(*Context) + unsigned NumIvars = !IDecl->ivar_empty() + ? IDecl->ivar_size() : (CDecl ? CDecl->ivar_size() : 0); if (NumIvars > 0) { static bool objc_ivar = false; @@ -3249,10 +3237,9 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, ObjCInterfaceDecl::ivar_iterator IVI, IVE; llvm::SmallVector<ObjCIvarDecl *, 8> IVars; - if (!IDecl->ivar_empty(*Context)) { + if (!IDecl->ivar_empty()) { for (ObjCImplementationDecl::ivar_iterator - IV = IDecl->ivar_begin(*Context), - IVEnd = IDecl->ivar_end(*Context); + IV = IDecl->ivar_begin(), IVEnd = IDecl->ivar_end(); IV != IVEnd; ++IV) IVars.push_back(*IV); IVI = IVars.begin(); @@ -3289,13 +3276,12 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, // Build _objc_method_list for class's instance methods if needed llvm::SmallVector<ObjCMethodDecl *, 32> - InstanceMethods(IDecl->instmeth_begin(*Context), - IDecl->instmeth_end(*Context)); + InstanceMethods(IDecl->instmeth_begin(), IDecl->instmeth_end()); // If any of our property implementations have associated getters or // setters, produce metadata for them as well. - for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(*Context), - PropEnd = IDecl->propimpl_end(*Context); + for (ObjCImplDecl::propimpl_iterator Prop = IDecl->propimpl_begin(), + PropEnd = IDecl->propimpl_end(); Prop != PropEnd; ++Prop) { if ((*Prop)->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) continue; @@ -3315,8 +3301,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, true, "", IDecl->getNameAsCString(), Result); // Build _objc_method_list for class's class methods if needed - RewriteObjCMethodsMetaData(IDecl->classmeth_begin(*Context), - IDecl->classmeth_end(*Context), + RewriteObjCMethodsMetaData(IDecl->classmeth_begin(), IDecl->classmeth_end(), false, "", IDecl->getNameAsCString(), Result); // Protocols referenced in class declaration? @@ -3389,7 +3374,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, // Set 'ivars' field for root class to 0. ObjC1 runtime does not use it. // 'info' field is initialized to CLS_META(2) for metaclass Result += ", 0,2, sizeof(struct _objc_class), 0"; - if (IDecl->classmeth_begin(*Context) != IDecl->classmeth_end(*Context)) { + if (IDecl->classmeth_begin() != IDecl->classmeth_end()) { Result += "\n\t, (struct _objc_method_list *)&_OBJC_CLASS_METHODS_"; Result += IDecl->getNameAsString(); Result += "\n"; @@ -3442,7 +3427,7 @@ void RewriteObjC::RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl, } else Result += ",0"; - if (IDecl->instmeth_begin(*Context) != IDecl->instmeth_end(*Context)) { + if (IDecl->instmeth_begin() != IDecl->instmeth_end()) { Result += ", (struct _objc_method_list *)&_OBJC_INSTANCE_METHODS_"; Result += CDecl->getNameAsString(); Result += ", 0\n\t"; @@ -4552,7 +4537,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { RewriteBlocksInFunctionProtoType(FD->getType(), FD); // FIXME: If this should support Obj-C++, support CXXTryStmt - if (CompoundStmt *Body = FD->getCompoundBody(*Context)) { + if (CompoundStmt *Body = FD->getCompoundBody()) { CurFunctionDef = FD; CollectPropertySetters(Body); CurrentBody = Body; @@ -4572,7 +4557,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { return; } if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { - if (CompoundStmt *Body = MD->getBody()) { + if (CompoundStmt *Body = MD->getCompoundBody()) { CurMethodDef = MD; CollectPropertySetters(Body); CurrentBody = Body; @@ -4636,8 +4621,8 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { } if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) { if (RD->isDefinition()) { - for (RecordDecl::field_iterator i = RD->field_begin(*Context), - e = RD->field_end(*Context); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i) { FieldDecl *FD = *i; if (isTopLevelBlockPointerType(FD->getType())) RewriteBlockPointerDecl(FD); diff --git a/lib/Lex/Lexer.cpp b/lib/Lex/Lexer.cpp index 81ea606f0d9f..6f1043ae7353 100644 --- a/lib/Lex/Lexer.cpp +++ b/lib/Lex/Lexer.cpp @@ -903,7 +903,10 @@ bool Lexer::SkipBCPLComment(Token &Result, const char *CurPtr) { } while (C != '\n' && C != '\r'); // Found but did not consume the newline. - + if (PP) + PP->HandleComment(SourceRange(getSourceLocation(BufferPtr), + getSourceLocation(CurPtr))); + // If we are returning comments as tokens, return this comment as a token. if (inKeepCommentMode()) return SaveBCPLComment(Result, CurPtr); @@ -1146,6 +1149,10 @@ bool Lexer::SkipBlockComment(Token &Result, const char *CurPtr) { C = *CurPtr++; } + if (PP) + PP->HandleComment(SourceRange(getSourceLocation(BufferPtr), + getSourceLocation(CurPtr))); + // If we are returning comments as tokens, return this comment as a token. if (inKeepCommentMode()) { FormTokenWithChars(Result, CurPtr, tok::comment); diff --git a/lib/Lex/Pragma.cpp b/lib/Lex/Pragma.cpp index 3227d1cf09c5..bb0b71e22682 100644 --- a/lib/Lex/Pragma.cpp +++ b/lib/Lex/Pragma.cpp @@ -19,6 +19,7 @@ #include "clang/Lex/LexDiagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" +#include <algorithm> using namespace clang; // Out-of-line destructor to provide a home for the class. diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 24ee5d8a8f92..9f0c15f59e49 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -476,3 +476,26 @@ void Preprocessor::HandleIdentifier(Token &Identifier) { if (II.isExtensionToken() && !DisableMacroExpansion) Diag(Identifier, diag::ext_token_used); } + +void Preprocessor::AddCommentHandler(CommentHandler *Handler) { + assert(Handler && "NULL comment handler"); + assert(std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler) == + CommentHandlers.end() && "Comment handler already registered"); + CommentHandlers.push_back(Handler); +} + +void Preprocessor::RemoveCommentHandler(CommentHandler *Handler) { + std::vector<CommentHandler *>::iterator Pos + = std::find(CommentHandlers.begin(), CommentHandlers.end(), Handler); + assert(Pos != CommentHandlers.end() && "Comment handler not registered"); + CommentHandlers.erase(Pos); +} + +void Preprocessor::HandleComment(SourceRange Comment) { + for (std::vector<CommentHandler *>::iterator H = CommentHandlers.begin(), + HEnd = CommentHandlers.end(); + H != HEnd; ++H) + (*H)->HandleComment(*this, Comment); +} + +CommentHandler::~CommentHandler() { } diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index ff602e8ba79b..4a3532c4103b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -802,7 +802,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation EndProtoLoc; llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl; ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc); - DS.setProtocolQualifiers(&ProtocolDecl[0], ProtocolDecl.size()); + DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size()); DS.SetRangeEnd(EndProtoLoc); continue; @@ -859,7 +859,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation EndProtoLoc; llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl; ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc); - DS.setProtocolQualifiers(&ProtocolDecl[0], ProtocolDecl.size()); + DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size()); DS.SetRangeEnd(EndProtoLoc); @@ -1066,7 +1066,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, SourceLocation EndProtoLoc; llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl; ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc); - DS.setProtocolQualifiers(&ProtocolDecl[0], ProtocolDecl.size()); + DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size()); DS.SetRangeEnd(EndProtoLoc); Diag(Loc, diag::warn_objc_protocol_qualifier_missing_id) @@ -1179,7 +1179,7 @@ bool Parser::ParseOptionalTypeSpecifier(DeclSpec &DS, int& isInvalid, SourceLocation EndProtoLoc; llvm::SmallVector<DeclPtrTy, 8> ProtocolDecl; ParseObjCProtocolReferences(ProtocolDecl, false, EndProtoLoc); - DS.setProtocolQualifiers(&ProtocolDecl[0], ProtocolDecl.size()); + DS.setProtocolQualifiers(ProtocolDecl.data(), ProtocolDecl.size()); DS.SetRangeEnd(EndProtoLoc); return true; diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 225f9261ef8f..373d22fd9f4f 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1277,16 +1277,28 @@ void Parser::ParseConstructorInitializer(DeclPtrTy ConstructorDecl) { /// '::'[opt] nested-name-specifier[opt] class-name /// identifier Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) { - // FIXME: parse '::'[opt] nested-name-specifier[opt] - - if (Tok.isNot(tok::identifier)) { + // parse '::'[opt] nested-name-specifier[opt] + CXXScopeSpec SS; + ParseOptionalCXXScopeSpecifier(SS); + TypeTy *TemplateTypeTy = 0; + if (Tok.is(tok::annot_template_id)) { + TemplateIdAnnotation *TemplateId + = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); + if (TemplateId->Kind == TNK_Type_template) { + AnnotateTemplateIdTokenAsType(&SS); + assert(Tok.is(tok::annot_typename) && "template-id -> type failed"); + TemplateTypeTy = Tok.getAnnotationValue(); + } + // FIXME. May need to check for TNK_Dependent_template as well. + } + if (!TemplateTypeTy && Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_expected_member_or_base_name); return true; } - + // Get the identifier. This may be a member name or a class name, // but we'll let the semantic analysis determine which it is. - IdentifierInfo *II = Tok.getIdentifierInfo(); + IdentifierInfo *II = Tok.is(tok::identifier) ? Tok.getIdentifierInfo() : 0; SourceLocation IdLoc = ConsumeToken(); // Parse the '('. @@ -1306,7 +1318,8 @@ Parser::MemInitResult Parser::ParseMemInitializer(DeclPtrTy ConstructorDecl) { SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc); - return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, II, IdLoc, + return Actions.ActOnMemInitializer(ConstructorDecl, CurScope, SS, II, + TemplateTypeTy, IdLoc, LParenLoc, ArgExprs.take(), ArgExprs.size(), CommaLocs.data(), RParenLoc); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 13b32acd5b29..cd7618f66536 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -777,7 +777,7 @@ Parser::OwningExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::annot_cxxscope: // [C++] id-expression: qualified-id case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id - // template-id + case tok::annot_template_id: // [C++] template-id Res = ParseCXXIdExpression(isAddressOfOperand); return ParsePostfixExpressionSuffix(move(Res)); @@ -1172,17 +1172,18 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() { Comps.back().LocEnd = MatchRHSPunctuation(tok::r_square, Comps.back().LocStart); - } else if (Tok.is(tok::r_paren)) { - if (Ty.isInvalid()) + } else { + if (Tok.isNot(tok::r_paren)) { + MatchRHSPunctuation(tok::r_paren, LParenLoc); + Res = ExprError(); + } else if (Ty.isInvalid()) { Res = ExprError(); - else + } else { Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc, Ty.get(), &Comps[0], Comps.size(), ConsumeParen()); + } break; - } else { - // Error occurred. - return ExprError(); } } break; diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index d89f1e172ffb..1220b2d27b4f 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -207,13 +207,13 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS) { /// operator-function-id /// conversion-function-id [TODO] /// '~' class-name [TODO] -/// template-id [TODO] +/// template-id /// /// qualified-id: /// '::'[opt] nested-name-specifier 'template'[opt] unqualified-id /// '::' identifier /// '::' operator-function-id -/// '::' template-id [TODO] +/// '::' template-id /// /// nested-name-specifier: /// type-name '::' @@ -264,7 +264,7 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { // operator-function-id // conversion-function-id // '~' class-name [TODO] - // template-id [TODO] + // template-id // switch (Tok.getKind()) { default: @@ -294,6 +294,29 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) { return ExprError(); } + case tok::annot_template_id: { + TemplateIdAnnotation *TemplateId + = static_cast<TemplateIdAnnotation *>(Tok.getAnnotationValue()); + assert((TemplateId->Kind == TNK_Function_template || + TemplateId->Kind == TNK_Dependent_template_name) && + "A template type name is not an ID expression"); + + ASTTemplateArgsPtr TemplateArgsPtr(Actions, + TemplateId->getTemplateArgs(), + TemplateId->getTemplateArgIsType(), + TemplateId->NumArgs); + + OwningExprResult Result + = Actions.ActOnTemplateIdExpr(TemplateTy::make(TemplateId->Template), + TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, + TemplateArgsPtr, + TemplateId->getTemplateArgLocations(), + TemplateId->RAngleLoc); + ConsumeToken(); // Consume the template-id token + return move(Result); + } + } // switch. assert(0 && "The switch was supposed to take care everything."); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 29d1d8792e1a..9771cf7b8474 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -20,6 +20,19 @@ #include "ParsePragma.h" using namespace clang; +/// \brief A comment handler that passes comments found by the preprocessor +/// to the parser action. +class ActionCommentHandler : public CommentHandler { + Action &Actions; + +public: + explicit ActionCommentHandler(Action &Actions) : Actions(Actions) { } + + virtual void HandleComment(Preprocessor &PP, SourceRange Comment) { + Actions.ActOnComment(Comment); + } +}; + Parser::Parser(Preprocessor &pp, Action &actions) : CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()), GreaterThanIsOperator(true) { @@ -43,6 +56,9 @@ Parser::Parser(Preprocessor &pp, Action &actions) WeakHandler.reset(new PragmaWeakHandler(&PP.getIdentifierTable().get("weak"), actions)); PP.AddPragmaHandler(0, WeakHandler.get()); + + CommentHandler.reset(new ActionCommentHandler(actions)); + PP.AddCommentHandler(CommentHandler.get()); } /// If a crash happens while the parser is active, print out a line indicating @@ -294,6 +310,7 @@ Parser::~Parser() { UnusedHandler.reset(); PP.RemovePragmaHandler(0, WeakHandler.get()); WeakHandler.reset(); + PP.RemoveCommentHandler(CommentHandler.get()); } /// Initialize - Warm up the parser. diff --git a/lib/Rewrite/Rewriter.cpp b/lib/Rewrite/Rewriter.cpp index d81c38d6a466..ec5a60412d13 100644 --- a/lib/Rewrite/Rewriter.cpp +++ b/lib/Rewrite/Rewriter.cpp @@ -218,7 +218,7 @@ bool Rewriter::ReplaceStmt(Stmt *From, Stmt *To) { // Get the new text. std::string SStr; llvm::raw_string_ostream S(SStr); - To->printPretty(S); + To->printPretty(S, 0, PrintingPolicy(*LangOpts)); const std::string &Str = S.str(); ReplaceText(From->getLocStart(), Size, &Str[0], Str.size()); diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index 425d80443955..ae863f2df1ee 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -77,11 +77,11 @@ JumpScopeChecker::JumpScopeChecker(Stmt *Body, Sema &s) : S(s) { /// GetDiagForGotoScopeDecl - If this decl induces a new goto scope, return a /// diagnostic that should be emitted if control goes over it. If not, return 0. -static unsigned GetDiagForGotoScopeDecl(ASTContext &Context, const Decl *D) { +static unsigned GetDiagForGotoScopeDecl(const Decl *D) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->getType()->isVariablyModifiedType()) return diag::note_protected_by_vla; - if (VD->hasAttr<CleanupAttr>(Context)) + if (VD->hasAttr<CleanupAttr>()) return diag::note_protected_by_cleanup; } else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { if (TD->getUnderlyingType()->isVariablyModifiedType()) @@ -125,7 +125,7 @@ void JumpScopeChecker::BuildScopeInformation(Stmt *S, unsigned ParentScope) { for (DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); I != E; ++I) { // If this decl causes a new scope, push and switch to it. - if (unsigned Diag = GetDiagForGotoScopeDecl(this->S.Context, *I)) { + if (unsigned Diag = GetDiagForGotoScopeDecl(*I)) { Scopes.push_back(GotoScope(ParentScope, Diag, (*I)->getLocation())); ParentScope = Scopes.size()-1; } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index c37f66dae907..d1e8e2104d50 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -345,3 +345,7 @@ Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() { = SemaRef.ActiveTemplateInstantiations.back(); } } + +void Sema::ActOnComment(SourceRange Comment) { + Context.Comments.push_back(Comment); +} diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 2d27ccc77839..7af80c0261e4 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -29,9 +29,9 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/OwningPtr.h" +#include <deque> #include <list> #include <string> -#include <queue> #include <vector> namespace llvm { @@ -86,6 +86,7 @@ namespace clang { class ObjCMethodDecl; class ObjCPropertyDecl; class ObjCContainerDecl; + class FunctionProtoType; class BasePaths; struct MemberLookupCriteria; class CXXTemporary; @@ -362,6 +363,8 @@ public: return CurBlock ? CurBlock->SwitchStack : FunctionSwitchStack; } + virtual void ActOnComment(SourceRange Comment); + //===--------------------------------------------------------------------===// // Type Analysis / Processing: SemaType.cpp. // @@ -392,6 +395,9 @@ public: DeclarationName GetNameForDeclarator(Declarator &D); bool CheckSpecifiedExceptionType(QualType T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); + bool CheckEquivalentExceptionSpec( + const FunctionProtoType *Old, SourceLocation OldLoc, + const FunctionProtoType *New, SourceLocation NewLoc); QualType ObjCGetTypeForMethodDefinition(DeclPtrTy D); @@ -406,6 +412,9 @@ public: QualType getQualifiedNameType(const CXXScopeSpec &SS, QualType T); + QualType BuildTypeofExprType(Expr *E); + QualType BuildDecltypeType(Expr *E); + //===--------------------------------------------------------------------===// // Symbol table / Decl tracking callbacks: SemaDecl.cpp. // @@ -482,7 +491,7 @@ public: void DiagnoseUnusedParameters(InputIterator Param, InputIterator ParamEnd) { for (; Param != ParamEnd; ++Param) { if (!(*Param)->isUsed() && (*Param)->getDeclName() && - !(*Param)->template hasAttr<UnusedAttr>(Context)) + !(*Param)->template hasAttr<UnusedAttr>()) Diag((*Param)->getLocation(), diag::warn_unused_parameter) << (*Param)->getDeclName(); } @@ -679,7 +688,7 @@ public: OR_Deleted ///< Overload resoltuion refers to a deleted function. }; - typedef llvm::SmallPtrSet<FunctionDecl *, 16> FunctionSet; + typedef llvm::SmallPtrSet<AnyFunctionDecl, 16> FunctionSet; typedef llvm::SmallPtrSet<NamespaceDecl *, 16> AssociatedNamespaceSet; typedef llvm::SmallPtrSet<CXXRecordDecl *, 16> AssociatedClassSet; @@ -698,6 +707,9 @@ public: bool SuppressUserConversions = false, bool ForceRValue = false); void AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions = false, @@ -744,6 +756,9 @@ public: FunctionDecl *ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, DeclarationName UnqualifiedName, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, @@ -1398,7 +1413,11 @@ public: bool HasTrailingLParen, const CXXScopeSpec *SS, bool isAddressOfOperand = false); - + OwningExprResult BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, + bool HasTrailingLParen, + const CXXScopeSpec *SS, + bool isAddressOfOperand); + virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); virtual OwningExprResult ActOnNumericConstant(const Token &); @@ -1594,9 +1613,9 @@ public: QualType DeclInitType, Expr **Exprs, unsigned NumExprs); - /// MarcDestructorReferenced - Prepare for calling destructor on the + /// MarkDestructorReferenced - Prepare for calling destructor on the /// constructed decl. - void MarcDestructorReferenced(SourceLocation Loc, QualType DeclInitType); + void MarkDestructorReferenced(SourceLocation Loc, QualType DeclInitType); /// DefineImplicitDefaultConstructor - Checks for feasibility of /// defining this constructor as the default constructor. @@ -1884,7 +1903,9 @@ public: virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorD, Scope *S, + const CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, + TypeTy *TemplateTypeTy, SourceLocation IdLoc, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, @@ -2068,6 +2089,20 @@ public: SourceLocation *TemplateArgLocs, SourceLocation RAngleLoc); + OwningExprResult BuildTemplateIdExpr(TemplateName Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc); + + virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc); + virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, const IdentifierInfo &Name, SourceLocation NameLoc, @@ -2134,6 +2169,7 @@ public: const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc, + bool PartialTemplateArgs, TemplateArgumentListBuilder &Converted); bool CheckTemplateTypeArgument(TemplateTypeParmDecl *Param, @@ -2225,7 +2261,10 @@ public: TDK_TooManyArguments, /// \brief When performing template argument deduction for a class /// template, there were too few call arguments. - TDK_TooFewArguments + TDK_TooFewArguments, + /// \brief The explicitly-specified template arguments were not valid + /// template arguments for the given template. + TDK_InvalidExplicitArguments }; /// \brief Provides information about an attempted template argument @@ -2307,6 +2346,9 @@ public: TemplateDeductionResult DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, TemplateDeductionInfo &Info); @@ -2323,7 +2365,7 @@ public: /// \brief A template instantiation that is currently in progress. struct ActiveTemplateInstantiation { /// \brief The kind of template instantiation we are performing - enum { + enum InstantiationKind { /// We are instantiating a template declaration. The entity is /// the declaration we're instantiating (e.g., a CXXRecordDecl). TemplateInstantiation, @@ -2335,13 +2377,16 @@ public: /// FIXME: Use a TemplateArgumentList DefaultTemplateArgumentInstantiation, - /// We are performing template argument deduction for a class - /// template partial specialization. The Entity is the class - /// template partial specialization, and - /// TemplateArgs/NumTemplateArgs provides the deduced template - /// arguments. - /// FIXME: Use a TemplateArgumentList - PartialSpecDeductionInstantiation + /// We are substituting explicit template arguments provided for + /// a function template. The entity is a FunctionTemplateDecl. + ExplicitTemplateArgumentSubstitution, + + /// We are substituting template argument determined as part of + /// template argument deduction for either a class template + /// partial specialization or a function template. The + /// Entity is either a ClassTemplatePartialSpecializationDecl or + /// a FunctionTemplateDecl. + DeducedTemplateArgumentSubstitution } Kind; /// \brief The point of instantiation within the source code. @@ -2375,7 +2420,8 @@ public: return true; case DefaultTemplateArgumentInstantiation: - case PartialSpecDeductionInstantiation: + case ExplicitTemplateArgumentSubstitution: + case DeducedTemplateArgumentSubstitution: return X.TemplateArgs == Y.TemplateArgs; } @@ -2432,6 +2478,15 @@ public: unsigned NumTemplateArgs, SourceRange InstantiationRange = SourceRange()); + /// \brief Note that we are instantiating a default argument in a + /// template-id. + InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + FunctionTemplateDecl *FunctionTemplate, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + ActiveTemplateInstantiation::InstantiationKind Kind, + SourceRange InstantiationRange = SourceRange()); + /// \brief Note that we are instantiating as part of template /// argument deduction for a class template partial /// specialization. @@ -2574,7 +2629,7 @@ public: /// \brief The queue of implicit template instantiations that are required /// but have not yet been performed. - std::queue<PendingImplicitInstantiation> PendingImplicitInstantiations; + std::deque<PendingImplicitInstantiation> PendingImplicitInstantiations; void PerformPendingImplicitInstantiations(); @@ -2629,7 +2684,8 @@ public: const TemplateArgumentList &TemplateArgs); void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, - FunctionDecl *Function); + FunctionDecl *Function, + bool Recursive = false); void InstantiateVariableDefinition(VarDecl *Var); NamedDecl *InstantiateCurrentDeclRef(NamedDecl *D); diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp index cbfa56a6911f..1bf8444c42b7 100644 --- a/lib/Sema/SemaAttr.cpp +++ b/lib/Sema/SemaAttr.cpp @@ -205,7 +205,7 @@ void Sema::ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs, // Otherwise, add the 'unused' attribute to each referenced declaration. for (unsigned i = 0; i < NumExprs; ++i) { DeclRefExpr *DR = (DeclRefExpr*) Exprs[i]; - DR->getDecl()->addAttr(Context, ::new (Context) UnusedAttr()); + DR->getDecl()->addAttr(::new (Context) UnusedAttr()); DR->Destroy(Context); } } diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index f6d6623f9a20..4eed01872246 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -166,7 +166,7 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { // handlers. // Printf checking. - if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>(Context)) { + if (const FormatAttr *Format = FDecl->getAttr<FormatAttr>()) { if (Format->getType() == "printf") { bool HasVAListArg = Format->getFirstArg() == 0; if (!HasVAListArg) { @@ -178,7 +178,7 @@ Sema::CheckFunctionCall(FunctionDecl *FDecl, CallExpr *TheCall) { HasVAListArg ? 0 : Format->getFirstArg() - 1); } } - for (const Attr *attr = FDecl->getAttrs(Context); + for (const Attr *attr = FDecl->getAttrs(); attr; attr = attr->getNext()) { if (const NonNullAttr *NonNull = dyn_cast<NonNullAttr>(attr)) CheckNonNullArguments(NonNull, TheCall); @@ -192,7 +192,7 @@ Sema::CheckBlockCall(NamedDecl *NDecl, CallExpr *TheCall) { OwningExprResult TheCallResult(Owned(TheCall)); // Printf checking. - const FormatAttr *Format = NDecl->getAttr<FormatAttr>(Context); + const FormatAttr *Format = NDecl->getAttr<FormatAttr>(); if (!Format) return move(TheCallResult); const VarDecl *V = dyn_cast<VarDecl>(NDecl); @@ -717,8 +717,6 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, if (E->isTypeDependent() || E->isValueDependent()) return false; - E = E->IgnoreParenCasts(); - switch (E->getStmtClass()) { case Stmt::ConditionalOperatorClass: { const ConditionalOperator *C = cast<ConditionalOperator>(E); @@ -763,6 +761,28 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, return SemaCheckStringLiteral(Init, TheCall, HasVAListArg, format_idx, firstDataArg); } + + // For vprintf* functions (i.e., HasVAListArg==true), we add a + // special check to see if the format string is a function parameter + // of the function calling the printf function. If the function + // has an attribute indicating it is a printf-like function, then we + // should suppress warnings concerning non-literals being used in a call + // to a vprintf function. For example: + // + // void + // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...){ + // va_list ap; + // va_start(ap, fmt); + // vprintf(fmt, ap); // Do NOT emit a warning about "fmt". + // ... + // + // + // FIXME: We don't have full attribute support yet, so just check to see + // if the argument is a DeclRefExpr that references a parameter. We'll + // add proper support for checking the attribute later. + if (HasVAListArg) + if (isa<ParmVarDecl>(VD)) + return true; } return false; @@ -774,7 +794,7 @@ bool Sema::SemaCheckStringLiteral(const Expr *E, const CallExpr *TheCall, = dyn_cast<ImplicitCastExpr>(CE->getCallee())) { if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ICE->getSubExpr())) { if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DRE->getDecl())) { - if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>(Context)) { + if (const FormatArgAttr *FA = FD->getAttr<FormatArgAttr>()) { unsigned ArgIndex = FA->getFormatIdx(); const Expr *Arg = CE->getArg(ArgIndex - 1); @@ -901,29 +921,6 @@ Sema::CheckPrintfArguments(const CallExpr *TheCall, bool HasVAListArg, firstDataArg)) return; // Literal format string found, check done! - // For vprintf* functions (i.e., HasVAListArg==true), we add a - // special check to see if the format string is a function parameter - // of the function calling the printf function. If the function - // has an attribute indicating it is a printf-like function, then we - // should suppress warnings concerning non-literals being used in a call - // to a vprintf function. For example: - // - // void - // logmessage(char const *fmt __attribute__ (format (printf, 1, 2)), ...) { - // va_list ap; - // va_start(ap, fmt); - // vprintf(fmt, ap); // Do NOT emit a warning about "fmt". - // ... - // - // - // FIXME: We don't have full attribute support yet, so just check to see - // if the argument is a DeclRefExpr that references a parameter. We'll - // add proper support for checking the attribute later. - if (HasVAListArg) - if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OrigFormatExpr)) - if (isa<ParmVarDecl>(DR->getDecl())) - return; - // If there are no arguments specified, warn with -Wformat-security, otherwise // warn only with -Wformat-nonliteral. if (TheCall->getNumArgs() == format_idx+1) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 13162d8e8ea9..1fd569729a37 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -256,7 +256,7 @@ static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) { if (isa<OverloadedFunctionDecl>(PrevDecl)) return true; - return PrevDecl->getAttr<OverloadableAttr>(Context) != 0; + return PrevDecl->getAttr<OverloadableAttr>() != 0; } /// Add this decl to the scope shadowed decl chains. @@ -273,7 +273,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) { // Add scoped declarations into their context, so that they can be // found later. Declarations without a context won't be inserted // into any context. - CurContext->addDecl(Context, D); + CurContext->addDecl(D); // C++ [basic.scope]p4: // -- exactly one declaration shall declare a class name or @@ -612,8 +612,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) { /// DeclhasAttr - returns true if decl Declaration already has the target /// attribute. static bool -DeclHasAttr(ASTContext &Context, const Decl *decl, const Attr *target) { - for (const Attr *attr = decl->getAttrs(Context); attr; attr = attr->getNext()) +DeclHasAttr(const Decl *decl, const Attr *target) { + for (const Attr *attr = decl->getAttrs(); attr; attr = attr->getNext()) if (attr->getKind() == target->getKind()) return true; @@ -622,11 +622,11 @@ DeclHasAttr(ASTContext &Context, const Decl *decl, const Attr *target) { /// MergeAttributes - append attributes from the Old decl to the New one. static void MergeAttributes(Decl *New, Decl *Old, ASTContext &C) { - for (const Attr *attr = Old->getAttrs(C); attr; attr = attr->getNext()) { - if (!DeclHasAttr(C, New, attr) && attr->isMerged()) { + for (const Attr *attr = Old->getAttrs(); attr; attr = attr->getNext()) { + if (!DeclHasAttr(New, attr) && attr->isMerged()) { Attr *NewAttr = attr->clone(C); NewAttr->setInherited(true); - New->addAttr(C, NewAttr); + New->addAttr(NewAttr); } } } @@ -1123,8 +1123,8 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, RecordDecl *AnonRecord) { bool Invalid = false; - for (RecordDecl::field_iterator F = AnonRecord->field_begin(Context), - FEnd = AnonRecord->field_end(Context); + for (RecordDecl::field_iterator F = AnonRecord->field_begin(), + FEnd = AnonRecord->field_end(); F != FEnd; ++F) { if ((*F)->getDeclName()) { NamedDecl *PrevDecl = LookupQualifiedName(Owner, (*F)->getDeclName(), @@ -1147,7 +1147,7 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner, // definition, the members of the anonymous union are // considered to have been defined in the scope in which the // anonymous union is declared. - Owner->makeDeclVisibleInContext(Context, *F); + Owner->makeDeclVisibleInContext(*F); S->AddDecl(DeclPtrTy::make(*F)); IdResolver.AddDecl(*F); } @@ -1213,8 +1213,8 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // The member-specification of an anonymous union shall only // define non-static data members. [Note: nested types and // functions cannot be declared within an anonymous union. ] - for (DeclContext::decl_iterator Mem = Record->decls_begin(Context), - MemEnd = Record->decls_end(Context); + for (DeclContext::decl_iterator Mem = Record->decls_begin(), + MemEnd = Record->decls_end(); Mem != MemEnd; ++Mem) { if (FieldDecl *FD = dyn_cast<FieldDecl>(*Mem)) { // C++ [class.union]p3: @@ -1302,7 +1302,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS, // Add the anonymous struct/union object to the current // context. We'll be referencing this object when we refer to one of // its members. - Owner->addDecl(Context, Anon); + Owner->addDecl(Anon); // Inject the members of the anonymous struct/union into the owning // context and into the identifier resolver chain for name lookup @@ -1851,8 +1851,7 @@ Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewVD->addAttr(Context, - ::new (Context) AsmLabelAttr(std::string(SE->getStrData(), + NewVD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -1931,11 +1930,11 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, } if (NewVD->hasLocalStorage() && T.isObjCGCWeak() - && !NewVD->hasAttr<BlocksAttr>(Context)) + && !NewVD->hasAttr<BlocksAttr>()) Diag(NewVD->getLocation(), diag::warn_attribute_weak_on_local); bool isVM = T->isVariablyModifiedType(); - if (isVM || NewVD->hasAttr<CleanupAttr>(Context)) + if (isVM || NewVD->hasAttr<CleanupAttr>()) CurFunctionNeedsScopeChecking = true; if ((isVM && NewVD->hasLinkage()) || @@ -1990,12 +1989,12 @@ void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl, return NewVD->setInvalidDecl(); } - if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>(Context)) { + if (!NewVD->hasLocalStorage() && NewVD->hasAttr<BlocksAttr>()) { Diag(NewVD->getLocation(), diag::err_block_on_nonlocal); return NewVD->setInvalidDecl(); } - if (isVM && NewVD->hasAttr<BlocksAttr>(Context)) { + if (isVM && NewVD->hasAttr<BlocksAttr>()) { Diag(NewVD->getLocation(), diag::err_block_on_vm); return NewVD->setInvalidDecl(); } @@ -2251,8 +2250,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (Expr *E = (Expr*) D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast<StringLiteral>(E); - NewFD->addAttr(Context, - ::new (Context) AsmLabelAttr(std::string(SE->getStrData(), + NewFD->addAttr(::new (Context) AsmLabelAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -2371,7 +2369,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, ProcessDeclAttributes(S, NewFD, D); AddKnownFunctionAttributes(NewFD); - if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>(Context)) { + if (OverloadableAttrRequired && !NewFD->getAttr<OverloadableAttr>()) { // If a function name is overloadable in C, then every function // with that name must be marked "overloadable". Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing) @@ -2379,7 +2377,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (PrevDecl) Diag(PrevDecl->getLocation(), diag::note_attribute_overloadable_prev_overload); - NewFD->addAttr(Context, ::new (Context) OverloadableAttr()); + NewFD->addAttr(::new (Context) OverloadableAttr()); } // If this is a locally-scoped extern C function, update the @@ -2797,7 +2795,7 @@ void Sema::ActOnUninitializedDecl(DeclPtrTy dcl) { InitializeVarWithConstructor(Var, Constructor, InitType, 0, 0); // FIXME. Must do all that is needed to destroy the object // on scope exit. For now, just mark the destructor as used. - MarcDestructorReferenced(Var->getLocation(), InitType); + MarkDestructorReferenced(Var->getLocation(), InitType); } } } @@ -2998,7 +2996,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { ProcessDeclAttributes(S, New, D); - if (New->hasAttr<BlocksAttr>(Context)) { + if (New->hasAttr<BlocksAttr>()) { Diag(New->getLocation(), diag::err_block_on_nonlocal); } return DeclPtrTy::make(New); @@ -3065,7 +3063,7 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // See if this is a redefinition. const FunctionDecl *Definition; - if (FD->getBody(Context, Definition)) { + if (FD->getBody(Definition)) { Diag(FD->getLocation(), diag::err_redefinition) << FD->getDeclName(); Diag(Definition->getLocation(), diag::note_previous_definition); } @@ -3128,10 +3126,10 @@ Sema::DeclPtrTy Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { // Checking attributes of current function definition // dllimport attribute. - if (FD->getAttr<DLLImportAttr>(Context) && - (!FD->getAttr<DLLExportAttr>(Context))) { + if (FD->getAttr<DLLImportAttr>() && + (!FD->getAttr<DLLExportAttr>())) { // dllimport attribute cannot be applied to definition. - if (!(FD->getAttr<DLLImportAttr>(Context))->isInherited()) { + if (!(FD->getAttr<DLLImportAttr>())->isInherited()) { Diag(FD->getLocation(), diag::err_attribute_can_be_applied_only_to_symbol_declaration) << "dllimport"; @@ -3313,9 +3311,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { unsigned FormatIdx; bool HasVAListArg; if (Context.BuiltinInfo.isPrintfLike(BuiltinID, FormatIdx, HasVAListArg)) { - if (!FD->getAttr<FormatAttr>(Context)) - FD->addAttr(Context, - ::new (Context) FormatAttr("printf", FormatIdx + 1, + if (!FD->getAttr<FormatAttr>()) + FD->addAttr(::new (Context) FormatAttr("printf", FormatIdx + 1, HasVAListArg ? 0 : FormatIdx + 2)); } @@ -3324,8 +3321,8 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { // IRgen to use LLVM intrinsics for such functions. if (!getLangOptions().MathErrno && Context.BuiltinInfo.isConstWithoutErrno(BuiltinID)) { - if (!FD->getAttr<ConstAttr>(Context)) - FD->addAttr(Context, ::new (Context) ConstAttr()); + if (!FD->getAttr<ConstAttr>()) + FD->addAttr(::new (Context) ConstAttr()); } } @@ -3343,17 +3340,15 @@ void Sema::AddKnownFunctionAttributes(FunctionDecl *FD) { return; if (Name->isStr("NSLog") || Name->isStr("NSLogv")) { - if (const FormatAttr *Format = FD->getAttr<FormatAttr>(Context)) { + if (const FormatAttr *Format = FD->getAttr<FormatAttr>()) { // FIXME: We known better than our headers. const_cast<FormatAttr *>(Format)->setType("printf"); } else - FD->addAttr(Context, - ::new (Context) FormatAttr("printf", 1, + FD->addAttr(::new (Context) FormatAttr("printf", 1, Name->isStr("NSLogv") ? 0 : 2)); } else if (Name->isStr("asprintf") || Name->isStr("vasprintf")) { - if (!FD->getAttr<FormatAttr>(Context)) - FD->addAttr(Context, - ::new (Context) FormatAttr("printf", 2, + if (!FD->getAttr<FormatAttr>()) + FD->addAttr(::new (Context) FormatAttr("printf", 2, Name->isStr("vasprintf") ? 0 : 3)); } } @@ -3709,7 +3704,7 @@ CreateNewDecl: // the #pragma tokens are effectively skipped over during the // parsing of the struct). if (unsigned Alignment = getPragmaPackAlignment()) - New->addAttr(Context, ::new (Context) PackedAttr(Alignment * 8)); + New->addAttr(::new (Context) PackedAttr(Alignment * 8)); } if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) { @@ -3761,7 +3756,7 @@ CreateNewDecl: S = getNonFieldDeclScope(S); PushOnScopeChains(New, S); } else { - CurContext->addDecl(Context, New); + CurContext->addDecl(New); } OwnedDecl = true; @@ -3917,7 +3912,7 @@ FieldDecl *Sema::HandleField(Scope *S, RecordDecl *Record, } else if (II) { PushOnScopeChains(NewFD, S); } else - Record->addDecl(Context, NewFD); + Record->addDecl(NewFD); return NewFD; } @@ -4239,7 +4234,7 @@ void Sema::ActOnFields(Scope* S, // Add ivar's to class's DeclContext. for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { ClsFields[i]->setLexicalDeclContext(ID); - ID->addDecl(Context, ClsFields[i]); + ID->addDecl(ClsFields[i]); } // Must enforce the rule that ivars in the base classes may not be // duplicates. @@ -4250,7 +4245,7 @@ void Sema::ActOnFields(Scope* S, if (IdentifierInfo *II = Ivar->getIdentifier()) { ObjCIvarDecl* prevIvar = - ID->getSuperClass()->lookupInstanceVariable(Context, II); + ID->getSuperClass()->lookupInstanceVariable(II); if (prevIvar) { Diag(Ivar->getLocation(), diag::err_duplicate_member) << II; Diag(prevIvar->getLocation(), diag::note_previous_declaration); @@ -4549,7 +4544,7 @@ Sema::DeclPtrTy Sema::ActOnFileScopeAsmDecl(SourceLocation Loc, FileScopeAsmDecl *New = FileScopeAsmDecl::Create(Context, CurContext, Loc, AsmString); - CurContext->addDecl(Context, New); + CurContext->addDecl(New); return DeclPtrTy::make(New); } @@ -4560,7 +4555,7 @@ void Sema::ActOnPragmaWeakID(IdentifierInfo* Name, // FIXME: This implementation is an ugly hack! if (PrevDecl) { - PrevDecl->addAttr(Context, ::new (Context) WeakAttr()); + PrevDecl->addAttr(::new (Context) WeakAttr()); return; } Diag(PragmaLoc, diag::err_unsupported_pragma_weak); @@ -4576,8 +4571,8 @@ void Sema::ActOnPragmaWeakAlias(IdentifierInfo* Name, // FIXME: This implementation is an ugly hack! if (PrevDecl) { - PrevDecl->addAttr(Context, ::new (Context) AliasAttr(AliasName->getName())); - PrevDecl->addAttr(Context, ::new (Context) WeakAttr()); + PrevDecl->addAttr(::new (Context) AliasAttr(AliasName->getName())); + PrevDecl->addAttr(::new (Context) WeakAttr()); return; } Diag(PragmaLoc, diag::err_unsupported_pragma_weak); diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index f7dd9303cb47..2b71df722459 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -284,7 +284,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { } if (TagDecl *TD = dyn_cast<TagDecl>(d)) - TD->addAttr(S.Context, ::new (S.Context) PackedAttr(1)); + TD->addAttr(::new (S.Context) PackedAttr(1)); else if (FieldDecl *FD = dyn_cast<FieldDecl>(d)) { // If the alignment is less than or equal to 8 bits, the packed attribute // has no effect. @@ -293,7 +293,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) << Attr.getName() << FD->getType(); else - FD->addAttr(S.Context, ::new (S.Context) PackedAttr(1)); + FD->addAttr(::new (S.Context) PackedAttr(1)); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); } @@ -308,7 +308,7 @@ static void HandleIBOutletAttr(Decl *d, const AttributeList &Attr, Sema &S) { // The IBOutlet attribute only applies to instance variables of Objective-C // classes. if (isa<ObjCIvarDecl>(d) || isa<ObjCPropertyDecl>(d)) - d->addAttr(S.Context, ::new (S.Context) IBOutletAttr()); + d->addAttr(::new (S.Context) IBOutletAttr()); else S.Diag(Attr.getLoc(), diag::err_attribute_iboutlet); } @@ -380,7 +380,7 @@ static void HandleNonNullAttr(Decl *d, const AttributeList &Attr, Sema &S) { unsigned* start = &NonNullArgs[0]; unsigned size = NonNullArgs.size(); std::sort(start, start + size); - d->addAttr(S.Context, ::new (S.Context) NonNullAttr(start, size)); + d->addAttr(::new (S.Context) NonNullAttr(start, size)); } static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -405,7 +405,7 @@ static void HandleAliasAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: check if target symbol exists in current file - d->addAttr(S.Context, ::new (S.Context) AliasAttr(std::string(Alias, AliasLen))); + d->addAttr(::new (S.Context) AliasAttr(std::string(Alias, AliasLen))); } static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, @@ -422,7 +422,7 @@ static void HandleAlwaysInlineAttr(Decl *d, const AttributeList &Attr, return; } - d->addAttr(S.Context, ::new (S.Context) AlwaysInlineAttr()); + d->addAttr(::new (S.Context) AlwaysInlineAttr()); } static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, @@ -447,13 +447,13 @@ static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr, static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (HandleCommonNoReturnAttr(d, Attr, S)) - d->addAttr(S.Context, ::new (S.Context) NoReturnAttr()); + d->addAttr(::new (S.Context) NoReturnAttr()); } static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (HandleCommonNoReturnAttr(d, Attr, S)) - d->addAttr(S.Context, ::new (S.Context) AnalyzerNoReturnAttr()); + d->addAttr(::new (S.Context) AnalyzerNoReturnAttr()); } static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -469,7 +469,7 @@ static void HandleUnusedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) UnusedAttr()); + d->addAttr(::new (S.Context) UnusedAttr()); } static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -490,7 +490,7 @@ static void HandleUsedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) UsedAttr()); + d->addAttr(::new (S.Context) UsedAttr()); } static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -519,7 +519,7 @@ static void HandleConstructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) ConstructorAttr(priority)); + d->addAttr(::new (S.Context) ConstructorAttr(priority)); } static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -548,7 +548,7 @@ static void HandleDestructorAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) DestructorAttr(priority)); + d->addAttr(::new (S.Context) DestructorAttr(priority)); } static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -558,7 +558,7 @@ static void HandleDeprecatedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) DeprecatedAttr()); + d->addAttr(::new (S.Context) DeprecatedAttr()); } static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -568,7 +568,7 @@ static void HandleUnavailableAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) UnavailableAttr()); + d->addAttr(::new (S.Context) UnavailableAttr()); } static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -605,7 +605,7 @@ static void HandleVisibilityAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) VisibilityAttr(type)); + d->addAttr(::new (S.Context) VisibilityAttr(type)); } static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, @@ -621,7 +621,7 @@ static void HandleObjCExceptionAttr(Decl *D, const AttributeList &Attr, return; } - D->addAttr(S.Context, ::new (S.Context) ObjCExceptionAttr()); + D->addAttr(::new (S.Context) ObjCExceptionAttr()); } static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { @@ -637,7 +637,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { return; } } - D->addAttr(S.Context, ::new (S.Context) ObjCNSObjectAttr()); + D->addAttr(::new (S.Context) ObjCNSObjectAttr()); } static void @@ -652,7 +652,7 @@ HandleOverloadableAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(S.Context, ::new (S.Context) OverloadableAttr()); + D->addAttr(::new (S.Context) OverloadableAttr()); } static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -676,7 +676,7 @@ static void HandleBlocksAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) BlocksAttr(type)); + d->addAttr(::new (S.Context) BlocksAttr(type)); } static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -768,7 +768,7 @@ static void HandleSentinelAttr(Decl *d, const AttributeList &Attr, Sema &S) { << Attr.getName() << 6 /*function, method or block */; return; } - d->addAttr(S.Context, ::new (S.Context) SentinelAttr(sentinel, nullPos)); + d->addAttr(::new (S.Context) SentinelAttr(sentinel, nullPos)); } static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) { @@ -786,7 +786,7 @@ static void HandleWarnUnusedResult(Decl *D, const AttributeList &Attr, Sema &S) return; } - Fn->addAttr(S.Context, ::new (S.Context) WarnUnusedResultAttr()); + Fn->addAttr(::new (S.Context) WarnUnusedResultAttr()); } static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -803,7 +803,7 @@ static void HandleWeakAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(S.Context, ::new (S.Context) WeakAttr()); + D->addAttr(::new (S.Context) WeakAttr()); } static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -818,7 +818,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { if (VarDecl *VD = dyn_cast<VarDecl>(D)) { isDef = (!VD->hasExternalStorage() || VD->getInit()); } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { - isDef = FD->getBody(S.Context); + isDef = FD->getBody(); } else if (isa<ObjCPropertyDecl>(D) || isa<ObjCMethodDecl>(D)) { // We ignore weak import on properties and methods return; @@ -836,7 +836,7 @@ static void HandleWeakImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(S.Context, ::new (S.Context) WeakImportAttr()); + D->addAttr(::new (S.Context) WeakImportAttr()); } static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -848,7 +848,7 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // Attribute can be applied only to functions or variables. if (isa<VarDecl>(D)) { - D->addAttr(S.Context, ::new (S.Context) DLLImportAttr()); + D->addAttr(::new (S.Context) DLLImportAttr()); return; } @@ -876,12 +876,12 @@ static void HandleDLLImportAttr(Decl *D, const AttributeList &Attr, Sema &S) { } } - if (D->getAttr<DLLExportAttr>(S.Context)) { + if (D->getAttr<DLLExportAttr>()) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << "dllimport"; return; } - D->addAttr(S.Context, ::new (S.Context) DLLImportAttr()); + D->addAttr(::new (S.Context) DLLImportAttr()); } static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { @@ -893,7 +893,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { // Attribute can be applied only to functions or variables. if (isa<VarDecl>(D)) { - D->addAttr(S.Context, ::new (S.Context) DLLExportAttr()); + D->addAttr(::new (S.Context) DLLExportAttr()); return; } @@ -912,7 +912,7 @@ static void HandleDLLExportAttr(Decl *D, const AttributeList &Attr, Sema &S) { return; } - D->addAttr(S.Context, ::new (S.Context) DLLExportAttr()); + D->addAttr(::new (S.Context) DLLExportAttr()); } static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, @@ -934,8 +934,7 @@ static void HandleReqdWorkGroupSize(Decl *D, const AttributeList &Attr, } WGSize[i] = (unsigned) ArgNum.getZExtValue(); } - D->addAttr(S.Context, - ::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1], + D->addAttr(::new (S.Context) ReqdWorkGroupSizeAttr(WGSize[0], WGSize[1], WGSize[2])); } @@ -955,8 +954,7 @@ static void HandleSectionAttr(Decl *D, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); return; } - D->addAttr(S.Context, - ::new (S.Context) SectionAttr(std::string(SE->getStrData(), + D->addAttr(::new (S.Context) SectionAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -975,13 +973,13 @@ static void HandleStdCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // stdcall and fastcall attributes are mutually incompatible. - if (d->getAttr<FastCallAttr>(S.Context)) { + if (d->getAttr<FastCallAttr>()) { S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) << "stdcall" << "fastcall"; return; } - d->addAttr(S.Context, ::new (S.Context) StdCallAttr()); + d->addAttr(::new (S.Context) StdCallAttr()); } static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -998,13 +996,13 @@ static void HandleFastCallAttr(Decl *d, const AttributeList &Attr, Sema &S) { } // stdcall and fastcall attributes are mutually incompatible. - if (d->getAttr<StdCallAttr>(S.Context)) { + if (d->getAttr<StdCallAttr>()) { S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible) << "fastcall" << "stdcall"; return; } - d->addAttr(S.Context, ::new (S.Context) FastCallAttr()); + d->addAttr(::new (S.Context) FastCallAttr()); } static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1014,7 +1012,7 @@ static void HandleNothrowAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) NoThrowAttr()); + d->addAttr(::new (S.Context) NoThrowAttr()); } static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1024,7 +1022,7 @@ static void HandleConstAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) ConstAttr()); + d->addAttr(::new (S.Context) ConstAttr()); } static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1034,7 +1032,7 @@ static void HandlePureAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) PureAttr()); + d->addAttr(::new (S.Context) PureAttr()); } static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1092,7 +1090,7 @@ static void HandleCleanupAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) CleanupAttr(FD)); + d->addAttr(::new (S.Context) CleanupAttr(FD)); } /// Handle __attribute__((format_arg((idx)))) attribute @@ -1155,7 +1153,7 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) FormatArgAttr(Idx.getZExtValue())); + d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue())); } /// Handle __attribute__((format(type,idx,firstarg))) attributes @@ -1296,8 +1294,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, - ::new (S.Context) FormatAttr(std::string(Format, FormatLen), + d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen), Idx.getZExtValue(), FirstArg.getZExtValue())); } @@ -1329,8 +1326,8 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, return; } - RecordDecl::field_iterator Field = RD->field_begin(S.Context), - FieldEnd = RD->field_end(S.Context); + RecordDecl::field_iterator Field = RD->field_begin(), + FieldEnd = RD->field_end(); if (Field == FieldEnd) { S.Diag(Attr.getLoc(), diag::warn_transparent_union_attribute_zero_fields); return; @@ -1365,7 +1362,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, } } - RD->addAttr(S.Context, ::new (S.Context) TransparentUnionAttr()); + RD->addAttr(::new (S.Context) TransparentUnionAttr()); } static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1383,8 +1380,7 @@ static void HandleAnnotateAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_annotate_no_string); return; } - d->addAttr(S.Context, - ::new (S.Context) AnnotateAttr(std::string(SE->getStrData(), + d->addAttr(::new (S.Context) AnnotateAttr(std::string(SE->getStrData(), SE->getByteLength()))); } @@ -1400,7 +1396,7 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { // FIXME: This should be the target specific maximum alignment. // (For now we just use 128 bits which is the maximum on X86). Align = 128; - d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Align)); + d->addAttr(::new (S.Context) AlignedAttr(Align)); return; } @@ -1417,7 +1413,7 @@ static void HandleAlignedAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8)); + d->addAttr(::new (S.Context) AlignedAttr(Alignment.getZExtValue() * 8)); } /// HandleModeAttr - This attribute modifies the width of a decl with @@ -1598,7 +1594,7 @@ static void HandleNodebugAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) NodebugAttr()); + d->addAttr(::new (S.Context) NodebugAttr()); } static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1614,7 +1610,7 @@ static void HandleNoinlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) NoinlineAttr()); + d->addAttr(::new (S.Context) NoinlineAttr()); } static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1636,7 +1632,7 @@ static void HandleGNUInlineAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, ::new (S.Context) GNUInlineAttr()); + d->addAttr(::new (S.Context) GNUInlineAttr()); } static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1672,8 +1668,7 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { return; } - d->addAttr(S.Context, - ::new (S.Context) RegparmAttr(NumParams.getZExtValue())); + d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue())); } //===----------------------------------------------------------------------===// @@ -1706,10 +1701,10 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr, assert(0 && "invalid ownership attribute"); return; case AttributeList::AT_cf_returns_retained: - d->addAttr(S.Context, ::new (S.Context) CFReturnsRetainedAttr()); + d->addAttr(::new (S.Context) CFReturnsRetainedAttr()); return; case AttributeList::AT_ns_returns_retained: - d->addAttr(S.Context, ::new (S.Context) NSReturnsRetainedAttr()); + d->addAttr(::new (S.Context) NSReturnsRetainedAttr()); return; }; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index cf0dab5cf298..75ceb1916555 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -258,6 +258,12 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old) { } } + if (CheckEquivalentExceptionSpec( + Old->getType()->getAsFunctionProtoType(), Old->getLocation(), + New->getType()->getAsFunctionProtoType(), New->getLocation())) { + Invalid = true; + } + return Invalid; } @@ -481,7 +487,7 @@ bool Sema::AttachBaseSpecifiers(CXXRecordDecl *Class, CXXBaseSpecifier **Bases, } // Attach the remaining base class specifiers to the derived class. - Class->setBases(Bases, NumGoodBases); + Class->setBases(Context, Bases, NumGoodBases); // Delete the remaining (good) base class specifiers, since their // data has been copied into the CXXRecordDecl. @@ -646,7 +652,9 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, Sema::MemInitResult Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, Scope *S, + const CXXScopeSpec &SS, IdentifierInfo *MemberOrBase, + TypeTy *TemplateTypeTy, SourceLocation IdLoc, SourceLocation LParenLoc, ExprTy **Args, unsigned NumArgs, @@ -677,28 +685,31 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, // composed of a single identifier refers to the class member. A // mem-initializer-id for the hidden base class may be specified // using a qualified name. ] - // Look for a member, first. - FieldDecl *Member = 0; - DeclContext::lookup_result Result - = ClassDecl->lookup(Context, MemberOrBase); - if (Result.first != Result.second) - Member = dyn_cast<FieldDecl>(*Result.first); - - // FIXME: Handle members of an anonymous union. - - if (Member) { - // FIXME: Perform direct initialization of the member. - return new CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs); + if (!SS.getScopeRep() && !TemplateTypeTy) { + // Look for a member, first. + FieldDecl *Member = 0; + DeclContext::lookup_result Result + = ClassDecl->lookup(MemberOrBase); + if (Result.first != Result.second) + Member = dyn_cast<FieldDecl>(*Result.first); + + // FIXME: Handle members of an anonymous union. + + if (Member) { + // FIXME: Perform direct initialization of the member. + return new CXXBaseOrMemberInitializer(Member, (Expr **)Args, NumArgs, + IdLoc); + } } - // It didn't name a member, so see if it names a class. - TypeTy *BaseTy = getTypeName(*MemberOrBase, IdLoc, S, 0/*SS*/); + TypeTy *BaseTy = TemplateTypeTy ? TemplateTypeTy + : getTypeName(*MemberOrBase, IdLoc, S, &SS); if (!BaseTy) return Diag(IdLoc, diag::err_mem_init_not_member_or_class) << MemberOrBase << SourceRange(IdLoc, RParenLoc); QualType BaseType = QualType::getFromOpaquePtr(BaseTy); - if (!BaseType->isRecordType()) + if (!BaseType->isRecordType() && !BaseType->isDependentType()) return Diag(IdLoc, diag::err_base_init_does_not_name_class) << BaseType << SourceRange(IdLoc, RParenLoc); @@ -749,8 +760,18 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, if (DirectBaseSpec && VirtualBaseSpec) return Diag(IdLoc, diag::err_base_init_direct_and_virtual) << MemberOrBase << SourceRange(IdLoc, RParenLoc); + // C++ [base.class.init]p2: + // Unless the mem-initializer-id names a nonstatic data membeer of the + // constructor's class ot a direst or virtual base of that class, the + // mem-initializer is ill-formed. + if (!DirectBaseSpec && !VirtualBaseSpec) + return Diag(IdLoc, diag::err_not_direct_base_or_virtual) + << BaseType << ClassDecl->getNameAsCString() + << SourceRange(IdLoc, RParenLoc); + - return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs); + return new CXXBaseOrMemberInitializer(BaseType, (Expr **)Args, NumArgs, + IdLoc); } void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, @@ -766,6 +787,42 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl, Diag(ColonLoc, diag::err_only_constructors_take_base_inits); return; } + llvm::DenseMap<void*, CXXBaseOrMemberInitializer *>Members; + bool err = false; + for (unsigned i = 0; i < NumMemInits; i++) { + CXXBaseOrMemberInitializer *Member = + static_cast<CXXBaseOrMemberInitializer*>(MemInits[i]); + void *KeyToMember = Member->getBaseOrMember(); + // For fields injected into the class via declaration of an anonymous union, + // use its anonymous union class declaration as the unique key. + if (FieldDecl *Field = Member->getMember()) + if (Field->getDeclContext()->isRecord() && + cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion()) + KeyToMember = static_cast<void *>(Field->getDeclContext()); + CXXBaseOrMemberInitializer *&PrevMember = Members[KeyToMember]; + if (!PrevMember) { + PrevMember = Member; + continue; + } + if (FieldDecl *Field = Member->getMember()) + Diag(Member->getSourceLocation(), + diag::error_multiple_mem_initialization) + << Field->getNameAsString(); + else { + Type *BaseClass = Member->getBaseClass(); + assert(BaseClass && "ActOnMemInitializers - neither field or base"); + Diag(Member->getSourceLocation(), + diag::error_multiple_base_initialization) + << BaseClass->getDesugaredType(true); + } + Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer) + << 0; + err = true; + } + if (!err) + Constructor->setBaseOrMemberInitializers(Context, + reinterpret_cast<CXXBaseOrMemberInitializer **>(MemInits), + NumMemInits); } namespace { @@ -821,8 +878,7 @@ namespace { MethodSetTy OverriddenMethods; size_t MethodsSize = Methods.size(); - for (RecordDecl::decl_iterator i = RD->decls_begin(Context), - e = RD->decls_end(Context); + for (RecordDecl::decl_iterator i = RD->decls_begin(), e = RD->decls_end(); i != e; ++i) { // Traverse the record, looking for methods. if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) { @@ -919,8 +975,8 @@ namespace { bool VisitDeclContext(const DeclContext *DC) { bool Invalid = false; - for (CXXRecordDecl::decl_iterator I = DC->decls_begin(SemaRef.Context), - E = DC->decls_end(SemaRef.Context); I != E; ++I) + for (CXXRecordDecl::decl_iterator I = DC->decls_begin(), + E = DC->decls_end(); I != E; ++I) Invalid |= Visit(*I); return Invalid; @@ -996,8 +1052,8 @@ void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, AbstractClassUsageDiagnoser(*this, RD); if (RD->hasTrivialConstructor() || RD->hasTrivialDestructor()) { - for (RecordDecl::field_iterator i = RD->field_begin(Context), - e = RD->field_end(Context); i != e; ++i) { + for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end(); + i != e; ++i) { // All the nonstatic data members must have trivial constructors. QualType FTy = i->getType(); while (const ArrayType *AT = Context.getAsArrayType(FTy)) @@ -1054,7 +1110,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { /*isImplicitlyDeclared=*/true); DefaultCon->setAccess(AS_public); DefaultCon->setImplicit(); - ClassDecl->addDecl(Context, DefaultCon); + ClassDecl->addDecl(DefaultCon); } if (!ClassDecl->hasUserDeclaredCopyConstructor()) { @@ -1086,8 +1142,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // class type M (or array thereof), each such class type // has a copy constructor whose first parameter is of type // const M& or const volatile M&. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context); - HasConstCopyConstructor && Field != ClassDecl->field_end(Context); + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(); + HasConstCopyConstructor && Field != ClassDecl->field_end(); ++Field) { QualType FieldType = (*Field)->getType(); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) @@ -1131,7 +1187,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { /*IdentifierInfo=*/0, ArgType, VarDecl::None, 0); CopyConstructor->setParams(Context, &FromParam, 1); - ClassDecl->addDecl(Context, CopyConstructor); + ClassDecl->addDecl(CopyConstructor); } if (!ClassDecl->hasUserDeclaredCopyAssignment()) { @@ -1165,8 +1221,8 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // type M (or array thereof), each such class type has a copy // assignment operator whose parameter is of type const M&, // const volatile M& or M. - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context); - HasConstCopyAssignment && Field != ClassDecl->field_end(Context); + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(); + HasConstCopyAssignment && Field != ClassDecl->field_end(); ++Field) { QualType FieldType = (*Field)->getType(); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) @@ -1210,7 +1266,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { // Don't call addedAssignmentOperator. There is no way to distinguish an // implicit from an explicit assignment operator. - ClassDecl->addDecl(Context, CopyAssignment); + ClassDecl->addDecl(CopyAssignment); } if (!ClassDecl->hasUserDeclaredDestructor()) { @@ -1229,7 +1285,7 @@ void Sema::AddImplicitlyDeclaredMembersToClass(CXXRecordDecl *ClassDecl) { /*isImplicitlyDeclared=*/true); Destructor->setAccess(AS_public); Destructor->setImplicit(); - ClassDecl->addDecl(Context, Destructor); + ClassDecl->addDecl(Destructor); } } @@ -1772,7 +1828,7 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { // or translation unit scope. We add UsingDirectiveDecls, into // it's lookup structure. if (DeclContext *Ctx = static_cast<DeclContext*>(S->getEntity())) - Ctx->addDecl(Context, UDir); + Ctx->addDecl(UDir); else // Otherwise it is block-sope. using-directives will affect lookup // only to the end of scope. @@ -1873,7 +1929,7 @@ Sema::DeclPtrTy Sema::ActOnNamespaceAliasDef(Scope *S, (NestedNameSpecifier *)SS.getScopeRep(), IdentLoc, R); - CurContext->addDecl(Context, AliasDecl); + CurContext->addDecl(AliasDecl); return DeclPtrTy::make(AliasDecl); } @@ -1891,8 +1947,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, // for its base class and its non-static data members shall have been // implicitly defined. bool err = false; - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); - Base != ClassDecl->bases_end(); ++Base) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); if (!BaseClassDecl->hasTrivialConstructor()) { @@ -1909,9 +1965,8 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, } } } - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context); - Field != ClassDecl->field_end(Context); - ++Field) { + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) { QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); @@ -1964,8 +2019,8 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, // implicitly defined, all the implicitly-declared default destructors // for its base class and its non-static data members shall have been // implicitly defined. - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); - Base != ClassDecl->bases_end(); ++Base) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); if (!BaseClassDecl->hasTrivialDestructor()) { @@ -1978,9 +2033,8 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, } } - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context); - Field != ClassDecl->field_end(Context); - ++Field) { + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) { QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); @@ -2010,7 +2064,6 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation, CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(MethodDecl->getDeclContext()); - assert(ClassDecl && "DefineImplicitOverloadedAssign - invalid constructor"); // C++[class.copy] p12 // Before the implicitly-declared copy assignment operator for a class is @@ -2018,17 +2071,16 @@ void Sema::DefineImplicitOverloadedAssign(SourceLocation CurrentLocation, // for its direct base classes and its nonstatic data members shall have // been implicitly defined. bool err = false; - for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); - Base != ClassDecl->bases_end(); ++Base) { + for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(), + E = ClassDecl->bases_end(); Base != E; ++Base) { CXXRecordDecl *BaseClassDecl = cast<CXXRecordDecl>(Base->getType()->getAsRecordType()->getDecl()); if (CXXMethodDecl *BaseAssignOpMethod = getAssignOperatorMethod(MethodDecl->getParamDecl(0), BaseClassDecl)) MarkDeclarationReferenced(CurrentLocation, BaseAssignOpMethod); } - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context); - Field != ClassDecl->field_end(Context); - ++Field) { + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + E = ClassDecl->field_end(); Field != E; ++Field) { QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); @@ -2113,9 +2165,9 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, BaseClassDecl->getCopyConstructor(Context, TypeQuals)) MarkDeclarationReferenced(CurrentLocation, BaseCopyCtor); } - for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(Context); - Field != ClassDecl->field_end(Context); - ++Field) { + for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(), + FieldEnd = ClassDecl->field_end(); + Field != FieldEnd; ++Field) { QualType FieldType = Context.getCanonicalType((*Field)->getType()); if (const ArrayType *Array = Context.getAsArrayType(FieldType)) FieldType = Array->getElementType(); @@ -2140,7 +2192,7 @@ void Sema::InitializeVarWithConstructor(VarDecl *VD, VD->setInit(Context, Temp); } -void Sema::MarcDestructorReferenced(SourceLocation Loc, QualType DeclInitType) +void Sema::MarkDestructorReferenced(SourceLocation Loc, QualType DeclInitType) { CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>( DeclInitType->getAsRecordType()->getDecl()); @@ -2218,7 +2270,7 @@ void Sema::AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, (Expr**)Exprs.release(), NumExprs); // FIXME. Must do all that is needed to destroy the object // on scope exit. For now, just mark the destructor as used. - MarcDestructorReferenced(VDecl->getLocation(), DeclInitType); + MarkDestructorReferenced(VDecl->getLocation(), DeclInitType); } return; } @@ -2282,7 +2334,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, = Context.DeclarationNames.getCXXConstructorName( Context.getCanonicalType(ClassType.getUnqualifiedType())); DeclContext::lookup_const_iterator Con, ConEnd; - for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(Context, ConstructorName); + for (llvm::tie(Con, ConEnd) = ClassDecl->lookup(ConstructorName); Con != ConEnd; ++Con) { CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); if ((Kind == IK_Direct) || @@ -2892,7 +2944,7 @@ Sema::DeclPtrTy Sema::ActOnStartLinkageSpecification(Scope *S, LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext, LangLoc, Language, LBraceLoc.isValid()); - CurContext->addDecl(Context, D); + CurContext->addDecl(D); PushDeclContext(S, D); return DeclPtrTy::make(D); } @@ -3006,7 +3058,7 @@ Sema::DeclPtrTy Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D) { if (II) PushOnScopeChains(ExDecl, S); else - CurContext->addDecl(Context, ExDecl); + CurContext->addDecl(ExDecl); ProcessDeclAttributes(S, ExDecl, D); return DeclPtrTy::make(ExDecl); @@ -3040,7 +3092,7 @@ Sema::DeclPtrTy Sema::ActOnStaticAssertDeclaration(SourceLocation AssertLoc, Decl *Decl = StaticAssertDecl::Create(Context, CurContext, AssertLoc, AssertExpr, AssertMessage); - CurContext->addDecl(Context, Decl); + CurContext->addDecl(Decl); return DeclPtrTy::make(Decl); } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 9013726e1aee..5cf48d6da0c8 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -379,12 +379,12 @@ void Sema::ComparePropertiesInBaseAndSuper(ObjCInterfaceDecl *IDecl) { if (!SDecl) return; // FIXME: O(N^2) - for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(Context), - E = SDecl->prop_end(Context); S != E; ++S) { + for (ObjCInterfaceDecl::prop_iterator S = SDecl->prop_begin(), + E = SDecl->prop_end(); S != E; ++S) { ObjCPropertyDecl *SuperPDecl = (*S); // Does property in super class has declaration in current class? - for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(Context), - E = IDecl->prop_end(Context); I != E; ++I) { + for (ObjCInterfaceDecl::prop_iterator I = IDecl->prop_begin(), + E = IDecl->prop_end(); I != E; ++I) { ObjCPropertyDecl *PDecl = (*I); if (SuperPDecl->getIdentifier() == PDecl->getIdentifier()) DiagnosePropertyMismatch(PDecl, SuperPDecl, @@ -404,13 +404,12 @@ Sema::MergeOneProtocolPropertiesIntoClass(Decl *CDecl, // Category ObjCCategoryDecl *CatDecl = static_cast<ObjCCategoryDecl*>(CDecl); assert (CatDecl && "MergeOneProtocolPropertiesIntoClass"); - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(Context), - E = PDecl->prop_end(Context); P != E; ++P) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { ObjCPropertyDecl *Pr = (*P); ObjCCategoryDecl::prop_iterator CP, CE; // Is this property already in category's list of properties? - for (CP = CatDecl->prop_begin(Context), CE = CatDecl->prop_end(Context); - CP != CE; ++CP) + for (CP = CatDecl->prop_begin(), CE = CatDecl->prop_end(); CP != CE; ++CP) if ((*CP)->getIdentifier() == Pr->getIdentifier()) break; if (CP != CE) @@ -419,13 +418,12 @@ Sema::MergeOneProtocolPropertiesIntoClass(Decl *CDecl, } return; } - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(Context), - E = PDecl->prop_end(Context); P != E; ++P) { + for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), + E = PDecl->prop_end(); P != E; ++P) { ObjCPropertyDecl *Pr = (*P); ObjCInterfaceDecl::prop_iterator CP, CE; // Is this property already in class's list of properties? - for (CP = IDecl->prop_begin(Context), CE = IDecl->prop_end(Context); - CP != CE; ++CP) + for (CP = IDecl->prop_begin(), CE = IDecl->prop_end(); CP != CE; ++CP) if ((*CP)->getIdentifier() == Pr->getIdentifier()) break; if (CP != CE) @@ -495,16 +493,16 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, return; // Possibly due to previous error llvm::DenseMap<Selector, const ObjCMethodDecl*> MethodMap; - for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(Context), - e = ID->meth_end(Context); i != e; ++i) { + for (ObjCInterfaceDecl::method_iterator i = ID->meth_begin(), + e = ID->meth_end(); i != e; ++i) { ObjCMethodDecl *MD = *i; MethodMap[MD->getSelector()] = MD; } if (MethodMap.empty()) return; - for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(Context), - e = CAT->meth_end(Context); i != e; ++i) { + for (ObjCCategoryDecl::method_iterator i = CAT->meth_begin(), + e = CAT->meth_end(); i != e; ++i) { ObjCMethodDecl *Method = *i; const ObjCMethodDecl *&PrevMethod = MethodMap[Method->getSelector()]; if (PrevMethod && !MatchTwoMethodDeclarations(Method, PrevMethod)) { @@ -539,7 +537,7 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, ObjCForwardProtocolDecl *PDecl = ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc, &Protocols[0], Protocols.size()); - CurContext->addDecl(Context, PDecl); + CurContext->addDecl(PDecl); CheckObjCDeclScope(PDecl); return DeclPtrTy::make(PDecl); } @@ -555,7 +553,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, ObjCCategoryDecl *CDecl = ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, CategoryName); // FIXME: PushOnScopeChains? - CurContext->addDecl(Context, CDecl); + CurContext->addDecl(CDecl); ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName); /// Check that class of this category is already completely declared. @@ -609,7 +607,7 @@ Sema::DeclPtrTy Sema::ActOnStartCategoryImplementation( Diag(ClassLoc, diag::err_undef_interface) << ClassName; // FIXME: PushOnScopeChains? - CurContext->addDecl(Context, CDecl); + CurContext->addDecl(CDecl); /// TODO: Check that CatName, category name, is not used in another // implementation. @@ -808,7 +806,7 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, return false; // Even if property is ready only, if interface has a user defined setter, // it is not considered read only. - if (IDecl->getInstanceMethod(Context, PDecl->getSetterName())) + if (IDecl->getInstanceMethod(PDecl->getSetterName())) return false; // Main class has the property as 'readonly'. Must search @@ -818,10 +816,10 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, Category; Category = Category->getNextClassCategory()) { // Even if property is ready only, if a category has a user defined setter, // it is not considered read only. - if (Category->getInstanceMethod(Context, PDecl->getSetterName())) + if (Category->getInstanceMethod(PDecl->getSetterName())) return false; ObjCPropertyDecl *P = - Category->FindPropertyDeclaration(Context, PDecl->getIdentifier()); + Category->FindPropertyDeclaration(PDecl->getIdentifier()); if (P && !P->isReadOnly()) return false; } @@ -831,19 +829,19 @@ bool Sema::isPropertyReadonly(ObjCPropertyDecl *PDecl, if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(CurContext)) { if (ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OMD->getDeclContext())) { - if (IMD->getInstanceMethod(Context, PDecl->getSetterName())) + if (IMD->getInstanceMethod(PDecl->getSetterName())) return false; } else if (ObjCCategoryImplDecl *CIMD = dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) { - if (CIMD->getInstanceMethod(Context, PDecl->getSetterName())) + if (CIMD->getInstanceMethod(PDecl->getSetterName())) return false; } } // Lastly, look through the implementation (if one is in scope). if (ObjCImplementationDecl *ImpDecl = LookupObjCImplementation(IDecl->getIdentifier())) - if (ImpDecl->getInstanceMethod(Context, PDecl->getSetterName())) + if (ImpDecl->getInstanceMethod(PDecl->getSetterName())) return false; // If all fails, look at the super class. if (ObjCInterfaceDecl *SIDecl = IDecl->getSuperClass()) @@ -890,31 +888,30 @@ void Sema::CheckProtocolMethodDefs(SourceLocation ImpLoc, // check unimplemented instance methods. if (!NSIDecl) - for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(Context), - E = PDecl->instmeth_end(Context); I != E; ++I) { + for (ObjCProtocolDecl::instmeth_iterator I = PDecl->instmeth_begin(), + E = PDecl->instmeth_end(); I != E; ++I) { ObjCMethodDecl *method = *I; if (method->getImplementationControl() != ObjCMethodDecl::Optional && !method->isSynthesized() && !InsMap.count(method->getSelector()) && (!Super || - !Super->lookupInstanceMethod(Context, method->getSelector()))) { + !Super->lookupInstanceMethod(method->getSelector()))) { // Ugly, but necessary. Method declared in protcol might have // have been synthesized due to a property declared in the class which // uses the protocol. ObjCMethodDecl *MethodInClass = - IDecl->lookupInstanceMethod(Context, method->getSelector()); + IDecl->lookupInstanceMethod(method->getSelector()); if (!MethodInClass || !MethodInClass->isSynthesized()) WarnUndefinedMethod(ImpLoc, method, IncompleteImpl); } } // check unimplemented class methods for (ObjCProtocolDecl::classmeth_iterator - I = PDecl->classmeth_begin(Context), - E = PDecl->classmeth_end(Context); + I = PDecl->classmeth_begin(), E = PDecl->classmeth_end(); I != E; ++I) { ObjCMethodDecl *method = *I; if (method->getImplementationControl() != ObjCMethodDecl::Optional && !ClsMap.count(method->getSelector()) && - (!Super || !Super->lookupClassMethod(Context, method->getSelector()))) + (!Super || !Super->lookupClassMethod(method->getSelector()))) WarnUndefinedMethod(ImpLoc, method, IncompleteImpl); } // Check on this protocols's referenced protocols, recursively. @@ -937,8 +934,8 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, { // Check and see if instance methods in class interface have been // implemented in the implementation class. If so, their types match. - for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(Context), - E = CDecl->instmeth_end(Context); I != E; ++I) { + for (ObjCInterfaceDecl::instmeth_iterator I = CDecl->instmeth_begin(), + E = CDecl->instmeth_end(); I != E; ++I) { if (InsMapSeen.count((*I)->getSelector())) continue; InsMapSeen.insert((*I)->getSelector()); @@ -950,9 +947,9 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, } else { ObjCMethodDecl *ImpMethodDecl = - IMPDecl->getInstanceMethod(Context, (*I)->getSelector()); + IMPDecl->getInstanceMethod((*I)->getSelector()); ObjCMethodDecl *IntfMethodDecl = - CDecl->getInstanceMethod(Context, (*I)->getSelector()); + CDecl->getInstanceMethod((*I)->getSelector()); assert(IntfMethodDecl && "IntfMethodDecl is null in ImplMethodsVsClassMethods"); // ImpMethodDecl may be null as in a @dynamic property. @@ -964,9 +961,7 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, // Check and see if class methods in class interface have been // implemented in the implementation class. If so, their types match. for (ObjCInterfaceDecl::classmeth_iterator - I = CDecl->classmeth_begin(Context), - E = CDecl->classmeth_end(Context); - I != E; ++I) { + I = CDecl->classmeth_begin(), E = CDecl->classmeth_end(); I != E; ++I) { if (ClsMapSeen.count((*I)->getSelector())) continue; ClsMapSeen.insert((*I)->getSelector()); @@ -975,10 +970,10 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap, WarnUndefinedMethod(IMPDecl->getLocation(), *I, IncompleteImpl); } else { - ObjCMethodDecl *ImpMethodDecl = - IMPDecl->getClassMethod(Context, (*I)->getSelector()); + ObjCMethodDecl *ImpMethodDecl = + IMPDecl->getClassMethod((*I)->getSelector()); ObjCMethodDecl *IntfMethodDecl = - CDecl->getClassMethod(Context, (*I)->getSelector()); + CDecl->getClassMethod((*I)->getSelector()); WarnConflictingTypedMethods(ImpMethodDecl, IntfMethodDecl); } } @@ -1003,24 +998,23 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, // Check and see if instance methods in class interface have been // implemented in the implementation class. for (ObjCImplementationDecl::instmeth_iterator - I = IMPDecl->instmeth_begin(Context), - E = IMPDecl->instmeth_end(Context); I != E; ++I) + I = IMPDecl->instmeth_begin(), E = IMPDecl->instmeth_end(); I!=E; ++I) InsMap.insert((*I)->getSelector()); // Check and see if properties declared in the interface have either 1) // an implementation or 2) there is a @synthesize/@dynamic implementation // of the property in the @implementation. if (isa<ObjCInterfaceDecl>(CDecl)) - for (ObjCContainerDecl::prop_iterator P = CDecl->prop_begin(Context), - E = CDecl->prop_end(Context); P != E; ++P) { + for (ObjCContainerDecl::prop_iterator P = CDecl->prop_begin(), + E = CDecl->prop_end(); P != E; ++P) { ObjCPropertyDecl *Prop = (*P); if (Prop->isInvalidDecl()) continue; ObjCPropertyImplDecl *PI = 0; // Is there a matching propery synthesize/dynamic? for (ObjCImplDecl::propimpl_iterator - I = IMPDecl->propimpl_begin(Context), - EI = IMPDecl->propimpl_end(Context); I != EI; ++I) + I = IMPDecl->propimpl_begin(), + EI = IMPDecl->propimpl_end(); I != EI; ++I) if ((*I)->getPropertyDecl() == Prop) { PI = (*I); break; @@ -1046,8 +1040,8 @@ void Sema::ImplMethodsVsClassMethods(ObjCImplDecl* IMPDecl, llvm::DenseSet<Selector> ClsMap; for (ObjCImplementationDecl::classmeth_iterator - I = IMPDecl->classmeth_begin(Context), - E = IMPDecl->classmeth_end(Context); I != E; ++I) + I = IMPDecl->classmeth_begin(), + E = IMPDecl->classmeth_end(); I != E; ++I) ClsMap.insert((*I)->getSelector()); // Check for type conflict of methods declared in a class/protocol and @@ -1134,7 +1128,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, ObjCClassDecl *CDecl = ObjCClassDecl::Create(Context, CurContext, AtClassLoc, &Interfaces[0], Interfaces.size()); - CurContext->addDecl(Context, CDecl); + CurContext->addDecl(CDecl); CheckObjCDeclScope(CDecl); return DeclPtrTy::make(CDecl); } @@ -1348,8 +1342,8 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCContainerDecl *CD) { ObjCMethodDecl *GetterMethod, *SetterMethod; - GetterMethod = CD->getInstanceMethod(Context, property->getGetterName()); - SetterMethod = CD->getInstanceMethod(Context, property->getSetterName()); + GetterMethod = CD->getInstanceMethod(property->getGetterName()); + SetterMethod = CD->getInstanceMethod(property->getSetterName()); DiagnosePropertyAccessorMismatch(property, GetterMethod, property->getLocation()); @@ -1384,7 +1378,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, ObjCPropertyDecl::Optional) ? ObjCMethodDecl::Optional : ObjCMethodDecl::Required); - CD->addDecl(Context, GetterMethod); + CD->addDecl(GetterMethod); } else // A user declared getter will be synthesize when @synthesize of // the property with the same name is seen in the @implementation @@ -1415,7 +1409,7 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property, VarDecl::None, 0); SetterMethod->setMethodParams(Context, &Argument, 1); - CD->addDecl(Context, SetterMethod); + CD->addDecl(SetterMethod); } else // A user declared setter will be synthesize when @synthesize of // the property with the same name is seen in the @implementation @@ -1481,7 +1475,7 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl, << Method->getDeclName(); Diag(PrevMethod->getLocation(), diag::note_previous_declaration); } else { - DC->addDecl(Context, Method); + DC->addDecl(Method); InsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "id". AddInstanceMethodToGlobalPool(Method); @@ -1498,7 +1492,7 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl, << Method->getDeclName(); Diag(PrevMethod->getLocation(), diag::note_previous_declaration); } else { - DC->addDecl(Context, Method); + DC->addDecl(Method); ClsMap[Method->getSelector()] = Method; /// The following allows us to typecheck messages to "Class". AddFactoryMethodToGlobalPool(Method); @@ -1524,8 +1518,8 @@ void Sema::ActOnAtEnd(SourceLocation AtEndLoc, DeclPtrTy classDecl, // ProcessPropertyDecl is responsible for diagnosing conflicts with any // user-defined setter/getter. It also synthesizes setter/getter methods // and adds them to the DeclContext and global method pools. - for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(Context), - E = CDecl->prop_end(Context); + for (ObjCContainerDecl::prop_iterator I = CDecl->prop_begin(), + E = CDecl->prop_end(); I != E; ++I) ProcessPropertyDecl(*I, CDecl); CDecl->setAtEndLoc(AtEndLoc); @@ -1683,11 +1677,11 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( if (ObjCImplementationDecl *ImpDecl = dyn_cast<ObjCImplementationDecl>(ClassDecl)) { if (MethodType == tok::minus) { - PrevMethod = ImpDecl->getInstanceMethod(Context, Sel); - ImpDecl->addInstanceMethod(Context, ObjCMethod); + PrevMethod = ImpDecl->getInstanceMethod(Sel); + ImpDecl->addInstanceMethod(ObjCMethod); } else { - PrevMethod = ImpDecl->getClassMethod(Context, Sel); - ImpDecl->addClassMethod(Context, ObjCMethod); + PrevMethod = ImpDecl->getClassMethod(Sel); + ImpDecl->addClassMethod(ObjCMethod); } if (AttrList) Diag(EndLoc, diag::warn_attribute_method_def); @@ -1695,11 +1689,11 @@ Sema::DeclPtrTy Sema::ActOnMethodDeclaration( else if (ObjCCategoryImplDecl *CatImpDecl = dyn_cast<ObjCCategoryImplDecl>(ClassDecl)) { if (MethodType == tok::minus) { - PrevMethod = CatImpDecl->getInstanceMethod(Context, Sel); - CatImpDecl->addInstanceMethod(Context, ObjCMethod); + PrevMethod = CatImpDecl->getInstanceMethod(Sel); + CatImpDecl->addInstanceMethod(ObjCMethod); } else { - PrevMethod = CatImpDecl->getClassMethod(Context, Sel); - CatImpDecl->addClassMethod(Context, ObjCMethod); + PrevMethod = CatImpDecl->getClassMethod(Sel); + CatImpDecl->addClassMethod(ObjCMethod); } if (AttrList) Diag(EndLoc, diag::warn_attribute_method_def); @@ -1823,8 +1817,7 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, ObjCPropertyDecl *PIDecl = 0; IdentifierInfo *PropertyId = FD.D.getIdentifier(); for (ObjCInterfaceDecl::prop_iterator - I = CCPrimary->prop_begin(Context), - E = CCPrimary->prop_end(Context); + I = CCPrimary->prop_begin(), E = CCPrimary->prop_end(); I != E; ++I) if ((*I)->getIdentifier() == PropertyId) { PIDecl = *I; @@ -1870,7 +1863,7 @@ Sema::DeclPtrTy Sema::ActOnProperty(Scope *S, SourceLocation AtLoc, ObjCPropertyDecl *PDecl = ObjCPropertyDecl::Create(Context, DC, FD.D.getIdentifierLoc(), FD.D.getIdentifier(), T); - DC->addDecl(Context, PDecl); + DC->addDecl(PDecl); if (T->isArrayType() || T->isFunctionType()) { Diag(AtLoc, diag::err_property_type) << T; @@ -1951,7 +1944,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, "ActOnPropertyImplDecl - @implementation without @interface"); // Look for this property declaration in the @implementation's @interface - property = IDecl->FindPropertyDeclaration(Context, PropertyId); + property = IDecl->FindPropertyDeclaration(PropertyId); if (!property) { Diag(PropertyLoc, diag::error_bad_property_decl) << IDecl->getDeclName(); return DeclPtrTy(); @@ -1975,7 +1968,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, if (!Category) return DeclPtrTy(); // Look for this property declaration in @implementation's category - property = Category->FindPropertyDeclaration(Context, PropertyId); + property = Category->FindPropertyDeclaration(PropertyId); if (!property) { Diag(PropertyLoc, diag::error_bad_category_property_decl) << Category->getDeclName(); @@ -1994,7 +1987,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, QualType PropType = Context.getCanonicalType(property->getType()); // Check that this is a previously declared 'ivar' in 'IDecl' interface ObjCInterfaceDecl *ClassDeclared; - Ivar = IDecl->lookupInstanceVariable(Context, PropertyIvar, ClassDeclared); + Ivar = IDecl->lookupInstanceVariable(PropertyIvar, ClassDeclared); if (!Ivar) { DeclContext *EnclosingContext = cast_or_null<DeclContext>(IDecl); assert(EnclosingContext && @@ -2004,7 +1997,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, ObjCIvarDecl::Public, (Expr *)0); Ivar->setLexicalDeclContext(IDecl); - IDecl->addDecl(Context, Ivar); + IDecl->addDecl(Ivar); property->setPropertyIvarDecl(Ivar); if (!getLangOptions().ObjCNonFragileABI) Diag(PropertyLoc, diag::error_missing_property_ivar_decl) << PropertyId; @@ -2071,7 +2064,7 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, if (IC) { if (Synthesize) if (ObjCPropertyImplDecl *PPIDecl = - IC->FindPropertyImplIvarDecl(Context, PropertyIvar)) { + IC->FindPropertyImplIvarDecl(PropertyIvar)) { Diag(PropertyLoc, diag::error_duplicate_ivar_use) << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() << PropertyIvar; @@ -2079,17 +2072,17 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, } if (ObjCPropertyImplDecl *PPIDecl - = IC->FindPropertyImplDecl(Context, PropertyId)) { + = IC->FindPropertyImplDecl(PropertyId)) { Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; Diag(PPIDecl->getLocation(), diag::note_previous_declaration); return DeclPtrTy(); } - IC->addPropertyImplementation(Context, PIDecl); + IC->addPropertyImplementation(PIDecl); } else { if (Synthesize) if (ObjCPropertyImplDecl *PPIDecl = - CatImplClass->FindPropertyImplIvarDecl(Context, PropertyIvar)) { + CatImplClass->FindPropertyImplIvarDecl(PropertyIvar)) { Diag(PropertyLoc, diag::error_duplicate_ivar_use) << PropertyId << PPIDecl->getPropertyDecl()->getIdentifier() << PropertyIvar; @@ -2097,12 +2090,12 @@ Sema::DeclPtrTy Sema::ActOnPropertyImplDecl(SourceLocation AtLoc, } if (ObjCPropertyImplDecl *PPIDecl = - CatImplClass->FindPropertyImplDecl(Context, PropertyId)) { + CatImplClass->FindPropertyImplDecl(PropertyId)) { Diag(PropertyLoc, diag::error_property_implemented) << PropertyId; Diag(PPIDecl->getLocation(), diag::note_previous_declaration); return DeclPtrTy(); } - CatImplClass->addPropertyImplementation(Context, PIDecl); + CatImplClass->addPropertyImplementation(PIDecl); } return DeclPtrTy::make(PIDecl); @@ -2154,7 +2147,7 @@ void Sema::ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, if (getLangOptions().CPlusPlus) PushOnScopeChains(cast<FieldDecl>(FD), S); else if (RecordDecl *Record = dyn_cast<RecordDecl>(TagD.getAs<Decl>())) - Record->addDecl(Context, FD); + Record->addDecl(FD); } } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 383edeca07a0..a5e508396422 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -39,7 +39,7 @@ using namespace clang; /// referenced), false otherwise. bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { // See if the decl is deprecated. - if (D->getAttr<DeprecatedAttr>(Context)) { + if (D->getAttr<DeprecatedAttr>()) { // Implementing deprecated stuff requires referencing deprecated // stuff. Don't warn if we are implementing a deprecated // construct. @@ -48,7 +48,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { if (NamedDecl *ND = getCurFunctionOrMethodDecl()) { // If this reference happens *in* a deprecated function or method, don't // warn. - isSilenced = ND->getAttr<DeprecatedAttr>(Context); + isSilenced = ND->getAttr<DeprecatedAttr>(); // If this is an Objective-C method implementation, check to see if the // method was deprecated on the declaration, not the definition. @@ -58,10 +58,9 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(MD->getParent())) { - MD = Impl->getClassInterface()->getMethod(Context, - MD->getSelector(), + MD = Impl->getClassInterface()->getMethod(MD->getSelector(), MD->isInstanceMethod()); - isSilenced |= MD && MD->getAttr<DeprecatedAttr>(Context); + isSilenced |= MD && MD->getAttr<DeprecatedAttr>(); } } } @@ -80,7 +79,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { } // See if the decl is unavailable - if (D->getAttr<UnavailableAttr>(Context)) { + if (D->getAttr<UnavailableAttr>()) { Diag(Loc, diag::warn_unavailable) << D->getDeclName(); Diag(D->getLocation(), diag::note_unavailable_here) << 0; } @@ -95,7 +94,7 @@ bool Sema::DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc) { void Sema::DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, Expr **Args, unsigned NumArgs) { - const SentinelAttr *attr = D->getAttr<SentinelAttr>(Context); + const SentinelAttr *attr = D->getAttr<SentinelAttr>(); if (!attr) return; int sentinelPos = attr->getSentinel(); @@ -673,8 +672,8 @@ static Decl *getObjectForAnonymousRecordDecl(ASTContext &Context, // operation rather than a slow walk through DeclContext's vector (which // itself will be eliminated). DeclGroups might make this even better. DeclContext *Ctx = Record->getDeclContext(); - for (DeclContext::decl_iterator D = Ctx->decls_begin(Context), - DEnd = Ctx->decls_end(Context); + for (DeclContext::decl_iterator D = Ctx->decls_begin(), + DEnd = Ctx->decls_end(); D != DEnd; ++D) { if (*D == Record) { // The object for the anonymous struct/union directly @@ -877,8 +876,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, if (D == 0 || D->isDefinedOutsideFunctionOrMethod()) { ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(Context, II, - ClassDeclared)) { + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { // Check if referencing a field with __attribute__((deprecated)). if (DiagnoseUseOfDecl(IV, Loc)) return ExprError(); @@ -915,8 +913,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // We should warn if a local variable hides an ivar. ObjCInterfaceDecl *IFace = getCurMethodDecl()->getClassInterface(); ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(Context, II, - ClassDeclared)) { + if (ObjCIvarDecl *IV = IFace->lookupInstanceVariable(II, ClassDeclared)) { if (IV->getAccessControl() != ObjCIvarDecl::Private || IFace == ClassDeclared) Diag(Loc, diag::warn_ivar_use_hidden) << IV->getDeclName(); @@ -973,7 +970,64 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, return ExprError(Diag(Loc, diag::err_undeclared_var_use) << Name); } } + + if (VarDecl *Var = dyn_cast<VarDecl>(D)) { + // Warn about constructs like: + // if (void *X = foo()) { ... } else { X }. + // In the else block, the pointer is always false. + + // FIXME: In a template instantiation, we don't have scope + // information to check this property. + if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) { + Scope *CheckS = S; + while (CheckS) { + if (CheckS->isWithinElse() && + CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { + if (Var->getType()->isBooleanType()) + ExprError(Diag(Loc, diag::warn_value_always_false) + << Var->getDeclName()); + else + ExprError(Diag(Loc, diag::warn_value_always_zero) + << Var->getDeclName()); + break; + } + + // Move up one more control parent to check again. + CheckS = CheckS->getControlParent(); + if (CheckS) + CheckS = CheckS->getParent(); + } + } + } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D)) { + if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) { + // C99 DR 316 says that, if a function type comes from a + // function definition (without a prototype), that type is only + // used for checking compatibility. Therefore, when referencing + // the function, we pretend that we don't have the full function + // type. + if (DiagnoseUseOfDecl(Func, Loc)) + return ExprError(); + + QualType T = Func->getType(); + QualType NoProtoType = T; + if (const FunctionProtoType *Proto = T->getAsFunctionProtoType()) + NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); + return BuildDeclRefExpr(Func, NoProtoType, Loc, false, false, SS); + } + } + + return BuildDeclarationNameExpr(Loc, D, HasTrailingLParen, SS, isAddressOfOperand); +} +/// \brief Complete semantic analysis for a reference to the given declaration. +Sema::OwningExprResult +Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D, + bool HasTrailingLParen, + const CXXScopeSpec *SS, + bool isAddressOfOperand) { + assert(D && "Cannot refer to a NULL declaration"); + DeclarationName Name = D->getDeclName(); + // If this is an expression of the form &Class::member, don't build an // implicit member ref, because we want a pointer to the member in general, // not any specific instance's member. @@ -1097,51 +1151,11 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, // this check when we're going to perform argument-dependent lookup // on this function name, because this might not be the function // that overload resolution actually selects. + bool ADL = getLangOptions().CPlusPlus && (!SS || !SS->isSet()) && + HasTrailingLParen; if (!(ADL && isa<FunctionDecl>(VD)) && DiagnoseUseOfDecl(VD, Loc)) return ExprError(); - if (VarDecl *Var = dyn_cast<VarDecl>(VD)) { - // Warn about constructs like: - // if (void *X = foo()) { ... } else { X }. - // In the else block, the pointer is always false. - - // FIXME: In a template instantiation, we don't have scope - // information to check this property. - if (Var->isDeclaredInCondition() && Var->getType()->isScalarType()) { - Scope *CheckS = S; - while (CheckS) { - if (CheckS->isWithinElse() && - CheckS->getControlParent()->isDeclScope(DeclPtrTy::make(Var))) { - if (Var->getType()->isBooleanType()) - ExprError(Diag(Loc, diag::warn_value_always_false) - << Var->getDeclName()); - else - ExprError(Diag(Loc, diag::warn_value_always_zero) - << Var->getDeclName()); - break; - } - - // Move up one more control parent to check again. - CheckS = CheckS->getControlParent(); - if (CheckS) - CheckS = CheckS->getParent(); - } - } - } else if (FunctionDecl *Func = dyn_cast<FunctionDecl>(VD)) { - if (!getLangOptions().CPlusPlus && !Func->hasPrototype()) { - // C99 DR 316 says that, if a function type comes from a - // function definition (without a prototype), that type is only - // used for checking compatibility. Therefore, when referencing - // the function, we pretend that we don't have the full function - // type. - QualType T = Func->getType(); - QualType NoProtoType = T; - if (const FunctionProtoType *Proto = T->getAsFunctionProtoType()) - NoProtoType = Context.getFunctionNoProtoType(Proto->getResultType()); - return BuildDeclRefExpr(VD, NoProtoType, Loc, false, false, SS); - } - } - // Only create DeclRefExpr's for valid Decl's. if (VD->isInvalidDecl()) return ExprError(); @@ -1158,7 +1172,7 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc, MarkDeclarationReferenced(Loc, VD); QualType ExprTy = VD->getType().getNonReferenceType(); // The BlocksAttr indicates the variable is bound by-reference. - if (VD->getAttr<BlocksAttr>(Context)) + if (VD->getAttr<BlocksAttr>()) return Owned(new (Context) BlockDeclRefExpr(VD, ExprTy, Loc, true)); // This is to record that a 'const' was actually synthesize and added. bool constAdded = !ExprTy.isConstQualified(); @@ -1310,8 +1324,8 @@ Action::OwningExprResult Sema::ActOnNumericConstant(const Token &Tok) { // isExact will be set by GetFloatValue(). bool isExact = false; - Res = new (Context) FloatingLiteral(Literal.GetFloatValue(Format, &isExact), - &isExact, Ty, Tok.getLocation()); + llvm::APFloat Val = Literal.GetFloatValue(Format, &isExact); + Res = new (Context) FloatingLiteral(Val, isExact, Ty, Tok.getLocation()); } else if (!Literal.isIntegerLiteral()) { return ExprError(); @@ -1989,9 +2003,9 @@ static Decl *FindGetterNameDeclFromProtocolList(const ObjCProtocolDecl*PDecl, const Selector &Sel, ASTContext &Context) { - if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(Context, &Member)) + if (ObjCPropertyDecl *PD = PDecl->FindPropertyDeclaration(&Member)) return PD; - if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Context, Sel)) + if (ObjCMethodDecl *OMD = PDecl->getInstanceMethod(Sel)) return OMD; for (ObjCProtocolDecl::protocol_iterator I = PDecl->protocol_begin(), @@ -2011,12 +2025,12 @@ static Decl *FindGetterNameDecl(const ObjCObjectPointerType *QIdTy, Decl *GDecl = 0; for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { - if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Context, &Member)) { + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) { GDecl = PD; break; } // Also must look for a getter name which uses property syntax. - if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Context, Sel)) { + if (ObjCMethodDecl *OMD = (*I)->getInstanceMethod(Sel)) { GDecl = OMD; break; } @@ -2042,7 +2056,7 @@ ObjCMethodDecl *Sema::FindMethodInNestedImplementations( ObjCMethodDecl *Method = 0; if (ObjCImplementationDecl *ImpDecl = LookupObjCImplementation(IFace->getIdentifier())) - Method = ImpDecl->getInstanceMethod(Context, Sel); + Method = ImpDecl->getInstanceMethod(Sel); if (!Method && IFace->getSuperClass()) return FindMethodInNestedImplementations(IFace->getSuperClass(), Sel); @@ -2201,8 +2215,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // (*Obj).ivar. if (const ObjCInterfaceType *IFTy = BaseType->getAsObjCInterfaceType()) { ObjCInterfaceDecl *ClassDeclared; - if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(Context, - &Member, + if (ObjCIvarDecl *IV = IFTy->getDecl()->lookupInstanceVariable(&Member, ClassDeclared)) { // If the decl being referenced had an error, return an error for this // sub-expr without emitting another error, in order to avoid cascading @@ -2262,14 +2275,13 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, ObjCInterfaceDecl *IFace = IFTy->getDecl(); // Search for a declared property first. - if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(Context, - &Member)) { + if (ObjCPropertyDecl *PD = IFace->FindPropertyDeclaration(&Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); QualType ResTy = PD->getType(); Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); - ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Context, Sel); + ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); if (DiagnosePropertyAccessorMismatch(PD, Getter, MemberLoc)) ResTy = Getter->getResultType(); return Owned(new (Context) ObjCPropertyRefExpr(PD, ResTy, @@ -2279,8 +2291,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // Check protocols on qualified interfaces. for (ObjCInterfaceType::qual_iterator I = IFTy->qual_begin(), E = IFTy->qual_end(); I != E; ++I) - if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(Context, - &Member)) { + if (ObjCPropertyDecl *PD = (*I)->FindPropertyDeclaration(&Member)) { // Check whether we can reference this property. if (DiagnoseUseOfDecl(PD, MemberLoc)) return ExprError(); @@ -2296,7 +2307,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, // shared with the code in ActOnInstanceMessage. Selector Sel = PP.getSelectorTable().getNullarySelector(&Member); - ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Context, Sel); + ObjCMethodDecl *Getter = IFace->lookupInstanceMethod(Sel); // If this reference is in an @implementation, check for 'private' methods. if (!Getter) @@ -2306,7 +2317,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (!Getter) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Getter; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Getter = ObjCCategoryImpls[i]->getInstanceMethod(Context, Sel); + Getter = ObjCCategoryImpls[i]->getInstanceMethod(Sel); } } if (Getter) { @@ -2319,7 +2330,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, Selector SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), &Member); - ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(Context, SetterSel); + ObjCMethodDecl *Setter = IFace->lookupInstanceMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. @@ -2329,7 +2340,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (!Setter) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Setter = ObjCCategoryImpls[i]->getInstanceMethod(Context, SetterSel); + Setter = ObjCCategoryImpls[i]->getInstanceMethod(SetterSel); } } @@ -2390,7 +2401,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, ObjCInterfaceDecl *IFace = MD->getClassInterface(); ObjCMethodDecl *Getter; // FIXME: need to also look locally in the implementation. - if ((Getter = IFace->lookupClassMethod(Context, Sel))) { + if ((Getter = IFace->lookupClassMethod(Sel))) { // Check the use of this method. if (DiagnoseUseOfDecl(Getter, MemberLoc)) return ExprError(); @@ -2400,7 +2411,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, Selector SetterSel = SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), &Member); - ObjCMethodDecl *Setter = IFace->lookupClassMethod(Context, SetterSel); + ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. @@ -2410,7 +2421,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc, if (!Setter) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Setter = ObjCCategoryImpls[i]->getClassMethod(Context, SetterSel); + Setter = ObjCCategoryImpls[i]->getClassMethod(SetterSel); } } @@ -2624,9 +2635,13 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, } // If we're directly calling a function, get the appropriate declaration. - DeclRefExpr *DRExpr = NULL; + // Also, in C++, keep track of whether we should perform argument-dependent + // lookup and whether there were any explicitly-specified template arguments. Expr *FnExpr = Fn; bool ADL = true; + bool HasExplicitTemplateArgs = 0; + const TemplateArgument *ExplicitTemplateArgs = 0; + unsigned NumExplicitTemplateArgs = 0; while (true) { if (ImplicitCastExpr *IcExpr = dyn_cast<ImplicitCastExpr>(FnExpr)) FnExpr = IcExpr->getSubExpr(); @@ -2639,14 +2654,41 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, cast<UnaryOperator>(FnExpr)->getOpcode() == UnaryOperator::AddrOf) { FnExpr = cast<UnaryOperator>(FnExpr)->getSubExpr(); - } else if ((DRExpr = dyn_cast<DeclRefExpr>(FnExpr))) { + } else if (DeclRefExpr *DRExpr = dyn_cast<DeclRefExpr>(FnExpr)) { // Qualified names disable ADL (C++0x [basic.lookup.argdep]p1). ADL &= !isa<QualifiedDeclRefExpr>(DRExpr); + NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl()); break; } else if (UnresolvedFunctionNameExpr *DepName = dyn_cast<UnresolvedFunctionNameExpr>(FnExpr)) { UnqualifiedName = DepName->getName(); break; + } else if (TemplateIdRefExpr *TemplateIdRef + = dyn_cast<TemplateIdRefExpr>(FnExpr)) { + NDecl = TemplateIdRef->getTemplateName().getAsTemplateDecl(); + HasExplicitTemplateArgs = true; + ExplicitTemplateArgs = TemplateIdRef->getTemplateArgs(); + NumExplicitTemplateArgs = TemplateIdRef->getNumTemplateArgs(); + + // C++ [temp.arg.explicit]p6: + // [Note: For simple function names, argument dependent lookup (3.4.2) + // applies even when the function name is not visible within the + // scope of the call. This is because the call still has the syntactic + // form of a function call (3.4.1). But when a function template with + // explicit template arguments is used, the call does not have the + // correct syntactic form unless there is a function template with + // that name visible at the point of the call. If no such name is + // visible, the call is not syntactically well-formed and + // argument-dependent lookup does not apply. If some such name is + // visible, argument dependent lookup applies and additional function + // templates may be found in other namespaces. + // + // The summary of this paragraph is that, if we get to this point and the + // template-id was not a qualified name, then argument-dependent lookup + // is still possible. + if (TemplateIdRef->getQualifier()) + ADL = false; + break; } else { // Any kind of name that does not refer to a declaration (or // set of declarations) disables ADL (C++0x [basic.lookup.argdep]p3). @@ -2657,14 +2699,13 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, OverloadedFunctionDecl *Ovl = 0; FunctionTemplateDecl *FunctionTemplate = 0; - if (DRExpr) { - FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()); - if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(DRExpr->getDecl()))) + if (NDecl) { + FDecl = dyn_cast<FunctionDecl>(NDecl); + if ((FunctionTemplate = dyn_cast<FunctionTemplateDecl>(NDecl))) FDecl = FunctionTemplate->getTemplatedDecl(); else - FDecl = dyn_cast<FunctionDecl>(DRExpr->getDecl()); - Ovl = dyn_cast<OverloadedFunctionDecl>(DRExpr->getDecl()); - NDecl = dyn_cast<NamedDecl>(DRExpr->getDecl()); + FDecl = dyn_cast<FunctionDecl>(NDecl); + Ovl = dyn_cast<OverloadedFunctionDecl>(NDecl); } if (Ovl || FunctionTemplate || @@ -2678,16 +2719,19 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, ADL = false; if (Ovl || FunctionTemplate || ADL) { - FDecl = ResolveOverloadedCallFn(Fn, DRExpr? DRExpr->getDecl() : 0, - UnqualifiedName, LParenLoc, Args, - NumArgs, CommaLocs, RParenLoc, ADL); + FDecl = ResolveOverloadedCallFn(Fn, NDecl, UnqualifiedName, + HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + LParenLoc, Args, NumArgs, CommaLocs, + RParenLoc, ADL); if (!FDecl) return ExprError(); // Update Fn to refer to the actual function selected. Expr *NewFn = 0; if (QualifiedDeclRefExpr *QDRExpr - = dyn_cast_or_null<QualifiedDeclRefExpr>(DRExpr)) + = dyn_cast<QualifiedDeclRefExpr>(FnExpr)) NewFn = new (Context) QualifiedDeclRefExpr(FDecl, FDecl->getType(), QDRExpr->getLocation(), false, false, @@ -2750,7 +2794,7 @@ Sema::ActOnCallExpr(Scope *S, ExprArg fn, SourceLocation LParenLoc, // Check if we have too few/too many template arguments, based // on our knowledge of the function definition. const FunctionDecl *Def = 0; - if (FDecl->getBody(Context, Def) && NumArgs != Def->param_size()) { + if (FDecl->getBody(Def) && NumArgs != Def->param_size()) { const FunctionProtoType *Proto = Def->getType()->getAsFunctionProtoType(); if (!Proto || !(Proto->isVariadic() && NumArgs >= Def->param_size())) { @@ -2860,7 +2904,7 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr) { // GCC cast to union extension RecordDecl *RD = castType->getAsRecordType()->getDecl(); RecordDecl::field_iterator Field, FieldEnd; - for (Field = RD->field_begin(Context), FieldEnd = RD->field_end(Context); + for (Field = RD->field_begin(), FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { if (Context.getCanonicalType(Field->getType()).getUnqualifiedType() == Context.getCanonicalType(castExpr->getType()).getUnqualifiedType()) { @@ -2931,19 +2975,8 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) { bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) { assert(DestTy->isExtVectorType() && "Not an extended vector type!"); - // If SrcTy is also an ExtVectorType, the types must be identical unless - // lax vector conversions is enabled. - if (SrcTy->isExtVectorType()) { - if (getLangOptions().LaxVectorConversions && - Context.getTypeSize(DestTy) == Context.getTypeSize(SrcTy)) - return false; - if (DestTy != SrcTy) - return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) - << DestTy << SrcTy << R; - return false; - } - - // If SrcTy is a VectorType, then only the total size must match. + // If SrcTy is a VectorType, the total size must match to explicitly cast to + // an ExtVectorType. if (SrcTy->isVectorType()) { if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy)) return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors) @@ -2951,9 +2984,13 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) { return false; } - // All scalar -> ext vector "c-style" casts are legal; the appropriate + // All non-pointer scalars can be cast to ExtVector type. The appropriate // conversion will take place first from scalar to elt type, and then // splat from elt type to vector. + if (SrcTy->isPointerType()) + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_vector_and_scalar) + << DestTy << SrcTy << R; return false; } @@ -3042,24 +3079,133 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer. return RHSTy; } + // Handle block pointer types. + if (LHSTy->isBlockPointerType() || RHSTy->isBlockPointerType()) { + if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) { + if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) { + QualType destType = Context.getPointerType(Context.VoidTy); + ImpCastExprToType(LHS, destType); + ImpCastExprToType(RHS, destType); + return destType; + } + Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + return QualType(); + } + // We have 2 block pointer types. + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical block pointer types are always compatible. + return LHSTy; + } + // The block pointer types aren't identical, continue checking. + QualType lhptee = LHSTy->getAsBlockPointerType()->getPointeeType(); + QualType rhptee = RHSTy->getAsBlockPointerType()->getPointeeType(); - const PointerType *LHSPT = LHSTy->getAsPointerType(); - const PointerType *RHSPT = RHSTy->getAsPointerType(); - const BlockPointerType *LHSBPT = LHSTy->getAsBlockPointerType(); - const BlockPointerType *RHSBPT = RHSTy->getAsBlockPointerType(); + if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), + rhptee.getUnqualifiedType())) { + Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) + << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); + // In this situation, we assume void* type. No especially good + // reason, but this is what gcc does, and we do have to pick + // to get a consistent AST. + QualType incompatTy = Context.getPointerType(Context.VoidTy); + ImpCastExprToType(LHS, incompatTy); + ImpCastExprToType(RHS, incompatTy); + return incompatTy; + } + // The block pointer types are compatible. + ImpCastExprToType(LHS, LHSTy); + ImpCastExprToType(RHS, LHSTy); + return LHSTy; + } + // Need to handle "id<xx>" explicitly. Unlike "id", whose canonical type + // evaluates to "struct objc_object *" (and is handled above when comparing + // id with statically typed objects). + if (LHSTy->isObjCQualifiedIdType() || RHSTy->isObjCQualifiedIdType()) { + // GCC allows qualified id and any Objective-C type to devolve to + // id. Currently localizing to here until clear this should be + // part of ObjCQualifiedIdTypesAreCompatible. + if (ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true) || + (LHSTy->isObjCQualifiedIdType() && + Context.isObjCObjectPointerType(RHSTy)) || + (RHSTy->isObjCQualifiedIdType() && + Context.isObjCObjectPointerType(LHSTy))) { + // FIXME: This is not the correct composite type. This only happens to + // work because id can more or less be used anywhere, however this may + // change the type of method sends. - // Handle the case where both operands are pointers before we handle null - // pointer constants in case both operands are null pointer constants. - if ((LHSPT || LHSBPT) && (RHSPT || RHSBPT)) { // C99 6.5.15p3,6 + // FIXME: gcc adds some type-checking of the arguments and emits + // (confusing) incompatible comparison warnings in some + // cases. Investigate. + QualType compositeType = Context.getObjCIdType(); + ImpCastExprToType(LHS, compositeType); + ImpCastExprToType(RHS, compositeType); + return compositeType; + } + } + // Check constraints for Objective-C object pointers types. + if (Context.isObjCObjectPointerType(LHSTy) && + Context.isObjCObjectPointerType(RHSTy)) { + + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + // Two identical object pointer types are always compatible. + return LHSTy; + } + // No need to check for block pointer types or qualified id types (they + // were handled above). + assert((LHSTy->isPointerType() && RHSTy->isPointerType()) && + "Sema::CheckConditionalOperands(): Unexpected type"); + QualType lhptee = LHSTy->getAsPointerType()->getPointeeType(); + QualType rhptee = RHSTy->getAsPointerType()->getPointeeType(); + + QualType compositeType = LHSTy; + + // If both operands are interfaces and either operand can be + // assigned to the other, use that type as the composite + // type. This allows + // xxx ? (A*) a : (B*) b + // where B is a subclass of A. + // + // Additionally, as for assignment, if either type is 'id' + // allow silent coercion. Finally, if the types are + // incompatible then make sure to use 'id' as the composite + // type so the result is acceptable for sending messages to. + + // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. + // It could return the composite type. + const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType(); + const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType(); + if (LHSIface && RHSIface && + Context.canAssignObjCInterfaces(LHSIface, RHSIface)) { + compositeType = LHSTy; + } else if (LHSIface && RHSIface && + Context.canAssignObjCInterfaces(RHSIface, LHSIface)) { + compositeType = RHSTy; + } else if (Context.isObjCIdStructType(lhptee) || + Context.isObjCIdStructType(rhptee)) { + compositeType = Context.getObjCIdType(); + } else { + Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) + << LHSTy << RHSTy + << LHS->getSourceRange() << RHS->getSourceRange(); + QualType incompatTy = Context.getObjCIdType(); + ImpCastExprToType(LHS, incompatTy); + ImpCastExprToType(RHS, incompatTy); + return incompatTy; + } + // The object pointer types are compatible. + ImpCastExprToType(LHS, compositeType); + ImpCastExprToType(RHS, compositeType); + return compositeType; + } + // Check constraints for C object pointers types (C99 6.5.15p3,6). + if (LHSTy->isPointerType() && RHSTy->isPointerType()) { // get the "pointed to" types - QualType lhptee = (LHSPT ? LHSPT->getPointeeType() - : LHSBPT->getPointeeType()); - QualType rhptee = (RHSPT ? RHSPT->getPointeeType() - : RHSBPT->getPointeeType()); + QualType lhptee = LHSTy->getAsPointerType()->getPointeeType(); + QualType rhptee = RHSTy->getAsPointerType()->getPointeeType(); // ignore qualifiers on void (C99 6.5.15p3, clause 6) - if (lhptee->isVoidType() - && (RHSBPT || rhptee->isIncompleteOrObjectType())) { + if (lhptee->isVoidType() && rhptee->isIncompleteOrObjectType()) { // Figure out necessary qualifiers (C99 6.5.15p6) QualType destPointee=lhptee.getQualifiedType(rhptee.getCVRQualifiers()); QualType destType = Context.getPointerType(destPointee); @@ -3067,8 +3213,7 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, ImpCastExprToType(RHS, destType); // promote to void* return destType; } - if (rhptee->isVoidType() - && (LHSBPT || lhptee->isIncompleteOrObjectType())) { + if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) { QualType destPointee=rhptee.getQualifiedType(lhptee.getCVRQualifiers()); QualType destType = Context.getPointerType(destPointee); ImpCastExprToType(LHS, destType); // add qualifiers if necessary @@ -3076,62 +3221,12 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return destType; } - bool sameKind = (LHSPT && RHSPT) || (LHSBPT && RHSBPT); - if (sameKind - && Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { + if (Context.getCanonicalType(LHSTy) == Context.getCanonicalType(RHSTy)) { // Two identical pointer types are always compatible. return LHSTy; } - - QualType compositeType = LHSTy; - - // If either type is an Objective-C object type then check - // compatibility according to Objective-C. - if (Context.isObjCObjectPointerType(LHSTy) || - Context.isObjCObjectPointerType(RHSTy)) { - // If both operands are interfaces and either operand can be - // assigned to the other, use that type as the composite - // type. This allows - // xxx ? (A*) a : (B*) b - // where B is a subclass of A. - // - // Additionally, as for assignment, if either type is 'id' - // allow silent coercion. Finally, if the types are - // incompatible then make sure to use 'id' as the composite - // type so the result is acceptable for sending messages to. - - // FIXME: Consider unifying with 'areComparableObjCPointerTypes'. - // It could return the composite type. - const ObjCInterfaceType* LHSIface = lhptee->getAsObjCInterfaceType(); - const ObjCInterfaceType* RHSIface = rhptee->getAsObjCInterfaceType(); - if (LHSIface && RHSIface && - Context.canAssignObjCInterfaces(LHSIface, RHSIface)) { - compositeType = LHSTy; - } else if (LHSIface && RHSIface && - Context.canAssignObjCInterfaces(RHSIface, LHSIface)) { - compositeType = RHSTy; - } else if (Context.isObjCIdStructType(lhptee) || - Context.isObjCIdStructType(rhptee)) { - compositeType = Context.getObjCIdType(); - } else if (LHSBPT || RHSBPT) { - if (!sameKind - || !Context.typesAreCompatible(lhptee.getUnqualifiedType(), - rhptee.getUnqualifiedType())) - Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); - return QualType(); - } else { - Diag(QuestionLoc, diag::ext_typecheck_cond_incompatible_operands) - << LHSTy << RHSTy - << LHS->getSourceRange() << RHS->getSourceRange(); - QualType incompatTy = Context.getObjCIdType(); - ImpCastExprToType(LHS, incompatTy); - ImpCastExprToType(RHS, incompatTy); - return incompatTy; - } - } else if (!sameKind - || !Context.typesAreCompatible(lhptee.getUnqualifiedType(), - rhptee.getUnqualifiedType())) { + if (!Context.typesAreCompatible(lhptee.getUnqualifiedType(), + rhptee.getUnqualifiedType())) { Diag(QuestionLoc, diag::warn_typecheck_cond_incompatible_pointers) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); // In this situation, we assume void* type. No especially good @@ -3149,11 +3244,11 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, // type. // FIXME: Need to calculate the composite type. // FIXME: Need to add qualifiers - ImpCastExprToType(LHS, compositeType); - ImpCastExprToType(RHS, compositeType); - return compositeType; + ImpCastExprToType(LHS, LHSTy); + ImpCastExprToType(RHS, LHSTy); + return LHSTy; } - + // GCC compatibility: soften pointer/integer mismatch. if (RHSTy->isPointerType() && LHSTy->isIntegerType()) { Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch) @@ -3168,32 +3263,6 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS, return LHSTy; } - // Need to handle "id<xx>" explicitly. Unlike "id", whose canonical type - // evaluates to "struct objc_object *" (and is handled above when comparing - // id with statically typed objects). - if (LHSTy->isObjCQualifiedIdType() || RHSTy->isObjCQualifiedIdType()) { - // GCC allows qualified id and any Objective-C type to devolve to - // id. Currently localizing to here until clear this should be - // part of ObjCQualifiedIdTypesAreCompatible. - if (ObjCQualifiedIdTypesAreCompatible(LHSTy, RHSTy, true) || - (LHSTy->isObjCQualifiedIdType() && - Context.isObjCObjectPointerType(RHSTy)) || - (RHSTy->isObjCQualifiedIdType() && - Context.isObjCObjectPointerType(LHSTy))) { - // FIXME: This is not the correct composite type. This only happens to - // work because id can more or less be used anywhere, however this may - // change the type of method sends. - - // FIXME: gcc adds some type-checking of the arguments and emits - // (confusing) incompatible comparison warnings in some - // cases. Investigate. - QualType compositeType = Context.getObjCIdType(); - ImpCastExprToType(LHS, compositeType); - ImpCastExprToType(RHS, compositeType); - return compositeType; - } - } - // Otherwise, the operands are not compatible. Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); @@ -3385,12 +3454,16 @@ Sema::CheckAssignmentConstraints(QualType lhsType, QualType rhsType) { return IncompatibleObjCQualifiedId; } + // Allow scalar to ExtVector assignments, and assignments of an ExtVector type + // to the same ExtVector type. + if (lhsType->isExtVectorType()) { + if (rhsType->isExtVectorType()) + return lhsType == rhsType ? Compatible : Incompatible; + if (!rhsType->isVectorType() && rhsType->isArithmeticType()) + return Compatible; + } + if (lhsType->isVectorType() || rhsType->isVectorType()) { - // For ExtVector, allow vector splats; float -> <n x float> - if (const ExtVectorType *LV = lhsType->getAsExtVectorType()) - if (LV->getElementType() == rhsType) - return Compatible; - // If we are allowing lax vector conversions, and LHS and RHS are both // vectors, the total size only needs to be the same. This is a bitcast; // no bits are changed but the result type is different. @@ -3492,15 +3565,15 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) { // If the ArgType is a Union type, we want to handle a potential // transparent_union GCC extension. const RecordType *UT = ArgType->getAsUnionType(); - if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>(Context)) + if (!UT || !UT->getDecl()->hasAttr<TransparentUnionAttr>()) return Incompatible; // The field to initialize within the transparent union. RecordDecl *UD = UT->getDecl(); FieldDecl *InitField = 0; // It's compatible if the expression matches any of the fields. - for (RecordDecl::field_iterator it = UD->field_begin(Context), - itend = UD->field_end(Context); + for (RecordDecl::field_iterator it = UD->field_begin(), + itend = UD->field_end(); it != itend; ++it) { if (it->getType()->isPointerType()) { // If the transparent union contains a pointer type, we allow: @@ -3617,33 +3690,36 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex, } } - // If the lhs is an extended vector and the rhs is a scalar of the same type - // or a literal, promote the rhs to the vector type. - if (const ExtVectorType *V = lhsType->getAsExtVectorType()) { - QualType eltType = V->getElementType(); - - if ((eltType->getAsBuiltinType() == rhsType->getAsBuiltinType()) || - (eltType->isIntegerType() && isa<IntegerLiteral>(rex)) || - (eltType->isFloatingType() && isa<FloatingLiteral>(rex))) { - ImpCastExprToType(rex, lhsType); - return lhsType; - } + // Canonicalize the ExtVector to the LHS, remember if we swapped so we can + // swap back (so that we don't reverse the inputs to a subtract, for instance. + bool swapped = false; + if (rhsType->isExtVectorType()) { + swapped = true; + std::swap(rex, lex); + std::swap(rhsType, lhsType); } - - // If the rhs is an extended vector and the lhs is a scalar of the same type, - // promote the lhs to the vector type. - if (const ExtVectorType *V = rhsType->getAsExtVectorType()) { - QualType eltType = V->getElementType(); - - if ((eltType->getAsBuiltinType() == lhsType->getAsBuiltinType()) || - (eltType->isIntegerType() && isa<IntegerLiteral>(lex)) || - (eltType->isFloatingType() && isa<FloatingLiteral>(lex))) { - ImpCastExprToType(lex, rhsType); - return rhsType; + + // Handle the case of an ext vector and scalar. + if (const ExtVectorType *LV = lhsType->getAsExtVectorType()) { + QualType EltTy = LV->getElementType(); + if (EltTy->isIntegralType() && rhsType->isIntegralType()) { + if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) { + ImpCastExprToType(rex, lhsType); + if (swapped) std::swap(rex, lex); + return lhsType; + } + } + if (EltTy->isRealFloatingType() && rhsType->isScalarType() && + rhsType->isRealFloatingType()) { + if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) { + ImpCastExprToType(rex, lhsType); + if (swapped) std::swap(rex, lex); + return lhsType; + } } } - - // You cannot convert between vector values of different size. + + // Vectors of different size or scalar and non-ext-vector are errors. Diag(Loc, diag::err_typecheck_vector_not_convertable) << lex->getType() << rex->getType() << lex->getSourceRange() << rex->getSourceRange(); @@ -4034,6 +4110,17 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, QualType RCanPointeeTy = Context.getCanonicalType(rType->getAsPointerType()->getPointeeType()); + if (rType->isFunctionPointerType() || lType->isFunctionPointerType()) { + if (isRelational) { + Diag(Loc, diag::ext_typecheck_ordered_comparison_of_function_pointers) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + } + } + if (((!LHSIsNull || isRelational) && LCanPointeeTy->isVoidType()) != + ((!RHSIsNull || isRelational) && RCanPointeeTy->isVoidType())) { + Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + } // Simple check: if the pointee types are identical, we're done. if (LCanPointeeTy == RCanPointeeTy) return ResultTy; @@ -4146,7 +4233,10 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } if ((lType->isPointerType() || lType->isObjCQualifiedIdType()) && rType->isIntegerType()) { - if (!RHSIsNull) + if (isRelational) + Diag(Loc, diag::ext_typecheck_ordered_comparison_of_pointer_integer) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + else if (!RHSIsNull) Diag(Loc, diag::ext_typecheck_comparison_of_pointer_integer) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(rex, lType); // promote the integer to pointer @@ -4154,7 +4244,10 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc, } if (lType->isIntegerType() && (rType->isPointerType() || rType->isObjCQualifiedIdType())) { - if (!LHSIsNull) + if (isRelational) + Diag(Loc, diag::ext_typecheck_ordered_comparison_of_pointer_integer) + << lType << rType << lex->getSourceRange() << rex->getSourceRange(); + else if (!LHSIsNull) Diag(Loc, diag::ext_typecheck_comparison_of_pointer_integer) << lType << rType << lex->getSourceRange() << rex->getSourceRange(); ImpCastExprToType(lex, rType); // promote the integer to pointer @@ -5226,7 +5319,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { CurBlock->hasPrototype = true; CurBlock->isVariadic = false; // Check for a valid sentinel attribute on this block. - if (CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) { + if (CurBlock->TheDecl->getAttr<SentinelAttr>()) { Diag(ParamInfo.getAttributes()->getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; // FIXME: remove the attribute. @@ -5275,7 +5368,7 @@ void Sema::ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) { // Check for a valid sentinel attribute on this block. if (!CurBlock->isVariadic && - CurBlock->TheDecl->getAttr<SentinelAttr>(Context)) { + CurBlock->TheDecl->getAttr<SentinelAttr>()) { Diag(ParamInfo.getAttributes()->getLoc(), diag::warn_attribute_sentinel_not_variadic) << 1; // FIXME: remove the attribute. @@ -5607,13 +5700,13 @@ void Sema::MarkDeclarationReferenced(SourceLocation Loc, Decl *D) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // Implicit instantiation of function templates and member functions of // class templates. - if (!Function->getBody(Context)) { + if (!Function->getBody()) { // FIXME: distinguish between implicit instantiations of function // templates and explicit specializations (the latter don't get // instantiated, naturally). if (Function->getInstantiatedFromMemberFunction() || Function->getPrimaryTemplate()) - PendingImplicitInstantiations.push(std::make_pair(Function, Loc)); + PendingImplicitInstantiations.push_back(std::make_pair(Function, Loc)); } diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index bc8fc4eae502..7afa5941dad9 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -552,7 +552,7 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, bool AllowMissing, FunctionDecl *&Operator) { DeclContext::lookup_iterator Alloc, AllocEnd; - llvm::tie(Alloc, AllocEnd) = Ctx->lookup(Context, Name); + llvm::tie(Alloc, AllocEnd) = Ctx->lookup(Name); if (Alloc == AllocEnd) { if (AllowMissing) return false; @@ -657,7 +657,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // Check if this function is already declared. { DeclContext::lookup_iterator Alloc, AllocEnd; - for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Context, Name); + for (llvm::tie(Alloc, AllocEnd) = GlobalCtx->lookup(Name); Alloc != AllocEnd; ++Alloc) { // FIXME: Do we need to check for default arguments here? FunctionDecl *Func = cast<FunctionDecl>(*Alloc); @@ -680,7 +680,7 @@ void Sema::DeclareGlobalAllocationFunction(DeclarationName Name, // FIXME: Also add this declaration to the IdentifierResolver, but // make sure it is at the end of the chain to coincide with the // global scope. - ((DeclContext *)TUScope->getEntity())->addDecl(Context, Alloc); + ((DeclContext *)TUScope->getEntity())->addDecl(Alloc); } /// ActOnCXXDelete - Parsed a C++ 'delete' expression (C++ 5.3.5), as in: @@ -1567,7 +1567,7 @@ Sema::OwningExprResult Sema::MaybeBindToTemporary(Expr *E) { CXXTemporary *Temp = CXXTemporary::Create(Context, RD->getDestructor(Context)); ExprTemporaries.push_back(Temp); - MarcDestructorReferenced(E->getExprLoc(), E->getType()); + MarkDestructorReferenced(E->getExprLoc(), E->getType()); // FIXME: Add the temporary to the temporaries vector. return Owned(CXXBindTemporaryExpr::Create(Context, Temp, E)); } diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index f1869f903719..7bb6b44c39cf 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -243,13 +243,13 @@ ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel, while (ClassDecl && !Method) { if (ObjCImplementationDecl *ImpDecl = LookupObjCImplementation(ClassDecl->getIdentifier())) - Method = ImpDecl->getClassMethod(Context, Sel); + Method = ImpDecl->getClassMethod(Sel); // Look through local category implementations associated with the class. if (!Method) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) - Method = ObjCCategoryImpls[i]->getClassMethod(Context, Sel); + Method = ObjCCategoryImpls[i]->getClassMethod(Sel); } } @@ -257,7 +257,7 @@ ObjCMethodDecl *Sema::LookupPrivateClassMethod(Selector Sel, // But only in the root. This matches gcc's behaviour and what the // runtime expects. if (!Method && !ClassDecl->getSuperClass()) { - Method = ClassDecl->lookupInstanceMethod(Context, Sel); + Method = ClassDecl->lookupInstanceMethod(Sel); // Look through local category implementations associated // with the root class. if (!Method) @@ -276,13 +276,13 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, // If we have implementations in scope, check "private" methods. if (ObjCImplementationDecl *ImpDecl = LookupObjCImplementation(ClassDecl->getIdentifier())) - Method = ImpDecl->getInstanceMethod(Context, Sel); + Method = ImpDecl->getInstanceMethod(Sel); // Look through local category implementations associated with the class. if (!Method) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Method; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == ClassDecl) - Method = ObjCCategoryImpls[i]->getInstanceMethod(Context, Sel); + Method = ObjCCategoryImpls[i]->getInstanceMethod(Sel); } } ClassDecl = ClassDecl->getSuperClass(); @@ -301,7 +301,7 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr( // Search for a declared property first. Selector Sel = PP.getSelectorTable().getNullarySelector(&propertyName); - ObjCMethodDecl *Getter = IFace->lookupClassMethod(Context, Sel); + ObjCMethodDecl *Getter = IFace->lookupClassMethod(Sel); // If this reference is in an @implementation, check for 'private' methods. if (!Getter) @@ -309,7 +309,7 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr( if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) if (ObjCImplementationDecl *ImpDecl = LookupObjCImplementation(ClassDecl->getIdentifier())) - Getter = ImpDecl->getClassMethod(Context, Sel); + Getter = ImpDecl->getClassMethod(Sel); if (Getter) { // FIXME: refactor/share with ActOnMemberReference(). @@ -323,7 +323,7 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr( SelectorTable::constructSetterName(PP.getIdentifierTable(), PP.getSelectorTable(), &propertyName); - ObjCMethodDecl *Setter = IFace->lookupClassMethod(Context, SetterSel); + ObjCMethodDecl *Setter = IFace->lookupClassMethod(SetterSel); if (!Setter) { // If this reference is in an @implementation, also check for 'private' // methods. @@ -331,13 +331,13 @@ Action::OwningExprResult Sema::ActOnClassPropertyRefExpr( if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) if (ObjCImplementationDecl *ImpDecl = LookupObjCImplementation(ClassDecl->getIdentifier())) - Setter = ImpDecl->getClassMethod(Context, SetterSel); + Setter = ImpDecl->getClassMethod(SetterSel); } // Look through local category implementations associated with the class. if (!Setter) { for (unsigned i = 0; i < ObjCCategoryImpls.size() && !Setter; i++) { if (ObjCCategoryImpls[i]->getClassInterface() == IFace) - Setter = ObjCCategoryImpls[i]->getClassMethod(Context, SetterSel); + Setter = ObjCCategoryImpls[i]->getClassMethod(SetterSel); } } @@ -450,7 +450,7 @@ Sema::ExprResult Sema::ActOnClassMessage( << Method->getDeclName(); } if (!Method) - Method = ClassDecl->lookupClassMethod(Context, Sel); + Method = ClassDecl->lookupClassMethod(Sel); // If we have an implementation in scope, check "private" methods. if (!Method) @@ -507,7 +507,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, // If we have an interface in scope, check 'super' methods. if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) if (ObjCInterfaceDecl *SuperDecl = ClassDecl->getSuperClass()) { - Method = SuperDecl->lookupInstanceMethod(Context, Sel); + Method = SuperDecl->lookupInstanceMethod(Sel); if (!Method) // If we have implementations in scope, check "private" methods. @@ -550,7 +550,7 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, if (ObjCMethodDecl *CurMeth = getCurMethodDecl()) { if (ObjCInterfaceDecl *ClassDecl = CurMeth->getClassInterface()) { // First check the public methods in the class interface. - Method = ClassDecl->lookupClassMethod(Context, Sel); + Method = ClassDecl->lookupClassMethod(Sel); if (!Method) Method = LookupPrivateClassMethod(Sel, ClassDecl); @@ -596,10 +596,10 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, for (ObjCObjectPointerType::qual_iterator I = QIdTy->qual_begin(), E = QIdTy->qual_end(); I != E; ++I) { ObjCProtocolDecl *PDecl = *I; - if (PDecl && (Method = PDecl->lookupInstanceMethod(Context, Sel))) + if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) break; // Since we aren't supporting "Class<foo>", look for a class method. - if (PDecl && (Method = PDecl->lookupClassMethod(Context, Sel))) + if (PDecl && (Method = PDecl->lookupClassMethod(Sel))) break; } } else if (const ObjCInterfaceType *OCIType = @@ -610,13 +610,13 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel, // FIXME: consider using LookupInstanceMethodInGlobalPool, since it will be // faster than the following method (which can do *many* linear searches). // The idea is to add class info to InstanceMethodPool. - Method = ClassDecl->lookupInstanceMethod(Context, Sel); + Method = ClassDecl->lookupInstanceMethod(Sel); if (!Method) { // Search protocol qualifiers. for (ObjCQualifiedInterfaceType::qual_iterator QI = OCIType->qual_begin(), E = OCIType->qual_end(); QI != E; ++QI) { - if ((Method = (*QI)->lookupInstanceMethod(Context, Sel))) + if ((Method = (*QI)->lookupInstanceMethod(Sel))) break; } } diff --git a/lib/Sema/SemaInherit.cpp b/lib/Sema/SemaInherit.cpp index 28ca5f64ef59..2f914f14a81f 100644 --- a/lib/Sema/SemaInherit.cpp +++ b/lib/Sema/SemaInherit.cpp @@ -187,7 +187,7 @@ bool Sema::LookupInBases(CXXRecordDecl *Class, = (Context.getCanonicalType(BaseSpec->getType()) == Criteria.Base); break; case MemberLookupCriteria::LK_NamedMember: - Paths.ScratchPath.Decls = BaseRecord->lookup(Context, Criteria.Name); + Paths.ScratchPath.Decls = BaseRecord->lookup(Criteria.Name); while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) { if (isAcceptableLookupResult(*Paths.ScratchPath.Decls.first, Criteria.NameKind, Criteria.IDNS)) { @@ -199,7 +199,7 @@ bool Sema::LookupInBases(CXXRecordDecl *Class, break; case MemberLookupCriteria::LK_OverriddenMember: Paths.ScratchPath.Decls = - BaseRecord->lookup(Context, Criteria.Method->getDeclName()); + BaseRecord->lookup(Criteria.Method->getDeclName()); while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) { if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Paths.ScratchPath.Decls.first)) { diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 6b812e1968de..ecfdfd7ba0b6 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -343,8 +343,8 @@ void InitListChecker::FillInValueInitializations(InitListExpr *ILE) { if (const RecordType *RType = ILE->getType()->getAsRecordType()) { unsigned Init = 0, NumInits = ILE->getNumInits(); for (RecordDecl::field_iterator - Field = RType->getDecl()->field_begin(SemaRef.Context), - FieldEnd = RType->getDecl()->field_end(SemaRef.Context); + Field = RType->getDecl()->field_begin(), + FieldEnd = RType->getDecl()->field_end(); Field != FieldEnd; ++Field) { if (Field->isUnnamedBitfield()) continue; @@ -449,8 +449,8 @@ int InitListChecker::numStructUnionElements(QualType DeclType) { RecordDecl *structDecl = DeclType->getAsRecordType()->getDecl(); int InitializableMembers = 0; for (RecordDecl::field_iterator - Field = structDecl->field_begin(SemaRef.Context), - FieldEnd = structDecl->field_end(SemaRef.Context); + Field = structDecl->field_begin(), + FieldEnd = structDecl->field_end(); Field != FieldEnd; ++Field) { if ((*Field)->getIdentifier() || !(*Field)->isBitField()) ++InitializableMembers; @@ -580,7 +580,7 @@ void InitListChecker::CheckListElementTypes(InitListExpr *IList, } else if (DeclType->isAggregateType()) { if (DeclType->isRecordType()) { RecordDecl *RD = DeclType->getAsRecordType()->getDecl(); - CheckStructUnionTypes(IList, DeclType, RD->field_begin(SemaRef.Context), + CheckStructUnionTypes(IList, DeclType, RD->field_begin(), SubobjectIsDesignatorContext, Index, StructuredList, StructuredIndex, TopLevelObject); @@ -946,7 +946,7 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, if (DeclType->isUnionType() && IList->getNumInits() == 0) { // Value-initialize the first named member of the union. RecordDecl *RD = DeclType->getAsRecordType()->getDecl(); - for (RecordDecl::field_iterator FieldEnd = RD->field_end(SemaRef.Context); + for (RecordDecl::field_iterator FieldEnd = RD->field_end(); Field != FieldEnd; ++Field) { if (Field->getDeclName()) { StructuredList->setInitializedFieldInUnion(*Field); @@ -961,7 +961,7 @@ void InitListChecker::CheckStructUnionTypes(InitListExpr *IList, // because an error should get printed out elsewhere. It might be // worthwhile to skip over the rest of the initializer, though. RecordDecl *RD = DeclType->getAsRecordType()->getDecl(); - RecordDecl::field_iterator FieldEnd = RD->field_end(SemaRef.Context); + RecordDecl::field_iterator FieldEnd = RD->field_end(); bool InitializedSomething = false; while (Index < IList->getNumInits()) { Expr *Init = IList->getInit(Index); @@ -1090,9 +1090,9 @@ static void ExpandAnonymousFieldDesignator(Sema &SemaRef, // Update FieldIter/FieldIndex; RecordDecl *Record = cast<RecordDecl>(Path.back()->getDeclContext()); - FieldIter = Record->field_begin(SemaRef.Context); + FieldIter = Record->field_begin(); FieldIndex = 0; - for (RecordDecl::field_iterator FEnd = Record->field_end(SemaRef.Context); + for (RecordDecl::field_iterator FEnd = Record->field_end(); FieldIter != FEnd; ++FieldIter) { if (FieldIter->isUnnamedBitfield()) continue; @@ -1217,8 +1217,8 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, IdentifierInfo *FieldName = D->getFieldName(); unsigned FieldIndex = 0; RecordDecl::field_iterator - Field = RT->getDecl()->field_begin(SemaRef.Context), - FieldEnd = RT->getDecl()->field_end(SemaRef.Context); + Field = RT->getDecl()->field_begin(), + FieldEnd = RT->getDecl()->field_end(); for (; Field != FieldEnd; ++Field) { if (Field->isUnnamedBitfield()) continue; @@ -1235,8 +1235,7 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, // something that we can't designate (e.g., a member function), // may find nothing, or may find a member of an anonymous // struct/union. - DeclContext::lookup_result Lookup - = RT->getDecl()->lookup(SemaRef.Context, FieldName); + DeclContext::lookup_result Lookup = RT->getDecl()->lookup(FieldName); if (Lookup.first == Lookup.second) { // Name lookup didn't find anything. SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) @@ -1565,8 +1564,8 @@ InitListChecker::getStructuredSubobjectInit(InitListExpr *IList, unsigned Index, if (RDecl->isUnion()) NumElements = 1; else - NumElements = std::distance(RDecl->field_begin(SemaRef.Context), - RDecl->field_end(SemaRef.Context)); + NumElements = std::distance(RDecl->field_begin(), + RDecl->field_end()); } if (NumElements < NumInits) diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp index cc9e783f6166..6f2fc5e0c434 100644 --- a/lib/Sema/SemaLookup.cpp +++ b/lib/Sema/SemaLookup.cpp @@ -65,7 +65,7 @@ void AddNamespaceUsingDirectives(ASTContext &Context, NamespaceSet &Visited) { DeclContext::udir_iterator I, End; - for (llvm::tie(I, End) = NS->getUsingDirectives(Context); I !=End; ++I) { + for (llvm::tie(I, End) = NS->getUsingDirectives(); I !=End; ++I) { UDirs.push_back(*I); std::push_heap(UDirs.begin(), UDirs.end(), UsingDirAncestorCompare()); NamespaceDecl *Nominated = (*I)->getNominatedNamespace(); @@ -609,7 +609,7 @@ CppNamespaceLookup(ASTContext &Context, DeclContext *NS, // Perform qualified name lookup into the LookupCtx. DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = NS->lookup(Context, Name); I != E; ++I) + for (llvm::tie(I, E) = NS->lookup(Name); I != E; ++I) if (Sema::isAcceptableLookupResult(*I, NameKind, IDNS)) { Results.push_back(Sema::LookupResult::CreateLookupResult(Context, I, E)); break; @@ -903,7 +903,7 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind, continue; } - if ((*I)->getAttr<OverloadableAttr>(Context)) { + if ((*I)->getAttr<OverloadableAttr>()) { // If this declaration has the "overloadable" attribute, we // might have a set of overloaded functions. @@ -1005,7 +1005,7 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name, // Perform qualified name lookup into the LookupCtx. DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = LookupCtx->lookup(Context, Name); I != E; ++I) + for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I) if (isAcceptableLookupResult(*I, NameKind, IDNS)) return LookupResult::CreateLookupResult(Context, I, E); @@ -1148,7 +1148,7 @@ Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS, // (C++0x [temp.dep.type]). unsigned IDNS = getIdentifierNamespacesFromLookupNameKind(NameKind, true); DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = Current->lookup(Context, Name); I != E; ++I) + for (llvm::tie(I, E) = Current->lookup(Name); I != E; ++I) if (isAcceptableLookupResult(*I, NameKind, IDNS)) return LookupResult::CreateLookupResult(Context, I, E); } @@ -1604,9 +1604,17 @@ void Sema::LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, for (LookupResult::iterator Op = Operators.begin(), OpEnd = Operators.end(); Op != OpEnd; ++Op) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Op)) { if (IsAcceptableNonMemberOperatorCandidate(FD, T1, T2, Context)) Functions.insert(FD); // FIXME: canonical FD + } else if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>(*Op)) { + // FIXME: friend operators? + // FIXME: do we need to check IsAcceptableNonMemberOperatorCandidate, + // later? + if (!FunTmpl->getDeclContext()->isRecord()) + Functions.insert(FunTmpl); + } } } @@ -1648,25 +1656,23 @@ void Sema::ArgumentDependentLookup(DeclarationName Name, // namespaces even if they are not visible during an ordinary // lookup (11.4). DeclContext::lookup_iterator I, E; - for (llvm::tie(I, E) = (*NS)->lookup(Context, Name); I != E; ++I) { - FunctionDecl *Func = dyn_cast<FunctionDecl>(*I); - if (!Func) - break; - - Functions.insert(Func); + for (llvm::tie(I, E) = (*NS)->lookup(Name); I != E; ++I) { + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I)) + Functions.insert(Func); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I)) + Functions.insert(FunTmpl); } } if (GlobalScope) { DeclContext::lookup_iterator I, E; for (llvm::tie(I, E) - = Context.getTranslationUnitDecl()->lookup(Context, Name); + = Context.getTranslationUnitDecl()->lookup(Name); I != E; ++I) { - FunctionDecl *Func = dyn_cast<FunctionDecl>(*I); - if (!Func) - break; - - Functions.insert(Func); + if (FunctionDecl *Func = dyn_cast<FunctionDecl>(*I)) + Functions.insert(Func); + else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*I)) + Functions.insert(FunTmpl); } } } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index fcc155750cdc..03ac2d9bb73a 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1375,7 +1375,7 @@ bool Sema::IsUserDefinedConversion(Expr *From, QualType ToType, Context.getCanonicalType(ToType).getUnqualifiedType()); DeclContext::lookup_iterator Con, ConEnd; for (llvm::tie(Con, ConEnd) - = ToRecordDecl->lookup(Context, ConstructorName); + = ToRecordDecl->lookup(ConstructorName); Con != ConEnd; ++Con) { CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(*Con); if (Constructor->isConvertingConstructor()) @@ -2161,9 +2161,16 @@ void Sema::AddFunctionCandidates(const FunctionSet &Functions, bool SuppressUserConversions) { for (FunctionSet::const_iterator F = Functions.begin(), FEnd = Functions.end(); - F != FEnd; ++F) - AddOverloadCandidate(*F, Args, NumArgs, CandidateSet, - SuppressUserConversions); + F != FEnd; ++F) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*F)) + AddOverloadCandidate(FD, Args, NumArgs, CandidateSet, + SuppressUserConversions); + else + AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*F), + /*FIXME: explicit args */false, 0, 0, + Args, NumArgs, CandidateSet, + SuppressUserConversions); + } } /// AddMethodCandidate - Adds the given C++ member function to the set @@ -2267,6 +2274,9 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, Expr *Object, /// template specialization. void Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, OverloadCandidateSet& CandidateSet, bool SuppressUserConversions, @@ -2283,8 +2293,9 @@ Sema::AddTemplateOverloadCandidate(FunctionTemplateDecl *FunctionTemplate, TemplateDeductionInfo Info(Context); FunctionDecl *Specialization = 0; if (TemplateDeductionResult Result - = DeduceTemplateArguments(FunctionTemplate, Args, NumArgs, - Specialization, Info)) { + = DeduceTemplateArguments(FunctionTemplate, HasExplicitTemplateArgs, + ExplicitTemplateArgs, NumExplicitTemplateArgs, + Args, NumArgs, Specialization, Info)) { // FIXME: Record what happened with template argument deduction, so // that we can give the user a beautiful diagnostic. (void)Result; @@ -2510,7 +2521,7 @@ void Sema::AddMemberOperatorCandidates(OverloadedOperatorKind Op, // FIXME: Lookup in base classes, too! if (const RecordType *T1Rec = T1->getAsRecordType()) { DeclContext::lookup_const_iterator Oper, OperEnd; - for (llvm::tie(Oper, OperEnd) = T1Rec->getDecl()->lookup(Context, OpName); + for (llvm::tie(Oper, OperEnd) = T1Rec->getDecl()->lookup(OpName); Oper != OperEnd; ++Oper) AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Args[0], Args+1, NumArgs - 1, CandidateSet, @@ -3405,8 +3416,11 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), CandEnd = CandidateSet.end(); Cand != CandEnd; ++Cand) - if (Cand->Function) + if (Cand->Function) { Functions.insert(Cand->Function); + if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate()) + Functions.insert(FunTmpl); + } ArgumentDependentLookup(Name, Args, NumArgs, Functions); @@ -3415,15 +3429,24 @@ Sema::AddArgumentDependentLookupCandidates(DeclarationName Name, for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(), CandEnd = CandidateSet.end(); Cand != CandEnd; ++Cand) - if (Cand->Function) + if (Cand->Function) { Functions.erase(Cand->Function); + if (FunctionTemplateDecl *FunTmpl = Cand->Function->getPrimaryTemplate()) + Functions.erase(FunTmpl); + } // For each of the ADL candidates we found, add it to the overload // set. for (FunctionSet::iterator Func = Functions.begin(), FuncEnd = Functions.end(); - Func != FuncEnd; ++Func) - AddOverloadCandidate(*Func, Args, NumArgs, CandidateSet); + Func != FuncEnd; ++Func) { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*Func)) + AddOverloadCandidate(FD, Args, NumArgs, CandidateSet); + else + AddTemplateOverloadCandidate(cast<FunctionTemplateDecl>(*Func), + /*FIXME: explicit args */false, 0, 0, + Args, NumArgs, CandidateSet); + } } /// isBetterOverloadCandidate - Determines whether the first overload @@ -3556,7 +3579,7 @@ Sema::BestViableFunction(OverloadCandidateSet& CandidateSet, // Best is the best viable function. if (Best->Function && (Best->Function->isDeleted() || - Best->Function->getAttr<UnavailableAttr>(Context))) + Best->Function->getAttr<UnavailableAttr>())) return OR_Deleted; // C++ [basic.def.odr]p2: @@ -3583,7 +3606,7 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, if (Cand->Viable || !OnlyViable) { if (Cand->Function) { if (Cand->Function->isDeleted() || - Cand->Function->getAttr<UnavailableAttr>(Context)) { + Cand->Function->getAttr<UnavailableAttr>()) { // Deleted or "unavailable" function. Diag(Cand->Function->getLocation(), diag::err_ovl_candidate_deleted) << Cand->Function->isDeleted(); @@ -3741,6 +3764,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, /// arguments and Fn, and returns NULL. FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, DeclarationName UnqualifiedName, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, SourceLocation LParenLoc, Expr **Args, unsigned NumArgs, SourceLocation *CommaLocs, @@ -3773,11 +3799,17 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, Func != FuncEnd; ++Func) { DeclContext *Ctx = 0; if (FunctionDecl *FunDecl = dyn_cast<FunctionDecl>(*Func)) { + if (HasExplicitTemplateArgs) + continue; + AddOverloadCandidate(FunDecl, Args, NumArgs, CandidateSet); Ctx = FunDecl->getDeclContext(); } else { FunctionTemplateDecl *FunTmpl = cast<FunctionTemplateDecl>(*Func); - AddTemplateOverloadCandidate(FunTmpl, Args, NumArgs, CandidateSet); + AddTemplateOverloadCandidate(FunTmpl, HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + Args, NumArgs, CandidateSet); Ctx = FunTmpl->getDeclContext(); } @@ -3786,6 +3818,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, ArgumentDependentLookup = false; } } else if (FunctionDecl *Func = dyn_cast_or_null<FunctionDecl>(Callee)) { + assert(!HasExplicitTemplateArgs && "Explicit template arguments?"); AddOverloadCandidate(Func, Args, NumArgs, CandidateSet); if (Func->getDeclContext()->isRecord() || @@ -3793,7 +3826,10 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, ArgumentDependentLookup = false; } else if (FunctionTemplateDecl *FuncTemplate = dyn_cast_or_null<FunctionTemplateDecl>(Callee)) { - AddTemplateOverloadCandidate(FuncTemplate, Args, NumArgs, CandidateSet); + AddTemplateOverloadCandidate(FuncTemplate, HasExplicitTemplateArgs, + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + Args, NumArgs, CandidateSet); if (FuncTemplate->getDeclContext()->isRecord()) ArgumentDependentLookup = false; @@ -3802,6 +3838,7 @@ FunctionDecl *Sema::ResolveOverloadedCallFn(Expr *Fn, NamedDecl *Callee, if (Callee) UnqualifiedName = Callee->getDeclName(); + // FIXME: Pass explicit template arguments through for ADL if (ArgumentDependentLookup) AddArgumentDependentLookupCandidates(UnqualifiedName, Args, NumArgs, CandidateSet); @@ -4273,7 +4310,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object, OverloadCandidateSet CandidateSet; DeclarationName OpName = Context.DeclarationNames.getCXXOperatorName(OO_Call); DeclContext::lookup_const_iterator Oper, OperEnd; - for (llvm::tie(Oper, OperEnd) = Record->getDecl()->lookup(Context, OpName); + for (llvm::tie(Oper, OperEnd) = Record->getDecl()->lookup(OpName); Oper != OperEnd; ++Oper) AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs, CandidateSet, /*SuppressUserConversions=*/false); @@ -4477,8 +4514,7 @@ Sema::BuildOverloadedArrowExpr(Scope *S, Expr *Base, SourceLocation OpLoc, DeclContext::lookup_const_iterator Oper, OperEnd; for (llvm::tie(Oper, OperEnd) - = BaseRecord->getDecl()->lookup(Context, OpName); - Oper != OperEnd; ++Oper) + = BaseRecord->getDecl()->lookup(OpName); Oper != OperEnd; ++Oper) AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Base, 0, 0, CandidateSet, /*SuppressUserConversions=*/false); diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index 914839cbf790..63191e0e00cc 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -84,7 +84,7 @@ Sema::ActOnCompoundStmt(SourceLocation L, SourceLocation R, SourceLocation Loc; SourceRange R1, R2; - if (!E->isUnusedResultAWarning(Loc, R1, R2, Context)) + if (!E->isUnusedResultAWarning(Loc, R1, R2)) continue; Diag(Loc, diag::warn_unused_expr) << R1 << R2; @@ -766,7 +766,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } QualType FnRetType = CurBlock->ReturnType; - if (CurBlock->TheDecl->hasAttr<NoReturnAttr>(Context)) { + if (CurBlock->TheDecl->hasAttr<NoReturnAttr>()) { Diag(ReturnLoc, diag::err_noreturn_block_has_return_expr) << getCurFunctionOrMethodDecl()->getDeclName(); return StmtError(); @@ -842,7 +842,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, FullExprArg rex) { QualType FnRetType; if (const FunctionDecl *FD = getCurFunctionDecl()) { FnRetType = FD->getResultType(); - if (FD->hasAttr<NoReturnAttr>(Context)) + if (FD->hasAttr<NoReturnAttr>()) Diag(ReturnLoc, diag::warn_noreturn_function_has_return_expr) << getCurFunctionOrMethodDecl()->getDeclName(); } else if (ObjCMethodDecl *MD = getCurMethodDecl()) diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index cd985c536c77..568d68c9a7e8 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -852,7 +852,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, NumTemplateArgs); if (CheckTemplateArgumentList(Template, TemplateLoc, LAngleLoc, TemplateArgs, NumTemplateArgs, RAngleLoc, - Converted)) + false, Converted)) return QualType(); assert((Converted.structuredSize() == @@ -933,6 +933,42 @@ Sema::ActOnTemplateIdType(TemplateTy TemplateD, SourceLocation TemplateLoc, return Result.getAsOpaquePtr(); } +Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + SourceLocation RAngleLoc) { + // FIXME: Can we do any checking at this point? I guess we could check the + // template arguments that we have against the template name, if the template + // name refers to a single template. That's not a terribly common case, + // though. + return Owned(TemplateIdRefExpr::Create(Context, + /*FIXME: New type?*/Context.OverloadTy, + /*FIXME: Necessary?*/0, + /*FIXME: Necessary?*/SourceRange(), + Template, TemplateNameLoc, LAngleLoc, + TemplateArgs, + NumTemplateArgs, RAngleLoc)); +} + +Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc) { + TemplateName Template = TemplateD.getAsVal<TemplateName>(); + + // Translate the parser's template argument list in our AST format. + llvm::SmallVector<TemplateArgument, 16> TemplateArgs; + translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs); + + return BuildTemplateIdExpr(Template, TemplateNameLoc, LAngleLoc, + TemplateArgs.data(), TemplateArgs.size(), + RAngleLoc); +} + /// \brief Form a dependent template name. /// /// This action forms a dependent template name given the template @@ -1019,6 +1055,7 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, SourceLocation RAngleLoc, + bool PartialTemplateArgs, TemplateArgumentListBuilder &Converted) { TemplateParameterList *Params = Template->getTemplateParameters(); unsigned NumParams = Params->size(); @@ -1029,7 +1066,8 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, NumParams > 0 && Params->getParam(NumParams - 1)->isTemplateParameterPack(); if ((NumArgs > NumParams && !HasParameterPack) || - NumArgs < Params->getMinRequiredArguments()) { + (NumArgs < Params->getMinRequiredArguments() && + !PartialTemplateArgs)) { // FIXME: point at either the first arg beyond what we can handle, // or the '>', depending on whether we have too many or too few // arguments. @@ -1056,6 +1094,9 @@ bool Sema::CheckTemplateArgumentList(TemplateDecl *Template, for (TemplateParameterList::iterator Param = Params->begin(), ParamEnd = Params->end(); Param != ParamEnd; ++Param, ++ArgIdx) { + if (ArgIdx > NumArgs && PartialTemplateArgs) + break; + // Decode the template argument TemplateArgument Arg; if (ArgIdx >= NumArgs) { @@ -2302,7 +2343,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, TemplateArgs.size()); if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, Converted)) + RAngleLoc, false, Converted)) return true; assert((Converted.structuredSize() == @@ -2498,7 +2539,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, // Add the specialization into its lexical context, so that it can // be seen when iterating through the list of declarations in that // context. However, specializations are not found by name lookup. - CurContext->addDecl(Context, Specialization); + CurContext->addDecl(Specialization); return DeclPtrTy::make(Specialization); } @@ -2597,7 +2638,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, TemplateArgs.size()); if (CheckTemplateArgumentList(ClassTemplate, TemplateNameLoc, LAngleLoc, TemplateArgs.data(), TemplateArgs.size(), - RAngleLoc, Converted)) + RAngleLoc, false, Converted)) return true; assert((Converted.structuredSize() == @@ -2654,7 +2695,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, ClassTemplate, Converted, 0); Specialization->setLexicalDeclContext(CurContext); - CurContext->addDecl(Context, Specialization); + CurContext->addDecl(Specialization); return DeclPtrTy::make(Specialization); } @@ -2703,7 +2744,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, // since explicit instantiations are never found by name lookup, we // just put it into the declaration context directly. Specialization->setLexicalDeclContext(CurContext); - CurContext->addDecl(Context, Specialization); + CurContext->addDecl(Specialization); // C++ [temp.explicit]p3: // A definition of a class template or class member template diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index 3d909bb26a79..5a0578f6bcb7 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -868,6 +868,16 @@ static bool isSimpleTemplateIdType(QualType T) { /// \param FunctionTemplate the function template for which we are performing /// template argument deduction. /// +/// \param HasExplicitTemplateArgs whether any template arguments were +/// explicitly specified. +/// +/// \param ExplicitTemplateArguments when @p HasExplicitTemplateArgs is true, +/// the explicitly-specified template arguments. +/// +/// \param NumExplicitTemplateArguments when @p HasExplicitTemplateArgs is true, +/// the number of explicitly-specified template arguments in +/// @p ExplicitTemplateArguments. This value may be zero. +/// /// \param Args the function call arguments /// /// \param NumArgs the number of arguments in Args @@ -880,22 +890,22 @@ static bool isSimpleTemplateIdType(QualType T) { /// about template argument deduction. /// /// \returns the result of template argument deduction. -/// -/// FIXME: We will also need to pass in any explicitly-specified template -/// arguments. Sema::TemplateDeductionResult Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, + bool HasExplicitTemplateArgs, + const TemplateArgument *ExplicitTemplateArgs, + unsigned NumExplicitTemplateArgs, Expr **Args, unsigned NumArgs, FunctionDecl *&Specialization, TemplateDeductionInfo &Info) { FunctionDecl *Function = FunctionTemplate->getTemplatedDecl(); - + // C++ [temp.deduct.call]p1: // Template argument deduction is done by comparing each function template // parameter type (call it P) with the type of the corresponding argument // of the call (call it A) as described below. unsigned CheckArgs = NumArgs; - if (NumArgs < Function->getNumParams()) + if (NumArgs < Function->getMinRequiredArguments()) return TDK_TooFewArguments; else if (NumArgs > Function->getNumParams()) { const FunctionProtoType *Proto @@ -905,18 +915,87 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, CheckArgs = Function->getNumParams(); } - + // Template argument deduction for function templates in a SFINAE context. // Trap any errors that might occur. SFINAETrap Trap(*this); - - // Deduce template arguments from the function parameters. - llvm::SmallVector<TemplateArgument, 4> Deduced; - Deduced.resize(FunctionTemplate->getTemplateParameters()->size()); + + // The types of the parameters from which we will perform template argument + // deduction. TemplateParameterList *TemplateParams = FunctionTemplate->getTemplateParameters(); + llvm::SmallVector<TemplateArgument, 4> Deduced; + llvm::SmallVector<QualType, 4> ParamTypes; + if (NumExplicitTemplateArgs) { + // C++ [temp.arg.explicit]p3: + // Template arguments that are present shall be specified in the + // declaration order of their corresponding template-parameters. The + // template argument list shall not specify more template-arguments than + // there are corresponding template-parameters. + TemplateArgumentListBuilder Builder(TemplateParams, + NumExplicitTemplateArgs); + + // Enter a new template instantiation context where we check the + // explicitly-specified template arguments against this function template, + // and then substitute them into the function parameter types. + InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), + FunctionTemplate, Deduced.data(), Deduced.size(), + ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution); + if (Inst) + return TDK_InstantiationDepth; + + if (CheckTemplateArgumentList(FunctionTemplate, + SourceLocation(), SourceLocation(), + ExplicitTemplateArgs, + NumExplicitTemplateArgs, + SourceLocation(), + true, + Builder) || Trap.hasErrorOccurred()) + return TDK_InvalidExplicitArguments; + + // Form the template argument list from the explicitly-specified + // template arguments. + TemplateArgumentList *ExplicitArgumentList + = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true); + Info.reset(ExplicitArgumentList); + + // Instantiate the types of each of the function parameters given the + // explicitly-specified template arguments. + for (FunctionDecl::param_iterator P = Function->param_begin(), + PEnd = Function->param_end(); + P != PEnd; + ++P) { + QualType ParamType = InstantiateType((*P)->getType(), + *ExplicitArgumentList, + (*P)->getLocation(), + (*P)->getDeclName()); + if (ParamType.isNull() || Trap.hasErrorOccurred()) + return TDK_SubstitutionFailure; + + ParamTypes.push_back(ParamType); + } + + // C++ [temp.arg.explicit]p2: + // Trailing template arguments that can be deduced (14.8.2) may be + // omitted from the list of explicit template- arguments. If all of the + // template arguments can be deduced, they may all be omitted; in this + // case, the empty template argument list <> itself may also be omitted. + // + // Take all of the explicitly-specified arguments and put them into the + // set of deduced template arguments. + Deduced.reserve(TemplateParams->size()); + for (unsigned I = 0, N = ExplicitArgumentList->size(); I != N; ++I) + Deduced.push_back(ExplicitArgumentList->get(I)); + } else { + // Just fill in the parameter types from the function declaration. + for (unsigned I = 0; I != CheckArgs; ++I) + ParamTypes.push_back(Function->getParamDecl(I)->getType()); + } + + // Deduce template arguments from the function parameters. + Deduced.resize(TemplateParams->size()); for (unsigned I = 0; I != CheckArgs; ++I) { - QualType ParamType = Function->getParamDecl(I)->getType(); + QualType ParamType = ParamTypes[I]; QualType ArgType = Args[I]->getType(); // C++ [temp.deduct.call]p2: @@ -998,11 +1077,6 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, // FIXME: C++ [temp.deduct.call] paragraphs 6-9 deal with function // pointer parameters. } - - InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), - FunctionTemplate, Deduced.data(), Deduced.size()); - if (Inst) - return TDK_InstantiationDepth; // C++ [temp.deduct.type]p2: // [...] or if any template argument remains neither deduced nor @@ -1030,20 +1104,36 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, = new (Context) TemplateArgumentList(Context, Builder, /*TakeArgs=*/true); Info.reset(DeducedArgumentList); + // Enter a new template instantiation context while we instantiate the + // actual function declaration. + InstantiatingTemplate Inst(*this, FunctionTemplate->getLocation(), + FunctionTemplate, Deduced.data(), Deduced.size(), + ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution); + if (Inst) + return TDK_InstantiationDepth; + // Substitute the deduced template arguments into the function template // declaration to produce the function template specialization. Specialization = cast_or_null<FunctionDecl>( InstantiateDecl(FunctionTemplate->getTemplatedDecl(), FunctionTemplate->getDeclContext(), *DeducedArgumentList)); + if (!Specialization) + return TDK_SubstitutionFailure; - if (!Specialization || Trap.hasErrorOccurred()) + // If the template argument list is owned by the function template + // specialization, release it. + if (Specialization->getTemplateSpecializationArgs() == DeducedArgumentList) + Info.take(); + + // There may have been an error that did not prevent us from constructing a + // declaration. Mark the declaration invalid and return with a substitution + // failure. + if (Trap.hasErrorOccurred()) { + Specialization->setInvalidDecl(true); return TDK_SubstitutionFailure; - - // Turn the specialization into an actual function template specialization. - Specialization->setFunctionTemplateSpecialization(Context, - FunctionTemplate, - Info.take()); + } + return TDK_Success; } diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index aed348966a4f..6c2dc77b4cce 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -100,6 +100,30 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, + FunctionTemplateDecl *FunctionTemplate, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, + ActiveTemplateInstantiation::InstantiationKind Kind, + SourceRange InstantiationRange) +: SemaRef(SemaRef) { + + Invalid = CheckInstantiationDepth(PointOfInstantiation, + InstantiationRange); + if (!Invalid) { + ActiveTemplateInstantiation Inst; + Inst.Kind = Kind; + Inst.PointOfInstantiation = PointOfInstantiation; + Inst.Entity = reinterpret_cast<uintptr_t>(FunctionTemplate); + Inst.TemplateArgs = TemplateArgs; + Inst.NumTemplateArgs = NumTemplateArgs; + Inst.InstantiationRange = InstantiationRange; + SemaRef.ActiveTemplateInstantiations.push_back(Inst); + Invalid = false; + } +} + +Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, + SourceLocation PointOfInstantiation, ClassTemplatePartialSpecializationDecl *PartialSpec, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs, @@ -111,7 +135,7 @@ Sema::InstantiatingTemplate::InstantiatingTemplate(Sema &SemaRef, if (!Invalid) { ActiveTemplateInstantiation Inst; Inst.Kind - = ActiveTemplateInstantiation::PartialSpecDeductionInstantiation; + = ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution; Inst.PointOfInstantiation = PointOfInstantiation; Inst.Entity = reinterpret_cast<uintptr_t>(PartialSpec); Inst.TemplateArgs = TemplateArgs; @@ -148,6 +172,7 @@ bool Sema::InstantiatingTemplate::CheckInstantiationDepth( /// \brief Prints the current instantiation stack through a series of /// notes. void Sema::PrintInstantiationStack() { + // FIXME: In all of these cases, we need to show the template arguments for (llvm::SmallVector<ActiveTemplateInstantiation, 16>::reverse_iterator Active = ActiveTemplateInstantiations.rbegin(), ActiveEnd = ActiveTemplateInstantiations.rend(); @@ -183,7 +208,7 @@ void Sema::PrintInstantiationStack() { TemplateDecl *Template = cast<TemplateDecl>((Decl *)Active->Entity); std::string TemplateArgsStr = TemplateSpecializationType::PrintTemplateArgumentList( - Active->TemplateArgs, + Active->TemplateArgs, Active->NumTemplateArgs, Context.PrintingPolicy); Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), @@ -193,18 +218,31 @@ void Sema::PrintInstantiationStack() { break; } - case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation: { - ClassTemplatePartialSpecializationDecl *PartialSpec - = cast<ClassTemplatePartialSpecializationDecl>((Decl *)Active->Entity); - // FIXME: The active template instantiation's template arguments - // are interesting, too. We should add something like [with T = - // foo, U = bar, etc.] to the string. + case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: { + FunctionTemplateDecl *FnTmpl + = cast<FunctionTemplateDecl>((Decl *)Active->Entity); Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), - diag::note_partial_spec_deduct_instantiation_here) - << Context.getTypeDeclType(PartialSpec) - << Active->InstantiationRange; + diag::note_explicit_template_arg_substitution_here) + << FnTmpl << Active->InstantiationRange; break; } + + case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution: + if (ClassTemplatePartialSpecializationDecl *PartialSpec + = dyn_cast<ClassTemplatePartialSpecializationDecl>( + (Decl *)Active->Entity)) { + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_partial_spec_deduct_instantiation_here) + << Context.getTypeDeclType(PartialSpec) + << Active->InstantiationRange; + } else { + FunctionTemplateDecl *FnTmpl + = cast<FunctionTemplateDecl>((Decl *)Active->Entity); + Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr), + diag::note_function_template_deduction_instantiation_here) + << FnTmpl << Active->InstantiationRange; + } + break; } } @@ -219,19 +257,20 @@ bool Sema::isSFINAEContext() const { ++Active) { switch(Active->Kind) { - case ActiveTemplateInstantiation::PartialSpecDeductionInstantiation: - // We're in a template argument deduction context, so SFINAE - // applies. - return true; - + case ActiveTemplateInstantiation::TemplateInstantiation: + // This is a template instantiation, so there is no SFINAE. + return false; + case ActiveTemplateInstantiation::DefaultTemplateArgumentInstantiation: // A default template argument instantiation may or may not be a // SFINAE context; look further up the stack. break; - - case ActiveTemplateInstantiation::TemplateInstantiation: - // This is a template instantiation, so there is no SFINAE. - return false; + + case ActiveTemplateInstantiation::ExplicitTemplateArgumentSubstitution: + case ActiveTemplateInstantiation::DeducedTemplateArgumentSubstitution: + // We're either substitution explicitly-specified template arguments + // or deduced template arguments, so SFINAE applies. + return true; } } @@ -530,7 +569,7 @@ TemplateTypeInstantiator::InstantiateTypeOfExprType( if (E.isInvalid()) return QualType(); - return SemaRef.Context.getTypeOfExprType(E.takeAs<Expr>()); + return SemaRef.BuildTypeofExprType(E.takeAs<Expr>()); } QualType @@ -555,7 +594,7 @@ TemplateTypeInstantiator::InstantiateDecltypeType(const DecltypeType *T) const { if (E.isInvalid()) return QualType(); - return SemaRef.Context.getDecltypeType(E.takeAs<Expr>()); + return SemaRef.BuildDecltypeType(E.takeAs<Expr>()); } QualType @@ -584,6 +623,15 @@ InstantiateTemplateTypeParmType(const TemplateTypeParmType *T) const { if (T->getDepth() == 0) { // Replace the template type parameter with its corresponding // template argument. + + // If the corresponding template argument is NULL or doesn't exist, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template class, but there were some + // arguments left unspecified. + if (T->getIndex() >= TemplateArgs.size() || + TemplateArgs[T->getIndex()].isNull()) + return QualType(T, 0); // Would be nice to keep the original type here + assert(TemplateArgs[T->getIndex()].getKind() == TemplateArgument::Type && "Template argument kind mismatch"); return TemplateArgs[T->getIndex()].getAsType(); @@ -859,8 +907,8 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, Invalid = true; llvm::SmallVector<DeclPtrTy, 4> Fields; - for (RecordDecl::decl_iterator Member = Pattern->decls_begin(Context), - MemberEnd = Pattern->decls_end(Context); + for (RecordDecl::decl_iterator Member = Pattern->decls_begin(), + MemberEnd = Pattern->decls_end(); Member != MemberEnd; ++Member) { Decl *NewMember = InstantiateDecl(*Member, Instantiation, TemplateArgs); if (NewMember) { @@ -996,11 +1044,11 @@ void Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, CXXRecordDecl *Instantiation, const TemplateArgumentList &TemplateArgs) { - for (DeclContext::decl_iterator D = Instantiation->decls_begin(Context), - DEnd = Instantiation->decls_end(Context); + for (DeclContext::decl_iterator D = Instantiation->decls_begin(), + DEnd = Instantiation->decls_end(); D != DEnd; ++D) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) { - if (!Function->getBody(Context)) + if (!Function->getBody()) InstantiateFunctionDefinition(PointOfInstantiation, Function); } else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) { const VarDecl *Def = 0; diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index a05095fa57a6..f59719992066 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -98,7 +98,7 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { if (Invalid) Typedef->setInvalidDecl(); - Owner->addDecl(SemaRef.Context, Typedef); + Owner->addDecl(Typedef); return Typedef; } @@ -124,7 +124,7 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) { // are not static data members. bool Redeclaration = false; SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration); - Owner->addDecl(SemaRef.Context, Var); + Owner->addDecl(Var); if (D->getInit()) { OwningExprResult Init @@ -188,7 +188,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) { if (Invalid) Field->setInvalidDecl(); - Owner->addDecl(SemaRef.Context, Field); + Owner->addDecl(Field); } return Field; @@ -219,14 +219,14 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { /*PrevDecl=*/0); Enum->setInstantiationOfMemberEnum(D); Enum->setAccess(D->getAccess()); - Owner->addDecl(SemaRef.Context, Enum); + Owner->addDecl(Enum); Enum->startDefinition(); llvm::SmallVector<Sema::DeclPtrTy, 4> Enumerators; EnumConstantDecl *LastEnumConst = 0; - for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(SemaRef.Context), - ECEnd = D->enumerator_end(SemaRef.Context); + for (EnumDecl::enumerator_iterator EC = D->enumerator_begin(), + ECEnd = D->enumerator_end(); EC != ECEnd; ++EC) { // The specified value for the enumerator. OwningExprResult Value = SemaRef.Owned((Expr *)0); @@ -257,7 +257,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { } if (EnumConst) { - Enum->addDecl(SemaRef.Context, EnumConst); + Enum->addDecl(EnumConst); Enumerators.push_back(Sema::DeclPtrTy::make(EnumConst)); LastEnumConst = EnumConst; } @@ -289,12 +289,29 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { if (!D->isInjectedClassName()) Record->setInstantiationOfMemberClass(D); - Owner->addDecl(SemaRef.Context, Record); + Owner->addDecl(Record); return Record; } Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { - // FIXME: Look for existing specializations (explicit or otherwise). + // Check whether there is already a function template specialization for + // this declaration. + FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); + void *InsertPos = 0; + if (FunctionTemplate) { + llvm::FoldingSetNodeID ID; + FunctionTemplateSpecializationInfo::Profile(ID, + TemplateArgs.getFlatArgumentList(), + TemplateArgs.flat_size()); + + FunctionTemplateSpecializationInfo *Info + = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, + InsertPos); + + // If we already have a function template specialization, return it. + if (Info) + return Info->Function; + } Sema::LocalInstantiationScope Scope(SemaRef); @@ -325,10 +342,15 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) { NamedDecl *PrevDecl = 0; SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration, /*FIXME:*/OverloadableAttrRequired); - - // FIXME: link this to the function template from which it was instantiated. - + if (FunctionTemplate) { + // Record this function template specialization. + Function->setFunctionTemplateSpecialization(SemaRef.Context, + FunctionTemplate, + &TemplateArgs, + InsertPos); + } + return Function; } @@ -372,7 +394,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D) { /*FIXME:*/OverloadableAttrRequired); if (!Method->isInvalidDecl() || !PrevDecl) - Owner->addDecl(SemaRef.Context, Method); + Owner->addDecl(Method); return Method; } @@ -420,7 +442,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConstructorDecl(CXXConstructorDecl *D) { /*FIXME:*/OverloadableAttrRequired); Record->addedConstructor(SemaRef.Context, Constructor); - Owner->addDecl(SemaRef.Context, Constructor); + Owner->addDecl(Constructor); return Constructor; } @@ -452,7 +474,7 @@ Decl *TemplateDeclInstantiator::VisitCXXDestructorDecl(CXXDestructorDecl *D) { NamedDecl *PrevDecl = 0; SemaRef.CheckFunctionDeclaration(Destructor, PrevDecl, Redeclaration, /*FIXME:*/OverloadableAttrRequired); - Owner->addDecl(SemaRef.Context, Destructor); + Owner->addDecl(Destructor); return Destructor; } @@ -485,7 +507,7 @@ Decl *TemplateDeclInstantiator::VisitCXXConversionDecl(CXXConversionDecl *D) { NamedDecl *PrevDecl = 0; SemaRef.CheckFunctionDeclaration(Conversion, PrevDecl, Redeclaration, /*FIXME:*/OverloadableAttrRequired); - Owner->addDecl(SemaRef.Context, Conversion); + Owner->addDecl(Conversion); return Conversion; } @@ -606,6 +628,28 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, FunctionDecl *Tmpl) { if (Tmpl->isDeleted()) New->setDeleted(); + + // If we are performing substituting explicitly-specified template arguments + // or deduced template arguments into a function template and we reach this + // point, we are now past the point where SFINAE applies and have committed + // to keeping the new function template specialization. We therefore + // convert the active template instantiation for the function template + // into a template instantiation for this specific function template + // specialization, which is not a SFINAE context, so that we diagnose any + // further errors in the declaration itself. + typedef Sema::ActiveTemplateInstantiation ActiveInstType; + ActiveInstType &ActiveInst = SemaRef.ActiveTemplateInstantiations.back(); + if (ActiveInst.Kind == ActiveInstType::ExplicitTemplateArgumentSubstitution || + ActiveInst.Kind == ActiveInstType::DeducedTemplateArgumentSubstitution) { + if (FunctionTemplateDecl *FunTmpl + = dyn_cast<FunctionTemplateDecl>((Decl *)ActiveInst.Entity)) { + assert(FunTmpl->getTemplatedDecl() == Tmpl && + "Deduction from the wrong function template?"); + ActiveInst.Kind = ActiveInstType::TemplateInstantiation; + ActiveInst.Entity = reinterpret_cast<uintptr_t>(New); + } + } + return false; } @@ -641,14 +685,23 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New, /// \brief Instantiate the definition of the given function from its /// template. /// +/// \param PointOfInstantiation the point at which the instantiation was +/// required. Note that this is not precisely a "point of instantiation" +/// for the function, but it's close. +/// /// \param Function the already-instantiated declaration of a -/// function. +/// function template specialization or member function of a class template +/// specialization. +/// +/// \param Recursive if true, recursively instantiates any functions that +/// are required by this instantiation. void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, - FunctionDecl *Function) { + FunctionDecl *Function, + bool Recursive) { if (Function->isInvalidDecl()) return; - assert(!Function->getBody(Context) && "Already instantiated!"); + assert(!Function->getBody() && "Already instantiated!"); // Find the function body that we'll be substituting. const FunctionDecl *PatternDecl = 0; @@ -658,7 +711,7 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, PatternDecl = Function->getInstantiatedFromMemberFunction(); Stmt *Pattern = 0; if (PatternDecl) - Pattern = PatternDecl->getBody(Context, PatternDecl); + Pattern = PatternDecl->getBody(PatternDecl); if (!Pattern) return; @@ -667,6 +720,13 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (Inst) return; + // If we're performing recursive template instantiation, create our own + // queue of pending implicit instantiations that we will instantiate later, + // while we're still within our own instantiation context. + std::deque<PendingImplicitInstantiation> SavedPendingImplicitInstantiations; + if (Recursive) + PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations); + ActOnStartOfFunctionDef(0, DeclPtrTy::make(Function)); // Introduce a new scope where local variable instantiations will be @@ -695,6 +755,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, DeclGroupRef DG(Function); Consumer.HandleTopLevelDecl(DG); + + if (Recursive) { + // Instantiate any pending implicit instantiations found during the + // instantiation of this template. + PerformPendingImplicitInstantiations(); + + // Restore the set of pending implicit instantiations. + PendingImplicitInstantiations.swap(SavedPendingImplicitInstantiations); + } } /// \brief Instantiate the definition of the given variable from its @@ -787,8 +856,7 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) { // find the instantiation of the declaration D. NamedDecl *Result = 0; if (D->getDeclName()) { - DeclContext::lookup_result Found - = ParentDC->lookup(Context, D->getDeclName()); + DeclContext::lookup_result Found = ParentDC->lookup(D->getDeclName()); Result = findInstantiationOf(Context, D, Found.first, Found.second); } else { // Since we don't have a name for the entity we're looking for, @@ -800,8 +868,8 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) { // // FIXME: Find a better way to find these instantiations! Result = findInstantiationOf(Context, D, - ParentDC->decls_begin(Context), - ParentDC->decls_end(Context)); + ParentDC->decls_begin(), + ParentDC->decls_end()); } assert(Result && "Unable to find instantiation of declaration!"); D = Result; @@ -838,12 +906,12 @@ NamedDecl * Sema::InstantiateCurrentDeclRef(NamedDecl *D) { void Sema::PerformPendingImplicitInstantiations() { while (!PendingImplicitInstantiations.empty()) { PendingImplicitInstantiation Inst = PendingImplicitInstantiations.front(); - PendingImplicitInstantiations.pop(); + PendingImplicitInstantiations.pop_front(); if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Inst.first)) - if (!Function->getBody(Context)) - InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function); + if (!Function->getBody()) + InstantiateFunctionDefinition(/*FIXME:*/Inst.second, Function, true); - // FIXME: instantiation static member variables + // FIXME: instantiate static member variables } } diff --git a/lib/Sema/SemaTemplateInstantiateExpr.cpp b/lib/Sema/SemaTemplateInstantiateExpr.cpp index 65a35f92f7c6..c82e1a7da3c9 100644 --- a/lib/Sema/SemaTemplateInstantiateExpr.cpp +++ b/lib/Sema/SemaTemplateInstantiateExpr.cpp @@ -107,12 +107,49 @@ TemplateExprInstantiator::VisitUnresolvedFunctionNameExpr( } Sema::OwningExprResult +TemplateExprInstantiator::VisitTemplateIdRefExpr(TemplateIdRefExpr *E) { + TemplateName Template + = SemaRef.InstantiateTemplateName(E->getTemplateName(), E->getTemplateNameLoc(), + TemplateArgs); + // FIXME: Can InstantiateTemplateName report an error? + + llvm::SmallVector<TemplateArgument, 4> InstantiatedArgs; + for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) { + TemplateArgument InstArg = SemaRef.Instantiate(E->getTemplateArgs()[I], + TemplateArgs); + if (InstArg.isNull()) + return SemaRef.ExprError(); + + InstantiatedArgs.push_back(InstArg); + } + + // FIXME: It's possible that we'll find out now that the template name + // actually refers to a type, in which case this is a functional cast. + // Implement this! + + return SemaRef.BuildTemplateIdExpr(Template, E->getTemplateNameLoc(), + E->getLAngleLoc(), + InstantiatedArgs.data(), + InstantiatedArgs.size(), + E->getRAngleLoc()); +} + +Sema::OwningExprResult TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { NamedDecl *D = E->getDecl(); if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(D)) { assert(NTTP->getDepth() == 0 && "No nested templates yet"); - const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; + // If the corresponding template argument is NULL or non-existent, it's + // because we are performing instantiation from explicitly-specified + // template arguments in a function template, but there were some + // arguments left unspecified. + if (NTTP->getPosition() >= TemplateArgs.size() || + TemplateArgs[NTTP->getPosition()].isNull()) + return SemaRef.Owned(E); // FIXME: Clone the expression! + + const TemplateArgument &Arg = TemplateArgs[NTTP->getPosition()]; + // The template argument itself might be an expression, in which // case we just return that expression. if (Arg.getKind() == TemplateArgument::Expression) @@ -156,18 +193,15 @@ TemplateExprInstantiator::VisitDeclRefExpr(DeclRefExpr *E) { false, false)); } - ValueDecl *NewD - = dyn_cast_or_null<ValueDecl>(SemaRef.InstantiateCurrentDeclRef(D)); - if (!NewD) + NamedDecl *InstD = SemaRef.InstantiateCurrentDeclRef(D); + if (!InstD) return SemaRef.ExprError(); - // FIXME: Build QualifiedDeclRefExpr? - QualType T = NewD->getType(); - return SemaRef.Owned(new (SemaRef.Context) DeclRefExpr(NewD, - T.getNonReferenceType(), - E->getLocation(), - T->isDependentType(), - T->isDependentType())); + // FIXME: nested-name-specifier for QualifiedDeclRefExpr + return SemaRef.BuildDeclarationNameExpr(E->getLocation(), InstD, + /*FIXME:*/false, + /*FIXME:*/0, + /*FIXME:*/false); } Sema::OwningExprResult @@ -525,8 +559,7 @@ TemplateExprInstantiator::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { const IdentifierInfo &Name = SemaRef.Context.Idents.get("__builtin_shufflevector"); TranslationUnitDecl *TUDecl = SemaRef.Context.getTranslationUnitDecl(); - DeclContext::lookup_result Lookup - = TUDecl->lookup(SemaRef.Context, DeclarationName(&Name)); + DeclContext::lookup_result Lookup = TUDecl->lookup(DeclarationName(&Name)); assert(Lookup.first != Lookup.second && "No __builtin_shufflevector?"); // Build a reference to the __builtin_shufflevector builtin diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index c6bcdc36f132..3756df870c2c 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/Parse/DeclSpec.h" +#include "llvm/ADT/SmallPtrSet.h" using namespace clang; /// \brief Perform adjustment on the parameter type of a function. @@ -89,8 +90,8 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, case DeclSpec::TST_unspecified: // "<proto1,proto2>" is an objc qualified ID with a missing id. if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { - Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ, - DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectPointerType(0, (ObjCProtocolDecl**)PQ, + DS.getNumProtocolQualifiers()); break; } @@ -200,8 +201,8 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, DS.getNumProtocolQualifiers()); else if (Result == Context.getObjCIdType()) // id<protocol-list> - Result = Context.getObjCQualifiedIdType((ObjCProtocolDecl**)PQ, - DS.getNumProtocolQualifiers()); + Result = Context.getObjCObjectPointerType(0, (ObjCProtocolDecl**)PQ, + DS.getNumProtocolQualifiers()); else if (Result == Context.getObjCClassType()) { if (DeclLoc.isInvalid()) DeclLoc = DS.getSourceRange().getBegin(); @@ -242,7 +243,11 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, Expr *E = static_cast<Expr *>(DS.getTypeRep()); assert(E && "Didn't get an expression for decltype?"); // TypeQuals handled by caller. - Result = Context.getDecltypeType(E); + Result = BuildDecltypeType(E); + if (Result.isNull()) { + Result = Context.IntTy; + isInvalid = true; + } break; } case DeclSpec::TST_auto: { @@ -693,7 +698,7 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, // C++ 8.3.3p3: A pointer to member shall not pointer to ... a member // with reference type, or "cv void." if (T->isReferenceType()) { - Diag(Loc, diag::err_illegal_decl_pointer_to_reference) + Diag(Loc, diag::err_illegal_decl_mempointer_to_reference) << (Entity? Entity.getAsString() : "type name"); return QualType(); } @@ -814,9 +819,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip, case Declarator::KNRTypeListContext: assert(0 && "K&R type lists aren't allowed in C++"); break; - default: - printf("context: %d\n", D.getContext()); - assert(0); case Declarator::PrototypeContext: Error = 0; // Function prototype break; @@ -1062,6 +1064,13 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip, break; } case DeclaratorChunk::MemberPointer: + // Verify that we're not building a pointer to pointer to function with + // exception specification. + if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { + Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec); + D.setInvalidType(true); + // Build the type anyway. + } // The scope spec must refer to a class, or be dependent. QualType ClsType; if (isDependentScopeSpecifier(DeclType.Mem.Scope())) { @@ -1186,6 +1195,45 @@ bool Sema::CheckDistantExceptionSpec(QualType T) { return FnT->hasExceptionSpec(); } +/// CheckEquivalentExceptionSpec - Check if the two types have equivalent +/// exception specifications. Exception specifications are equivalent if +/// they allow exactly the same set of exception types. It does not matter how +/// that is achieved. See C++ [except.spec]p2. +bool Sema::CheckEquivalentExceptionSpec( + const FunctionProtoType *Old, SourceLocation OldLoc, + const FunctionProtoType *New, SourceLocation NewLoc) { + bool OldAny = !Old->hasExceptionSpec() || Old->hasAnyExceptionSpec(); + bool NewAny = !New->hasExceptionSpec() || New->hasAnyExceptionSpec(); + if (OldAny && NewAny) + return false; + if (OldAny || NewAny) { + Diag(NewLoc, diag::err_mismatched_exception_spec); + Diag(OldLoc, diag::note_previous_declaration); + return true; + } + + bool Success = true; + // Both have a definite exception spec. Collect the first set, then compare + // to the second. + llvm::SmallPtrSet<const Type*, 8> Types; + for (FunctionProtoType::exception_iterator I = Old->exception_begin(), + E = Old->exception_end(); I != E; ++I) + Types.insert(Context.getCanonicalType(*I).getTypePtr()); + + for (FunctionProtoType::exception_iterator I = New->exception_begin(), + E = New->exception_end(); I != E && Success; ++I) + Success = Types.erase(Context.getCanonicalType(*I).getTypePtr()); + + Success = Success && Types.empty(); + + if (Success) { + return false; + } + Diag(NewLoc, diag::err_mismatched_exception_spec); + Diag(OldLoc, diag::note_previous_declaration); + return true; +} + /// ObjCGetTypeForMethodDefinition - Builds the type for a method definition /// declarator QualType Sema::ObjCGetTypeForMethodDefinition(DeclPtrTy D) { @@ -1466,3 +1514,16 @@ QualType Sema::getQualifiedNameType(const CXXScopeSpec &SS, QualType T) { = static_cast<NestedNameSpecifier *>(SS.getScopeRep()); return Context.getQualifiedNameType(NNS, T); } + +QualType Sema::BuildTypeofExprType(Expr *E) { + return Context.getTypeOfExprType(E); +} + +QualType Sema::BuildDecltypeType(Expr *E) { + if (E->getType() == Context.OverloadTy) { + Diag(E->getLocStart(), + diag::err_cannot_determine_declared_type_of_overloaded_function); + return QualType(); + } + return Context.getDecltypeType(E); +} diff --git a/test/Analysis/array-struct.c b/test/Analysis/array-struct.c index 438e1ccf476d..da7df4b28e30 100644 --- a/test/Analysis/array-struct.c +++ b/test/Analysis/array-struct.c @@ -2,8 +2,8 @@ // RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic -analyzer-constraints=range -verify %s // RegionStore now has an infinite recursion with this test case. -// NOWORK: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && -// NOWORK: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=basic -verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -analyzer-constraints=range -verify %s struct s { int data; @@ -157,3 +157,26 @@ struct s3 p[1]; void f16(struct s3 *p) { struct s3 a = *((struct s3*) ((char*) &p[0])); } + +void inv(struct s1 *); + +// Invalidate the struct field. +void f17() { + struct s1 t; + int x; + inv(&t); + if (t.e.d) + x = 1; +} + +void read(char*); + +void f18() { + char *q; + char *p = (char *) __builtin_alloca(10); + read(p); + q = p; + q++; + if (*q) { // no-warning + } +} diff --git a/test/Analysis/concrete-address.c b/test/Analysis/concrete-address.c new file mode 100644 index 000000000000..84ebb21805a2 --- /dev/null +++ b/test/Analysis/concrete-address.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=basic --verify %s && +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region --verify %s + +void foo() { + int *p = (int*) 0x10000; // Should not crash here. + *p = 3; +} diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 205bac2c825f..ea41b5bb2f35 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -1,8 +1,7 @@ // RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=basic --verify -fblocks %s && -// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s - -// NOWORK: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s && -// NOWORK: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic -analyzer-constraints=range --verify -fblocks %s && +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s && +// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s typedef struct objc_selector *SEL; typedef signed char BOOL; @@ -285,3 +284,15 @@ int test_invalidate_by_ref() { return 0; } +// Test for <rdar://problem/7027684>. This just tests that the CFG is +// constructed correctly. Previously, the successor block of the entrance +// was the block containing the merge for '?', which would trigger an +// assertion failure. +int rdar_7027684_aux(); +int rdar_7027684_aux_2() __attribute__((noreturn)); +void rdar_7027684(int x, int y) { + {}; // this empty compound statement is critical. + (rdar_7027684_aux() ? rdar_7027684_aux_2() : (void) 0); +} + + diff --git a/test/Analysis/stack-addr-ps.c b/test/Analysis/stack-addr-ps.c index 2f7a4bdf7408..0d7a70373c9a 100644 --- a/test/Analysis/stack-addr-ps.c +++ b/test/Analysis/stack-addr-ps.c @@ -41,3 +41,19 @@ void* alloca_test() { return p; // expected-warning{{Address of stack memory}} } +int array_test(int x[2]) { + return x[0]; // no-warning +} + +struct baz { + int x; + int y[2]; +}; + +int struct_test(struct baz byVal, int flag) { + if (flag) + return byVal.x; // no-warning + else { + return byVal.y[0]; // no-warning + } +} diff --git a/test/Analysis/xfail_regionstore_wine_crash.c b/test/Analysis/xfail_regionstore_wine_crash.c index 2628d0dacf6a..af20ca2e28c2 100644 --- a/test/Analysis/xfail_regionstore_wine_crash.c +++ b/test/Analysis/xfail_regionstore_wine_crash.c @@ -1,5 +1,4 @@ -// RUN: clang-cc -checker-cfref -analyze -analyzer-store=region -verify %s -// XFAIL +// RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s // When this test passes we should put it in the misc-ps.m test file. // This test fails now because RegionStoreManager::Retrieve() does correctly diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7521a1d167bc..d5e23278729b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -8,6 +8,7 @@ set(CLANG_TEST_DIRECTORIES "Driver" "FixIt" "Frontend" + "Index" "Lexer" "Misc" "PCH" @@ -54,6 +55,6 @@ if(PYTHONINTERP_FOUND) --clang-cc=${LLVM_TOOLS_PATH}/${CMAKE_CFG_INTDIR}/clang-cc ${all_testdirs} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} - DEPENDS clang clang-cc + DEPENDS clang clang-cc index-test COMMENT "Running Clang regression tests") endif() diff --git a/test/CXX/basic/basic.def.odr/p2-typeid.cpp b/test/CXX/basic/basic.def.odr/p2-typeid.cpp index 7eb10ef52eb5..881212d74ba4 100644 --- a/test/CXX/basic/basic.def.odr/p2-typeid.cpp +++ b/test/CXX/basic/basic.def.odr/p2-typeid.cpp @@ -32,5 +32,5 @@ void test(X<Poly> xp, X<Poly, Poly&> xpr, X<NonPoly> xnp, X<NonPoly, NonPoly&> x xnpr.g(NonPoly()); // Triggers an error (as it should); - xpr.g(Poly()); + xpr.g(Poly()); // expected-note{{instantiation of member function}} } diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp new file mode 100644 index 000000000000..088a9e55eb3e --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p1.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only %s + +template<typename T> struct A { }; + +template<typename T> T make(); +template<typename T> T make2(const T&); + +void test_make() { + int& ir0 = make<int&>(); + A<int> a0 = make< A<int> >(); + A<int> a1 = make2< A<int> >(A<int>()); +} diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp new file mode 100644 index 000000000000..f4970b89f693 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3.cpp @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<class X, class Y, class Z> X f(Y,Z); + +void g() { + f<int,char*,double>("aa",3.0); + f<int,char*>("aa",3.0); // Z is deduced to be double + f<int>("aa",3.0); // Y is deduced to be char*, and + // Z is deduced to be double + f("aa",3.0); // expected-error{{no matching}} +}
\ No newline at end of file diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp new file mode 100644 index 000000000000..d193fb2ef296 --- /dev/null +++ b/test/CXX/temp/temp.fct.spec/temp.deduct/sfinae-1.cpp @@ -0,0 +1,17 @@ +// RUN: clang-cc %s + +typedef char one_byte; +struct two_bytes { char data[2]; }; + +template<typename T> one_byte __is_class_check(int T::*); +template<typename T> two_bytes __is_class_check(...); + +template<typename T> struct is_class { + static const bool value = sizeof(__is_class_check<T>(0)) == 1; +}; + +struct X { }; + +int array0[is_class<X>::value? 1 : -1]; +int array1[is_class<int>::value? -1 : 1]; +int array2[is_class<char[3]>::value? -1 : 1]; diff --git a/test/CodeGen/attributes.c b/test/CodeGen/attributes.c index a5de4f4b42a2..8f157f3d314b 100644 --- a/test/CodeGen/attributes.c +++ b/test/CodeGen/attributes.c @@ -60,7 +60,7 @@ int t17() { extern int t18 __attribute__((weak_import)); int t18 = 1; -// RUN: grep 'define i[0-9]* @t19() nounwind {' %t && +// RUN: grep 'define i[0-9]* @t19()' %t && extern int t19(void) __attribute__((weak_import)); int t19(void) { return 10; diff --git a/test/CodeGen/stack-protector.c b/test/CodeGen/stack-protector.c new file mode 100644 index 000000000000..bdac853aed62 --- /dev/null +++ b/test/CodeGen/stack-protector.c @@ -0,0 +1,22 @@ +// RUN: clang-cc -triple i686-unknown-unknown -emit-llvm -o %t %s && +// RUN: not grep 'ssp' %t && +// RUN: clang-cc -triple i686-apple-darwin9 -emit-llvm -o %t %s && +// RUN: not grep 'ssp' %t && +// RUN: clang-cc -triple i686-apple-darwin10 -emit-llvm -o %t %s && +// RUN: grep 'ssp' %t && +// RUN: clang -fstack-protector-all -emit-llvm -S -o %t %s && +// RUN: grep 'sspreq' %t && +// RUN: clang -fstack-protector -emit-llvm -S -o %t %s && +// RUN: grep 'ssp' %t && +// RUN: clang -fno-stack-protector -emit-llvm -S -o %t %s && +// RUN: not grep 'ssp' %t && +// RUN: true + +#include <stdio.h> +#include <string.h> + +void test1(const char *msg) { + char a[strlen(msg) + 1]; + strcpy(a, msg); + printf("%s\n", a); +} diff --git a/test/CodeGen/unwind-attr.c b/test/CodeGen/unwind-attr.c index b2890c4c10de..4954a0b59ce4 100644 --- a/test/CodeGen/unwind-attr.c +++ b/test/CodeGen/unwind-attr.c @@ -1,5 +1,5 @@ -// RUN: clang-cc -fexceptions -emit-llvm -o - %s | grep "@foo() {" | count 1 && -// RUN: clang-cc -emit-llvm -o - %s | grep "@foo() nounwind {" | count 1 +// RUN: clang-cc -fexceptions -emit-llvm -o - %s | grep "@foo()" | not grep nounwind && +// RUN: clang-cc -emit-llvm -o - %s | grep "@foo()" | grep nounwind int foo(void) { } diff --git a/test/CodeGenCXX/function-template-specialization.cpp b/test/CodeGenCXX/function-template-specialization.cpp new file mode 100644 index 000000000000..bea3af2bb5af --- /dev/null +++ b/test/CodeGenCXX/function-template-specialization.cpp @@ -0,0 +1,27 @@ +// RUN: clang-cc -emit-llvm %s -o %t && +template<typename T, typename U> +T* next(T* ptr, const U& diff); + +template<typename T, typename U> +T* next(T* ptr, const U& diff) { + return ptr + diff; +} + +void test(int *iptr, float *fptr, int diff) { + // FIXME: should be "_Z4nextIiiEPT_S1_RKT0_" + // RUN: grep "_Z4nextIiiEPiPiRKi" %t && + iptr = next(iptr, diff); + // FIXME: should be "_Z4nextIfiEPT_S1_RKT0_" + // RUN: grep "_Z4nextIfiEPfPfRKi" %t && + fptr = next(fptr, diff); +} + +template<typename T, typename U> +T* next(T* ptr, const U& diff); + +void test2(int *iptr, double *dptr, int diff) { + iptr = next(iptr, diff); + // FIXME: should be "_Z4nextIdiEPT_S1_RKT0_" + // RUN: grep "_Z4nextIdiEPdPdRKi" %t + dptr = next(dptr, diff); +}
\ No newline at end of file diff --git a/test/Driver/openbsd.c b/test/Driver/openbsd.c new file mode 100644 index 000000000000..fd0d4fa21cd9 --- /dev/null +++ b/test/Driver/openbsd.c @@ -0,0 +1,6 @@ +// RUN: clang -ccc-clang-archs "" -ccc-host-triple i686-pc-openbsd %s -### 2> %t.log && +// RUN: grep 'clang-cc" "-triple" "i386-pc-openbsd"' %t.log && +// RUN: grep 'as" "-o" ".*\.o" ".*\.s' %t.log && +// RUN: grep 'ld" "--eh-frame-hdr" "-dynamic-linker" ".*ld.so" "-o" "a\.out" ".*crt0.o" ".*crtbegin.o" ".*\.o" "-lc" ".*crtend.o"' %t.log && +// RUN: true + diff --git a/test/Index/comments.c b/test/Index/comments.c new file mode 100644 index 000000000000..7ad8fd7e1f49 --- /dev/null +++ b/test/Index/comments.c @@ -0,0 +1,30 @@ +// RUN: clang-cc -emit-pch -o %t.ast %s && +// RUN: index-test %t.ast -point-at %s:22:6 | grep "starts here" && +// RUN: index-test %t.ast -point-at %s:22:6 | grep "block comment" && +// RUN: index-test %t.ast -point-at %s:28:6 | grep "BCPL" && +// RUN: index-test %t.ast -point-at %s:28:6 | grep "But" && +// RUN: index-test %t.ast -point-at %s:28:6 | grep "NOT" | count 0 && +// RUN: index-test %t.ast -point-at %s:30:6 | grep "member" + + + + + + +//! It all starts here. +/*! It's a little odd to continue line this, + * + * but we need more multi-line comments. */ +/// This comment comes before my other comments +/** This is a block comment that is associated with the function f. It + * runs for three lines. + */ +void f(int, int); + +// NOT IN THE COMMENT +/// This is a BCPL comment that is associated with the function g. +/// It has only two lines. +/** But there are other blocks that are part of the comment, too. */ +void g(int); + +void h(int); ///< This is a member comment.
\ No newline at end of file diff --git a/test/PCH/pr4489.c b/test/PCH/pr4489.c new file mode 100644 index 000000000000..696da5bbb483 --- /dev/null +++ b/test/PCH/pr4489.c @@ -0,0 +1,20 @@ +// RUN: clang -x c-header -o %t.pch %s && +// RUN: clang -include %t -x c /dev/null -emit-llvm -S -o - +// PR 4489: Crash with PCH + +typedef struct _IO_FILE FILE; +extern int fprintf (struct _IO_FILE *__restrict __stream, + __const char *__restrict __format, ...); + +int x(void) +{ + switch (1) { + case 2: ; + int y = 0; + } +} + +void y(void) { + extern char z; + fprintf (0, "a"); +}
\ No newline at end of file diff --git a/test/Parser/offsetof.c b/test/Parser/offsetof.c new file mode 100644 index 000000000000..6c4e3feaa694 --- /dev/null +++ b/test/Parser/offsetof.c @@ -0,0 +1,7 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct a { struct { int b; } x[2]; }; + +int a = __builtin_offsetof(struct a, x; // expected-error{{expected ')'}} expected-note{{to match this '('}} +// FIXME: This actually shouldn't give an error +int b = __builtin_offsetof(struct a, x->b); // expected-error{{expected ')'}} expected-note{{to match this '('}} diff --git a/test/Sema/compare.c b/test/Sema/compare.c index 4b44bf5b96a0..51f77317385c 100644 --- a/test/Sema/compare.c +++ b/test/Sema/compare.c @@ -15,3 +15,17 @@ int arrays(char (*a)[5], char(*b)[10], char(*c)[5]) { int d = (a == c); return a == b; // expected-warning {{comparison of distinct pointer types}} } + +int pointers(int *a) +{ + return a > 0; // expected-warning {{ordered comparison between pointer and integer}} + return a > (void *)0; // expected-warning {{comparison of distinct pointer types}} +} + +int function_pointers(int (*a)(int), int (*b)(int)) +{ + return a > b; // expected-warning {{ordered comparison of function pointers}} + return function_pointers > function_pointers; // expected-warning {{ordered comparison of function pointers}} + return a == (void *) 0; + return a == (void *) 1; // expected-warning {{comparison of distinct pointer types}} +} diff --git a/test/Sema/ext_vector_casts.c b/test/Sema/ext_vector_casts.c index 8aa762ebcf2a..dbcd1c9b3ac0 100644 --- a/test/Sema/ext_vector_casts.c +++ b/test/Sema/ext_vector_casts.c @@ -2,6 +2,7 @@ typedef __attribute__(( ext_vector_type(2) )) float float2; typedef __attribute__(( ext_vector_type(4) )) int int4; +typedef __attribute__(( ext_vector_type(8) )) short short8; typedef __attribute__(( ext_vector_type(4) )) float float4; typedef float t3 __attribute__ ((vector_size (16))); @@ -9,8 +10,12 @@ static void test() { float2 vec2; float4 vec4, vec4_2; int4 ivec4; + short8 ish8; t3 vec4_3; + int *ptr; + int i; + vec4 = 5.0f; vec4 = (float4)5.0f; vec4 = (float4)5; vec4 = (float4)vec4_3; @@ -19,5 +24,22 @@ static void test() { ivec4 = (int4)5; ivec4 = (int4)vec4_3; + i = (int)ivec4; // expected-error {{invalid conversion between vector type 'int4' and integer type 'int' of different size}} + i = ivec4; // expected-error {{incompatible type assigning 'int4', expected 'int'}} + + ivec4 = (int4)ptr; // expected-error {{invalid conversion between vector type 'int4' and scalar type 'int *'}} + vec4 = (float4)vec2; // expected-error {{invalid conversion between ext-vector type 'float4' and 'float2'}} + + ish8 += 5; // expected-error {{can't convert between vector values of different size ('short8' and 'int')}} + ish8 += (short)5; + ivec4 *= 5; + vec4 /= 5.2f; + vec4 %= 4; // expected-error {{invalid operands to binary expression ('float4' and 'int')}} + ivec4 %= 4; + ivec4 += vec4; // expected-error {{can't convert between vector values of different size ('float4' and 'int4')}} + ivec4 += (int4)vec4; + ivec4 -= ivec4; + ivec4 |= ivec4; + ivec4 += ptr; // expected-error {{can't convert between vector values of different size ('int4' and 'int *')}} } diff --git a/test/Sema/format-attr-pr4470.c b/test/Sema/format-attr-pr4470.c new file mode 100644 index 000000000000..cba3adf1d6de --- /dev/null +++ b/test/Sema/format-attr-pr4470.c @@ -0,0 +1,11 @@ +// RUN: clang-cc -fsyntax-only -verify -Wformat=2 %s + +#include <stdio.h> + +const char *foo(const char *format) __attribute__((format_arg(1))); + +void __attribute__((format(printf, 1, 0))) +foo2(const char *fmt, va_list va) +{ + vprintf(foo(fmt), va); +} diff --git a/test/SemaCXX/class-base-member-init.cpp b/test/SemaCXX/class-base-member-init.cpp new file mode 100644 index 000000000000..c38c3d3337e7 --- /dev/null +++ b/test/SemaCXX/class-base-member-init.cpp @@ -0,0 +1,19 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +class S { +public: + S (); +}; + +struct D : S { + D() : b1(0), b2(1), b1(0), S(), S() {} // expected-error {{multiple initializations given for non-static member 'b1'}} \ + // expected-note {{previous initialization is here}} \ + // expected-error {{multiple initializations given for base 'class S'}} \ + // expected-note {{previous initialization is here}} + + int b1; + int b2; + +}; + + diff --git a/test/SemaCXX/constructor-initializer.cpp b/test/SemaCXX/constructor-initializer.cpp index d0c978a80d15..a180d907f1b7 100644 --- a/test/SemaCXX/constructor-initializer.cpp +++ b/test/SemaCXX/constructor-initializer.cpp @@ -1,6 +1,7 @@ // RUN: clang-cc -fsyntax-only -verify %s class A { int m; + A() : A::m(17) { } // expected-error {{member initializer 'm' does not name a non-static data member or base class}} }; class B : public A { @@ -54,3 +55,41 @@ class H : A { H::H() : A(10) { } + +class X {}; +class Y {}; + +struct S : Y, virtual X { + S (); +}; + +struct Z : S { + Z() : S(), X(), E() {} // expected-error {{type 'class E' is not a direct or virtual base of 'Z'}} +}; + +class U { + union { int a; char* p; }; + union { int b; double d; }; + + U() : a(1), p(0), d(1.0) {} // expected-error {{multiple initializations given for non-static member 'p'}} \ + // expected-note {{previous initialization is here}} +}; + +struct V {}; +struct Base {}; +struct Base1 {}; + +struct Derived : Base, Base1, virtual V { + Derived (); +}; + +struct Current : Derived { + int Derived; + Current() : Derived(1), ::Derived(), + ::Derived::Base(), // expected-error {{type '::Derived::Base' is not a direct or virtual base of 'Current'}} + Derived::Base1(), // expected-error {{type 'Derived::Base1' is not a direct or virtual base of 'Current'}} + Derived::V(), + ::NonExisting(), // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}} + INT::NonExisting() {} // expected-error {{expected a class or namespace}} \ + // expected-error {{member initializer 'NonExisting' does not name a non-static data member or}} +}; diff --git a/test/SemaCXX/decltype-overloaded-functions.cpp b/test/SemaCXX/decltype-overloaded-functions.cpp new file mode 100644 index 000000000000..4c5349b85868 --- /dev/null +++ b/test/SemaCXX/decltype-overloaded-functions.cpp @@ -0,0 +1,12 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +void f(); +void f(int); +decltype(f) a; // expected-error{{can't determine the declared type of an overloaded function}} + +template<typename T> struct S { + decltype(T::f) * f; // expected-error{{can't determine the declared type of an overloaded function}} +}; + +struct K { void f(); void f(int); }; +S<K> b; // expected-note{{in instantiation of template class 'struct S<struct K>' requested here}} diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp index ea02aac4915f..5eba26e70c6f 100644 --- a/test/SemaCXX/exception-spec.cpp +++ b/test/SemaCXX/exception-spec.cpp @@ -1,4 +1,4 @@ -// RUN: clang-cc -fsyntax-only -verify %s +// RUN: clang-cc -fsyntax-only -verify -fms-extensions %s // Straight from the standard: // Plain function with spec @@ -33,3 +33,31 @@ void ic2() throw(Incomplete); // expected-error {{incomplete type 'struct Incomp void ic3() throw(void*); void ic4() throw(Incomplete*); // expected-error {{pointer to incomplete type 'struct Incomplete' is not allowed in exception specification}} void ic5() throw(Incomplete&); // expected-error {{reference to incomplete type 'struct Incomplete' is not allowed in exception specification}} + +// Redeclarations +typedef int INT; +void r1() throw(int); +void r1() throw(int); + +void r2() throw(int); +void r2() throw(INT); + +// throw-any spec and no spec at all are semantically equivalent +void r3(); +void r3() throw(...); + +void r4() throw(int, float); +void r4() throw(float, int); + +void r5() throw(int); // expected-note {{previous declaration}} +void r5(); // expected-error {{exception specification in declaration does not match}} + +void r6() throw(...); // expected-note {{previous declaration}} +void r6() throw(int); // expected-error {{exception specification in declaration does not match}} + +void r7() throw(int); // expected-note {{previous declaration}} +void r7() throw(float); // expected-error {{exception specification in declaration does not match}} + +// Top-level const doesn't matter. +void r8() throw(int); +void r8() throw(const int); diff --git a/test/SemaCXX/member-pointer.cpp b/test/SemaCXX/member-pointer.cpp index d2df5eb317a0..3b106d5576fe 100644 --- a/test/SemaCXX/member-pointer.cpp +++ b/test/SemaCXX/member-pointer.cpp @@ -16,7 +16,7 @@ int B::*pbi; // expected-error {{expected a class or namespace}} \ // expected-error{{does not point into a class}} int C::*pci; // expected-error {{'pci' does not point into a class}} void A::*pdv; // expected-error {{'pdv' declared as a member pointer to void}} -int& A::*pdr; // expected-error {{'pdr' declared as a pointer to a reference}} +int& A::*pdr; // expected-error {{'pdr' declared as a member pointer to a reference}} void f() { // This requires tentative parsing. diff --git a/test/SemaTemplate/class-template-ctor-initializer.cpp b/test/SemaTemplate/class-template-ctor-initializer.cpp new file mode 100644 index 000000000000..d7649f52688d --- /dev/null +++ b/test/SemaTemplate/class-template-ctor-initializer.cpp @@ -0,0 +1,33 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<class X> struct A {}; + +template<class X> struct B : A<X> { + B() : A<X>() {} +}; +B<int> x; + +template<class X> struct B1 : A<X> { + typedef A<X> Base; + B1() : Base() {} +}; +B1<int> x1; + + +template<typename T> struct Tmpl { }; + +template<typename T> struct TmplB { }; + +struct TmplC : Tmpl<int> { + TmplC() : + Tmpl<int>(), + TmplB<int>() { } // expected-error {{type 'TmplB<int>' is not a direct or virtual base of 'TmplC'}} +}; + + +struct TmplD : Tmpl<char>, TmplB<char> { + TmplD(): + Tmpl<int>(), // expected-error {{type 'Tmpl<int>' is not a direct or virtual base of 'TmplD'}} + TmplB<char>() {} +}; + diff --git a/test/SemaTemplate/operator-template.cpp b/test/SemaTemplate/operator-template.cpp index 3d041ec13a32..7039e0ec83de 100644 --- a/test/SemaTemplate/operator-template.cpp +++ b/test/SemaTemplate/operator-template.cpp @@ -5,10 +5,12 @@ template<class X>struct A{typedef X Y;}; template<class X>bool operator==(A<X>,typename A<X>::Y); int a(A<int> x) { return operator==(x,1); } -// FIXME: The diagnostic here is a bit messed up +int a0(A<int> x) { return x == 1; } + +// FIXME: the location information for the note isn't very good template<class X>struct B{typedef X Y;}; template<class X>bool operator==(B<X>*,typename B<X>::Y); // \ expected-error{{overloaded 'operator==' must have at least one parameter of class or enumeration type}} \ -expected-note{{in instantiation of default argument for 'operator==<int>' required here}} +expected-note{{in instantiation of member function}} int a(B<int> x) { return operator==(&x,1); } diff --git a/test/SemaTemplate/recursive-template-instantiation.cpp b/test/SemaTemplate/recursive-template-instantiation.cpp new file mode 100644 index 000000000000..7c88d5019fd5 --- /dev/null +++ b/test/SemaTemplate/recursive-template-instantiation.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> void f(T* t) { + f(*t); // expected-error{{no matching function}}\ + // expected-note 3{{requested here}} +} + +void test_f(int ****p) { + f(p); // expected-note{{requested here}} +} diff --git a/test/cxx-sections.data b/test/cxx-sections.data index b4501ea286ca..0edc5f150846 100644 --- a/test/cxx-sections.data +++ b/test/cxx-sections.data @@ -26,40 +26,43 @@ 1.10 [intro.multithread] 1.11 [intro.ack] 2 [lex] - 2.1 [lex.phases] - 2.2 [lex.charset] - 2.3 [lex.trigraph] - 2.4 [lex.pptoken] - 2.5 [lex.digraph] - 2.6 [lex.token] - 2.7 [lex.comment] - 2.8 [lex.header] - 2.9 [lex.ppnumber] - 2.10 [lex.name] - 2.11 [lex.key] - 2.12 [lex.operators] - 2.13 [lex.literal] - 2.13.1 [lex.icon] - 2.13.2 [lex.ccon] - 2.13.3 [lex.fcon] - 2.13.4 [lex.string] - 2.13.5 [lex.bool] - 2.13.6 [lex.nullptr] - 2.13.7 [lex.ext] + 2.1 [lex.separate] + 2.2 [lex.phases] + 2.3 [lex.charset] + 2.4 [lex.trigraph] + 2.5 [lex.pptoken] + 2.6 [lex.digraph] + 2.7 [lex.token] + 2.8 [lex.comment] + 2.9 [lex.header] + 2.10 [lex.ppnumber] + 2.11 [lex.name] + 2.12 [lex.key] + 2.13 [lex.operators] + 2.14 [lex.literal] + 2.14.1 [lex.literal.kinds] + 2.14.2 [lex.icon] + 2.14.3 [lex.ccon] + 2.14.4 [lex.fcon] + 2.14.5 [lex.string] + 2.14.6 [lex.bool] + 2.14.7 [lex.nullptr] + 2.14.8 [lex.ext] 3 [basic] 3.1 [basic.def] 3.2 [basic.def.odr] 3.3 [basic.scope] - 3.3.1 [basic.scope.pdecl] - 3.3.2 [basic.scope.local] - 3.3.3 [basic.scope.proto] - 3.3.4 [basic.funscope] - 3.3.5 [basic.scope.namespace] - 3.3.6 [basic.scope.class] - 3.3.7 [basic.scope.concept] - 3.3.8 [basic.scope.req] - 3.3.9 [basic.scope.enum] - 3.3.10 [basic.scope.hiding] + 3.3.1 [basic.scope.declarative] + 3.3.2 [basic.scope.pdecl] + 3.3.3 [basic.scope.local] + 3.3.4 [basic.scope.proto] + 3.3.5 [basic.funscope] + 3.3.6 [basic.scope.namespace] + 3.3.7 [basic.scope.class] + 3.3.8 [basic.scope.concept] + 3.3.9 [basic.scope.req] + 3.3.10 [basic.scope.enum] + 3.3.11 [basic.scope.hiding] 3.4 [basic.lookup] 3.4.1 [basic.lookup.unqual] 3.4.2 [basic.lookup.argdep] @@ -107,7 +110,8 @@ 4.13 [conv.rank] 5 [expr] 5.1 [expr.prim] - 5.1.1 [expr.prim.lambda] + 5.1.1 [expr.prim.general] + 5.1.2 [expr.prim.lambda] 5.2 [expr.post] 5.2.1 [expr.sub] 5.2.2 [expr.call] @@ -284,76 +288,77 @@ 13.5.8 [over.literal] 13.6 [over.built] 14 [temp] - 14.1 [temp.param] - 14.2 [temp.names] - 14.3 [temp.arg] - 14.3.1 [temp.arg.type] - 14.3.2 [temp.arg.nontype] - 14.3.3 [temp.arg.template] - 14.4 [temp.type] - 14.5 [temp.decls] - 14.5.1 [temp.class] - 14.5.1.1 [temp.mem.func] - 14.5.1.2 [temp.mem.class] - 14.5.1.3 [temp.static] - 14.5.2 [temp.mem] - 14.5.3 [temp.variadic] - 14.5.4 [temp.friend] - 14.5.5 [temp.class.spec] - 14.5.5.1 [temp.class.spec.match] - 14.5.5.2 [temp.class.order] - 14.5.5.3 [temp.class.spec.mfunc] - 14.5.6 [temp.fct] - 14.5.6.1 [temp.over.link] - 14.5.6.2 [temp.func.order] - 14.5.7 [temp.alias] - 14.5.8 [temp.concept.map] - 14.6 [temp.res] - 14.6.1 [temp.local] - 14.6.2 [temp.dep] - 14.6.2.1 [temp.dep.type] - 14.6.2.2 [temp.dep.expr] - 14.6.2.3 [temp.dep.constexpr] - 14.6.2.4 [temp.dep.temp] - 14.6.3 [temp.nondep] - 14.6.4 [temp.dep.res] - 14.6.4.1 [temp.point] - 14.6.4.2 [temp.dep.candidate] - 14.6.5 [temp.inject] - 14.7 [temp.spec] - 14.7.1 [temp.inst] - 14.7.2 [temp.explicit] - 14.7.3 [temp.expl.spec] - 14.8 [temp.fct.spec] - 14.8.1 [temp.arg.explicit] - 14.8.2 [temp.deduct] - 14.8.2.1 [temp.deduct.call] - 14.8.2.2 [temp.deduct.funcaddr] - 14.8.2.3 [temp.deduct.conv] - 14.8.2.4 [temp.deduct.partial] - 14.8.2.5 [temp.deduct.type] - 14.8.3 [temp.over] - 14.9 [concept] - 14.9.1 [concept.def] - 14.9.1.1 [concept.fct] - 14.9.1.2 [concept.assoc] - 14.9.1.3 [concept.req] - 14.9.1.4 [concept.axiom] - 14.9.2 [concept.map] - 14.9.2.1 [concept.map.fct] - 14.9.2.2 [concept.map.assoc] - 14.9.3 [concept.refine] - 14.9.3.1 [concept.member.lookup] - 14.9.3.2 [concept.refine.maps] - 14.9.4 [concept.support] - 14.10 [temp.constrained] - 14.10.1 [temp.req] - 14.10.1.1 [temp.req.sat] - 14.10.1.2 [temp.req.impl] - 14.10.2 [temp.archetype] - 14.10.2.1 [temp.archetype.assemble] - 14.10.3 [temp.constrained.set] - 14.10.4 [temp.constrained.inst] + 14.1 [temp.export] + 14.2 [temp.param] + 14.3 [temp.names] + 14.4 [temp.arg] + 14.4.1 [temp.arg.type] + 14.4.2 [temp.arg.nontype] + 14.4.3 [temp.arg.template] + 14.5 [temp.type] + 14.6 [temp.decls] + 14.6.1 [temp.class] + 14.6.1.1 [temp.mem.func] + 14.6.1.2 [temp.mem.class] + 14.6.1.3 [temp.static] + 14.6.2 [temp.mem] + 14.6.3 [temp.variadic] + 14.6.4 [temp.friend] + 14.6.5 [temp.class.spec] + 14.6.5.1 [temp.class.spec.match] + 14.6.5.2 [temp.class.order] + 14.6.5.3 [temp.class.spec.mfunc] + 14.6.6 [temp.fct] + 14.6.6.1 [temp.over.link] + 14.6.6.2 [temp.func.order] + 14.6.7 [temp.alias] + 14.6.8 [temp.concept.map] + 14.7 [temp.res] + 14.7.1 [temp.local] + 14.7.2 [temp.dep] + 14.7.2.1 [temp.dep.type] + 14.7.2.2 [temp.dep.expr] + 14.7.2.3 [temp.dep.constexpr] + 14.7.2.4 [temp.dep.temp] + 14.7.3 [temp.nondep] + 14.7.4 [temp.dep.res] + 14.7.4.1 [temp.point] + 14.7.4.2 [temp.dep.candidate] + 14.7.5 [temp.inject] + 14.8 [temp.spec] + 14.8.1 [temp.inst] + 14.8.2 [temp.explicit] + 14.8.3 [temp.expl.spec] + 14.9 [temp.fct.spec] + 14.9.1 [temp.arg.explicit] + 14.9.2 [temp.deduct] + 14.9.2.1 [temp.deduct.call] + 14.9.2.2 [temp.deduct.funcaddr] + 14.9.2.3 [temp.deduct.conv] + 14.9.2.4 [temp.deduct.partial] + 14.9.2.5 [temp.deduct.type] + 14.9.3 [temp.over] + 14.10 [concept] + 14.10.1 [concept.def] + 14.10.1.1 [concept.fct] + 14.10.1.2 [concept.assoc] + 14.10.1.3 [concept.req] + 14.10.1.4 [concept.axiom] + 14.10.2 [concept.map] + 14.10.2.1 [concept.map.fct] + 14.10.2.2 [concept.map.assoc] + 14.10.3 [concept.refine] + 14.10.3.1 [concept.member.lookup] + 14.10.3.2 [concept.refine.maps] + 14.10.4 [concept.support] + 14.11 [temp.constrained] + 14.11.1 [temp.req] + 14.11.1.1 [temp.req.sat] + 14.11.1.2 [temp.req.impl] + 14.11.2 [temp.archetype] + 14.11.2.1 [temp.archetype.assemble] + 14.11.3 [temp.constrained.set] + 14.11.4 [temp.constrained.inst] 15 [except] 15.1 [except.throw] 15.2 [except.ctor] @@ -363,7 +368,6 @@ 15.5.1 [except.terminate] 15.5.2 [except.unexpected] 15.5.3 [except.uncaught] - 15.6 [except.access] 16 [cpp] 16.1 [cpp.cond] 16.2 [cpp.include] @@ -381,7 +385,7 @@ 16.9 [cpp.pragma.op] 17 [library] 17.1 [library.general] - 17.2 [library.overview] + 17.2 [library.c] 17.3 [definitions] 17.3.1 [defns.arbitrary.stream] 17.3.2 [defns.blocked] @@ -394,191 +398,187 @@ 17.3.9 [defns.handler] 17.3.10 [defns.iostream.templates] 17.3.11 [defns.modifier] - 17.3.12 [defns.obj.state] - 17.3.13 [defns.ntcts] - 17.3.14 [defns.narrow.iostream] - 17.3.15 [defns.observer] - 17.3.16 [defns.replacement] - 17.3.17 [defns.repositional.stream] - 17.3.18 [defns.required.behavior] - 17.3.19 [defns.reserved.function] - 17.3.20 [defns.stable] - 17.3.21 [defns.traits] - 17.3.22 [defns.wide.iostream] + 17.3.12 [defns.move.assign] + 17.3.13 [defns.move.assign.op] + 17.3.14 [defns.move.ctor] + 17.3.15 [defns.obj.state] + 17.3.16 [defns.ntcts] + 17.3.17 [defns.observer] + 17.3.18 [defns.replacement] + 17.3.19 [defns.repositional.stream] + 17.3.20 [defns.required.behavior] + 17.3.21 [defns.reserved.function] + 17.3.22 [defns.stable] + 17.3.23 [defns.traits] 17.4 [defns.additional] 17.5 [description] - 17.5.1 [description.general] - 17.5.2 [structure] - 17.5.2.1 [structure.elements] - 17.5.2.2 [structure.summary] - 17.5.2.3 [structure.requirements] - 17.5.2.4 [structure.specifications] - 17.5.2.5 [structure.see.also] - 17.5.3 [conventions] - 17.5.3.1 [conventions.general] - 17.5.3.2 [type.descriptions] - 17.5.3.2.1 [type.descriptions.general] - 17.5.3.2.2 [enumerated.types] - 17.5.3.2.3 [bitmask.types] - 17.5.3.2.4 [character.seq] - 17.5.3.2.4.1 [character.seq.general] - 17.5.3.2.4.2 [byte.strings] - 17.5.3.2.4.3 [multibyte.strings] - 17.5.3.2.4.4 [char16_t.seq] - 17.5.3.2.4.5 [char32_t.seq] - 17.5.3.2.4.6 [wide.characters] - 17.5.3.3 [functions.within.classes] - 17.5.3.4 [objects.within.classes] + 17.5.1 [structure] + 17.5.1.1 [structure.elements] + 17.5.1.2 [structure.summary] + 17.5.1.3 [structure.requirements] + 17.5.1.4 [structure.specifications] + 17.5.1.5 [structure.see.also] + 17.5.2 [conventions] + 17.5.2.1 [type.descriptions] + 17.5.2.1.1 [type.descriptions.general] + 17.5.2.1.2 [enumerated.types] + 17.5.2.1.3 [bitmask.types] + 17.5.2.1.4 [character.seq] + 17.5.2.1.4.1 [byte.strings] + 17.5.2.1.4.2 [multibyte.strings] + 17.5.2.1.4.3 [char16_t.seq] + 17.5.2.1.4.4 [char32_t.seq] + 17.5.2.1.4.5 [wide.characters] + 17.5.2.2 [functions.within.classes] + 17.5.2.3 [objects.within.classes] 17.6 [requirements] - 17.6.1 [requirements.general] - 17.6.2 [organization] - 17.6.2.1 [organization.general] - 17.6.2.2 [contents] - 17.6.2.3 [headers] - 17.6.2.4 [compliance] - 17.6.3 [using] - 17.6.3.1 [using.overview] - 17.6.3.2 [using.headers] - 17.6.3.3 [using.linkage] - 17.6.4 [constraints] - 17.6.4.1 [constraints.overview] - 17.6.4.2 [namespace.constraints] - 17.6.4.2.1 [namespace.std] - 17.6.4.2.2 [namespace.posix] - 17.6.4.3 [reserved.names] - 17.6.4.3.1 [reserved.names.general] - 17.6.4.3.2 [macro.names] - 17.6.4.3.3 [global.names] - 17.6.4.3.4 [extern.names] - 17.6.4.3.5 [extern.types] - 17.6.4.3.6 [usrlit.suffix] - 17.6.4.4 [alt.headers] - 17.6.4.5 [derived.classes] - 17.6.4.6 [replacement.functions] - 17.6.4.7 [handler.functions] - 17.6.4.8 [res.on.functions] - 17.6.4.9 [res.on.arguments] - 17.6.4.10 [res.on.objects] - 17.6.4.11 [res.on.required] - 17.6.5 [conforming] - 17.6.5.1 [conforming.overview] - 17.6.5.2 [res.on.headers] - 17.6.5.3 [res.on.macro.definitions] - 17.6.5.4 [global.functions] - 17.6.5.5 [member.functions] - 17.6.5.6 [reentrancy] - 17.6.5.7 [res.on.data.races] - 17.6.5.8 [protection.within.classes] - 17.6.5.9 [derivation] - 17.6.5.10 [res.on.exception.handling] - 17.6.5.11 [res.on.pointer.storage] - 17.6.5.12 [value.error.codes] + 17.6.1 [organization] + 17.6.1.1 [contents] + 17.6.1.2 [headers] + 17.6.1.3 [compliance] + 17.6.2 [using] + 17.6.2.1 [using.overview] + 17.6.2.2 [using.headers] + 17.6.2.3 [using.linkage] + 17.6.3 [constraints] + 17.6.3.1 [constraints.overview] + 17.6.3.2 [namespace.constraints] + 17.6.3.2.1 [namespace.std] + 17.6.3.2.2 [namespace.posix] + 17.6.3.3 [reserved.names] + 17.6.3.3.1 [macro.names] + 17.6.3.3.2 [global.names] + 17.6.3.3.3 [extern.names] + 17.6.3.3.4 [extern.types] + 17.6.3.3.5 [usrlit.suffix] + 17.6.3.4 [alt.headers] + 17.6.3.5 [derived.classes] + 17.6.3.6 [replacement.functions] + 17.6.3.7 [handler.functions] + 17.6.3.8 [res.on.functions] + 17.6.3.9 [res.on.arguments] + 17.6.3.10 [res.on.objects] + 17.6.3.11 [res.on.required] + 17.6.4 [conforming] + 17.6.4.1 [conforming.overview] + 17.6.4.2 [res.on.headers] + 17.6.4.3 [res.on.macro.definitions] + 17.6.4.4 [global.functions] + 17.6.4.5 [member.functions] + 17.6.4.6 [reentrancy] + 17.6.4.7 [res.on.data.races] + 17.6.4.8 [protection.within.classes] + 17.6.4.9 [derivation] + 17.6.4.10 [res.on.exception.handling] + 17.6.4.11 [res.on.pointer.storage] + 17.6.4.12 [value.error.codes] 18 [language.support] - 18.1 [support.types] - 18.2 [support.limits] - 18.2.1 [limits] - 18.2.1.1 [numeric.limits] - 18.2.1.2 [numeric.limits.members] - 18.2.1.3 [round.style] - 18.2.1.4 [denorm.style] - 18.2.1.5 [numeric.special] - 18.2.2 [c.limits] - 18.3 [cstdint] - 18.3.1 [cstdint.syn] - 18.3.2 [stdinth] - 18.4 [support.start.term] - 18.5 [support.dynamic] - 18.5.1 [new.delete] - 18.5.1.1 [new.delete.single] - 18.5.1.2 [new.delete.array] - 18.5.1.3 [new.delete.placement] - 18.5.1.4 [new.delete.dataraces] - 18.5.2 [alloc.errors] - 18.5.2.1 [bad.alloc] - 18.5.2.2 [new.handler] - 18.5.2.3 [set.new.handler] - 18.6 [support.rtti] - 18.6.1 [type.info] - 18.6.2 [type.index] - 18.6.2.1 [type.index.overview] - 18.6.2.2 [type.index.members] - 18.6.2.3 [type.index.templ] - 18.6.3 [bad.cast] - 18.6.4 [bad.typeid] - 18.7 [support.exception] - 18.7.1 [exception] - 18.7.2 [exception.unexpected] - 18.7.2.1 [bad.exception] - 18.7.2.2 [unexpected.handler] - 18.7.2.3 [set.unexpected] - 18.7.2.4 [unexpected] - 18.7.3 [exception.terminate] - 18.7.3.1 [terminate.handler] - 18.7.3.2 [set.terminate] - 18.7.3.3 [terminate] - 18.7.4 [uncaught] - 18.7.5 [propagation] - 18.7.6 [except.nested] - 18.8 [support.initlist] - 18.8.1 [support.initlist.cons] - 18.8.2 [support.initlist.access] - 18.8.3 [support.initlist.concept] - 18.9 [support.runtime] + 18.1 [support.general] + 18.2 [support.types] + 18.3 [support.limits] + 18.3.1 [limits] + 18.3.1.1 [numeric.limits] + 18.3.1.2 [numeric.limits.members] + 18.3.1.3 [round.style] + 18.3.1.4 [denorm.style] + 18.3.1.5 [numeric.special] + 18.3.2 [c.limits] + 18.4 [cstdint] + 18.4.1 [cstdint.syn] + 18.4.2 [stdinth] + 18.5 [support.start.term] + 18.6 [support.dynamic] + 18.6.1 [new.delete] + 18.6.1.1 [new.delete.single] + 18.6.1.2 [new.delete.array] + 18.6.1.3 [new.delete.placement] + 18.6.1.4 [new.delete.dataraces] + 18.6.2 [alloc.errors] + 18.6.2.1 [bad.alloc] + 18.6.2.2 [new.handler] + 18.6.2.3 [set.new.handler] + 18.7 [support.rtti] + 18.7.1 [type.info] + 18.7.2 [type.index] + 18.7.2.1 [type.index.overview] + 18.7.2.2 [type.index.members] + 18.7.2.3 [type.index.templ] + 18.7.3 [bad.cast] + 18.7.4 [bad.typeid] + 18.8 [support.exception] + 18.8.1 [exception] + 18.8.2 [exception.unexpected] + 18.8.2.1 [bad.exception] + 18.8.2.2 [unexpected.handler] + 18.8.2.3 [set.unexpected] + 18.8.2.4 [unexpected] + 18.8.3 [exception.terminate] + 18.8.3.1 [terminate.handler] + 18.8.3.2 [set.terminate] + 18.8.3.3 [terminate] + 18.8.4 [uncaught] + 18.8.5 [propagation] + 18.8.6 [except.nested] + 18.9 [support.initlist] + 18.9.1 [support.initlist.cons] + 18.9.2 [support.initlist.access] + 18.9.3 [support.initlist.concept] + 18.10 [support.runtime] 19 [diagnostics] - 19.1 [std.exceptions] - 19.1.1 [logic.error] - 19.1.2 [domain.error] - 19.1.3 [invalid.argument] - 19.1.4 [length.error] - 19.1.5 [out.of.range] - 19.1.6 [runtime.error] - 19.1.7 [range.error] - 19.1.8 [overflow.error] - 19.1.9 [underflow.error] - 19.2 [assertions] - 19.3 [errno] - 19.4 [syserr] - 19.4.1 [syserr.errcat] - 19.4.1.1 [syserr.errcat.overview] - 19.4.1.2 [syserr.errcat.virtuals] - 19.4.1.3 [syserr.errcat.nonvirtuals] - 19.4.1.4 [syserr.errcat.derived] - 19.4.1.5 [syserr.errcat.objects] - 19.4.2 [syserr.errcode] - 19.4.2.1 [syserr.errcodeenum] - 19.4.2.2 [syserr.errcode.overview] - 19.4.2.3 [syserr.errcode.constructors] - 19.4.2.4 [syserr.errcode.modifiers] - 19.4.2.5 [syserr.errcode.observers] - 19.4.2.6 [syserr.errcode.nonmembers] - 19.4.3 [syserr.errcondition] - 19.4.3.1 [syserr.errcondenum] - 19.4.3.2 [syserr.errcondition.overview] - 19.4.3.3 [syserr.errcondition.constructors] - 19.4.3.4 [syserr.errcondition.modifiers] - 19.4.3.5 [syserr.errcondition.observers] - 19.4.3.6 [syserr.errcondition.nonmembers] - 19.4.4 [syserr.compare] - 19.4.5 [syserr.syserr] - 19.4.5.1 [syserr.syserr.overview] - 19.4.5.2 [syserr.syserr.members] + 19.1 [diagnostics.general] + 19.2 [std.exceptions] + 19.2.1 [logic.error] + 19.2.2 [domain.error] + 19.2.3 [invalid.argument] + 19.2.4 [length.error] + 19.2.5 [out.of.range] + 19.2.6 [runtime.error] + 19.2.7 [range.error] + 19.2.8 [overflow.error] + 19.2.9 [underflow.error] + 19.3 [assertions] + 19.4 [errno] + 19.5 [syserr] + 19.5.1 [syserr.errcat] + 19.5.1.1 [syserr.errcat.overview] + 19.5.1.2 [syserr.errcat.virtuals] + 19.5.1.3 [syserr.errcat.nonvirtuals] + 19.5.1.4 [syserr.errcat.derived] + 19.5.1.5 [syserr.errcat.objects] + 19.5.2 [syserr.errcode] + 19.5.2.1 [syserr.errcodeenum] + 19.5.2.2 [syserr.errcode.overview] + 19.5.2.3 [syserr.errcode.constructors] + 19.5.2.4 [syserr.errcode.modifiers] + 19.5.2.5 [syserr.errcode.observers] + 19.5.2.6 [syserr.errcode.nonmembers] + 19.5.3 [syserr.errcondition] + 19.5.3.1 [syserr.errcondenum] + 19.5.3.2 [syserr.errcondition.overview] + 19.5.3.3 [syserr.errcondition.constructors] + 19.5.3.4 [syserr.errcondition.modifiers] + 19.5.3.5 [syserr.errcondition.observers] + 19.5.3.6 [syserr.errcondition.nonmembers] + 19.5.4 [syserr.compare] + 19.5.5 [syserr.syserr] + 19.5.5.1 [syserr.syserr.overview] + 19.5.5.2 [syserr.syserr.members] 20 [utilities] - 20.1 [utility.requirements] - 20.1.1 [utility.arg.requirements] - 20.1.2 [allocator.requirements] + 20.1 [utilities.general] 20.2 [utility.concepts] 20.2.1 [concept.transform] 20.2.2 [concept.true] - 20.2.3 [concept.operator] - 20.2.4 [concept.predicate] - 20.2.5 [concept.comparison] - 20.2.6 [concept.construct] - 20.2.7 [concept.destruct] - 20.2.8 [concept.copymove] - 20.2.9 [concept.memory] - 20.2.10 [concept.regular] - 20.2.11 [concept.convertible] - 20.2.12 [concept.arithmetic] + 20.2.3 [concept.classify] + 20.2.4 [concept.operator] + 20.2.5 [concept.predicate] + 20.2.6 [concept.comparison] + 20.2.7 [concept.construct] + 20.2.8 [concept.destruct] + 20.2.9 [concept.copymove] + 20.2.10 [concept.memory] + 20.2.11 [concept.regular] + 20.2.12 [concept.convertible] + 20.2.13 [concept.arithmetic] 20.3 [utility] 20.3.1 [operators] 20.3.2 [forward] @@ -597,15 +597,14 @@ 20.5 [tuple] 20.5.1 [tuple.general] 20.5.2 [tuple.tuple] - 20.5.2.1 [tuple.traits] - 20.5.2.2 [tuple.cnstr] - 20.5.2.3 [tuple.creation] - 20.5.2.4 [tuple.helper] - 20.5.2.5 [tuple.elem] - 20.5.2.6 [tuple.rel] - 20.5.2.7 [tuple.swap] - 20.5.2.8 [tuple.special] - 20.5.2.9 [tuple.concepts] + 20.5.2.1 [tuple.cnstr] + 20.5.2.2 [tuple.creation] + 20.5.2.3 [tuple.helper] + 20.5.2.4 [tuple.elem] + 20.5.2.5 [tuple.rel] + 20.5.2.6 [tuple.swap] + 20.5.2.7 [tuple.special] + 20.5.2.8 [tuple.concepts] 20.6 [meta] 20.6.1 [meta.rqmts] 20.6.2 [meta.type.synop] @@ -660,79 +659,72 @@ 20.7.16.2.6 [func.wrap.func.nullptr] 20.7.16.2.7 [func.wrap.func.alg] 20.7.17 [unord.hash] - 20.7.18 [func.referenceclosure] - 20.7.18.1 [func.referenceclosure.cons] - 20.7.18.2 [func.referenceclosure.obs] - 20.7.18.3 [func.referenceclosure.invoke] - 20.7.18.4 [func.referenceclosure.compare] 20.8 [memory] 20.8.1 [allocator.tag] 20.8.2 [allocator] 20.8.2.1 [allocator.general] 20.8.2.2 [allocator.concepts] + 20.8.2.3 [allocator.concepts.legacy] + 20.8.2.4 [allocator.concepts.members] 20.8.3 [allocator.element.concepts] - 20.8.4 [allocator.propagation] - 20.8.5 [allocator.propagation.map] - 20.8.6 [default.allocator] - 20.8.6.1 [allocator.members] - 20.8.6.2 [allocator.globals] - 20.8.7 [allocator.adaptor] - 20.8.7.1 [allocator.adaptor.cntr] - 20.8.7.2 [allocator.adaptor.members] - 20.8.7.3 [allocator.adaptor.globals] - 20.8.8 [storage.iterator] - 20.8.9 [temporary.buffer] - 20.8.10 [construct.element] - 20.8.11 [specialized.algorithms] - 20.8.11.1 [object.addressof] - 20.8.11.2 [uninitialized.copy] - 20.8.11.3 [uninitialized.fill] - 20.8.11.4 [uninitialized.fill.n] - 20.8.12 [unique.ptr] - 20.8.12.1 [unique.ptr.dltr] - 20.8.12.1.1 [unique.ptr.dltr.dflt] - 20.8.12.1.2 [unique.ptr.dltr.dflt1] - 20.8.12.1.3 [unique.ptr.dltr.dflt2] - 20.8.12.2 [unique.ptr.single] - 20.8.12.2.1 [unique.ptr.single.ctor] - 20.8.12.2.2 [unique.ptr.single.dtor] - 20.8.12.2.3 [unique.ptr.single.asgn] - 20.8.12.2.4 [unique.ptr.single.observers] - 20.8.12.2.5 [unique.ptr.single.modifiers] - 20.8.12.3 [unique.ptr.runtime] - 20.8.12.3.1 [unique.ptr.runtime.ctor] - 20.8.12.3.2 [unique.ptr.runtime.observers] - 20.8.12.3.3 [unique.ptr.runtime.modifiers] - X [unique.ptr.compiletime] - 20.8.12.4 [unique.ptr.special] - 20.8.13 [util.smartptr] - 20.8.13.1 [util.smartptr.weakptr] - 20.8.13.2 [util.smartptr.shared] - 20.8.13.2.1 [util.smartptr.shared.const] - 20.8.13.2.2 [util.smartptr.shared.dest] - 20.8.13.2.3 [util.smartptr.shared.assign] - 20.8.13.2.4 [util.smartptr.shared.mod] - 20.8.13.2.5 [util.smartptr.shared.obs] - 20.8.13.2.6 [util.smartptr.shared.create] - 20.8.13.2.7 [util.smartptr.shared.cmp] - 20.8.13.2.8 [util.smartptr.shared.io] - 20.8.13.2.9 [util.smartptr.shared.spec] - 20.8.13.2.10 [util.smartptr.shared.cast] - 20.8.13.2.11 [util.smartptr.getdeleter] - 20.8.13.3 [util.smartptr.weak] - 20.8.13.3.1 [util.smartptr.weak.const] - 20.8.13.3.2 [util.smartptr.weak.dest] - 20.8.13.3.3 [util.smartptr.weak.assign] - 20.8.13.3.4 [util.smartptr.weak.mod] - 20.8.13.3.5 [util.smartptr.weak.obs] - 20.8.13.3.6 [util.smartptr.weak.cmp] - 20.8.13.3.7 [util.smartptr.weak.spec] - 20.8.13.4 [util.smartptr.ownerless] - 20.8.13.5 [util.smartptr.enab] - 20.8.13.6 [util.smartptr.shared.atomic] - 20.8.13.7 [util.dynamic.safety] - 20.8.14 [ptr.align] - 20.8.15 [c.malloc] + 20.8.4 [default.allocator] + 20.8.4.1 [allocator.members] + 20.8.4.2 [allocator.globals] + 20.8.5 [allocator.adaptor] + 20.8.5.1 [allocator.adaptor.base] + 20.8.5.2 [allocator.adaptor.cntr] + 20.8.5.3 [allocator.adaptor2.cntr] + 20.8.5.4 [allocator.adaptor.members] + 20.8.5.5 [allocator.adaptor.globals] + 20.8.6 [storage.iterator] + 20.8.7 [temporary.buffer] + 20.8.8 [specialized.algorithms] + 20.8.8.1 [object.addressof] + 20.8.8.2 [uninitialized.copy] + 20.8.8.3 [uninitialized.fill] + 20.8.8.4 [uninitialized.fill.n] + 20.8.9 [unique.ptr] + 20.8.9.1 [unique.ptr.dltr] + 20.8.9.1.1 [unique.ptr.dltr.dflt] + 20.8.9.1.2 [unique.ptr.dltr.dflt1] + 20.8.9.2 [unique.ptr.single] + 20.8.9.2.1 [unique.ptr.single.ctor] + 20.8.9.2.2 [unique.ptr.single.dtor] + 20.8.9.2.3 [unique.ptr.single.asgn] + 20.8.9.2.4 [unique.ptr.single.observers] + 20.8.9.2.5 [unique.ptr.single.modifiers] + 20.8.9.3 [unique.ptr.runtime] + 20.8.9.3.1 [unique.ptr.runtime.ctor] + 20.8.9.3.2 [unique.ptr.runtime.observers] + 20.8.9.3.3 [unique.ptr.runtime.modifiers] + 20.8.9.4 [unique.ptr.special] + 20.8.10 [util.smartptr] + 20.8.10.1 [util.smartptr.weakptr] + 20.8.10.2 [util.smartptr.shared] + 20.8.10.2.1 [util.smartptr.shared.const] + 20.8.10.2.2 [util.smartptr.shared.dest] + 20.8.10.2.3 [util.smartptr.shared.assign] + 20.8.10.2.4 [util.smartptr.shared.mod] + 20.8.10.2.5 [util.smartptr.shared.obs] + 20.8.10.2.6 [util.smartptr.shared.create] + 20.8.10.2.7 [util.smartptr.shared.cmp] + 20.8.10.2.8 [util.smartptr.shared.io] + 20.8.10.2.9 [util.smartptr.shared.spec] + 20.8.10.2.10 [util.smartptr.shared.cast] + 20.8.10.2.11 [util.smartptr.getdeleter] + 20.8.10.3 [util.smartptr.weak] + 20.8.10.3.1 [util.smartptr.weak.const] + 20.8.10.3.2 [util.smartptr.weak.dest] + 20.8.10.3.3 [util.smartptr.weak.assign] + 20.8.10.3.4 [util.smartptr.weak.mod] + 20.8.10.3.5 [util.smartptr.weak.obs] + 20.8.10.3.6 [util.smartptr.weak.spec] + 20.8.10.4 [util.smartptr.ownerless] + 20.8.10.5 [util.smartptr.enab] + 20.8.10.6 [util.smartptr.shared.atomic] + 20.8.10.7 [util.dynamic.safety] + 20.8.11 [ptr.align] + 20.8.12 [c.malloc] 20.9 [time] 20.9.1 [time.clock.req] 20.9.2 [time.traits] @@ -761,628 +753,636 @@ 20.9.5.3 [time.clock.hires] 20.10 [date.time] 21 [strings] - 21.1 [char.traits] - 21.1.1 [char.traits.require] - 21.1.2 [char.traits.typedefs] - 21.1.3 [char.traits.specializations] - 21.1.3.1 [char.traits.specializations.char] - 21.1.3.2 [char.traits.specializations.char16_t] - 21.1.3.3 [char.traits.specializations.char32_t] - 21.1.3.4 [char.traits.specializations.wchar.t] - 21.2 [string.classes] - 21.3 [basic.string] - 21.3.1 [string.require] - 21.3.2 [string.cons] - 21.3.3 [string.iterators] - 21.3.4 [string.capacity] - 21.3.5 [string.access] - 21.3.6 [string.modifiers] - 21.3.6.1 [string::op+=] - 21.3.6.2 [string::append] - 21.3.6.3 [string::assign] - 21.3.6.4 [string::insert] - 21.3.6.5 [string::erase] - 21.3.6.6 [string::replace] - 21.3.6.7 [string::copy] - 21.3.6.8 [string::swap] - 21.3.7 [string.ops] - 21.3.7.1 [string.accessors] - 21.3.7.2 [string::find] - 21.3.7.3 [string::rfind] - 21.3.7.4 [string::find.first.of] - 21.3.7.5 [string::find.last.of] - 21.3.7.6 [string::find.first.not.of] - 21.3.7.7 [string::find.last.not.of] - 21.3.7.8 [string::substr] - 21.3.7.9 [string::compare] - 21.3.8 [string.nonmembers] - 21.3.8.1 [string::op+] - 21.3.8.2 [string::operator==] - 21.3.8.3 [string::op!=] - 21.3.8.4 [string::op<] - 21.3.8.5 [string::op>] - 21.3.8.6 [string::op<=] - 21.3.8.7 [string::op>=] - 21.3.8.8 [string.special] - 21.3.8.9 [string.io] - 21.4 [string.conversions] - 21.5 [c.strings] + 21.1 [strings.general] + 21.2 [char.traits] + 21.2.1 [char.traits.require] + 21.2.2 [char.traits.typedefs] + 21.2.3 [char.traits.specializations] + 21.2.3.1 [char.traits.specializations.char] + 21.2.3.2 [char.traits.specializations.char16_t] + 21.2.3.3 [char.traits.specializations.char32_t] + 21.2.3.4 [char.traits.specializations.wchar.t] + 21.3 [string.classes] + 21.4 [basic.string] + 21.4.1 [string.require] + 21.4.2 [string.cons] + 21.4.3 [string.iterators] + 21.4.4 [string.capacity] + 21.4.5 [string.access] + 21.4.6 [string.modifiers] + 21.4.6.1 [string::op+=] + 21.4.6.2 [string::append] + 21.4.6.3 [string::assign] + 21.4.6.4 [string::insert] + 21.4.6.5 [string::erase] + 21.4.6.6 [string::replace] + 21.4.6.7 [string::copy] + 21.4.6.8 [string::swap] + 21.4.7 [string.ops] + 21.4.7.1 [string.accessors] + 21.4.7.2 [string::find] + 21.4.7.3 [string::rfind] + 21.4.7.4 [string::find.first.of] + 21.4.7.5 [string::find.last.of] + 21.4.7.6 [string::find.first.not.of] + 21.4.7.7 [string::find.last.not.of] + 21.4.7.8 [string::substr] + 21.4.7.9 [string::compare] + 21.4.8 [string.nonmembers] + 21.4.8.1 [string::op+] + 21.4.8.2 [string::operator==] + 21.4.8.3 [string::op!=] + 21.4.8.4 [string::op<] + 21.4.8.5 [string::op>] + 21.4.8.6 [string::op<=] + 21.4.8.7 [string::op>=] + 21.4.8.8 [string.special] + 21.4.8.9 [string.io] + 21.5 [string.conversions] + 21.6 [c.strings] 22 [localization] - 22.1 [locales] - 22.1.1 [locale] - 22.1.1.1 [locale.types] - 22.1.1.1.1 [locale.category] - 22.1.1.1.2 [locale.facet] - 22.1.1.1.3 [locale.id] - 22.1.1.2 [locale.cons] - 22.1.1.3 [locale.members] - 22.1.1.4 [locale.operators] - 22.1.1.5 [locale.statics] - 22.1.2 [locale.global.templates] - 22.1.3 [locale.convenience] - 22.1.3.1 [classification] - 22.1.3.2 [conversions] - 22.1.3.2.1 [conversions.character] - 22.1.3.2.2 [conversions.string] - 22.1.3.2.3 [conversions.buffer] - 22.2 [locale.categories] - 22.2.1 [category.ctype] - 22.2.1.1 [locale.ctype] - 22.2.1.1.1 [locale.ctype.members] - 22.2.1.1.2 [locale.ctype.virtuals] - 22.2.1.2 [locale.ctype.byname] - 22.2.1.3 [facet.ctype.special] - 22.2.1.3.1 [facet.ctype.char.dtor] - 22.2.1.3.2 [facet.ctype.char.members] - 22.2.1.3.3 [facet.ctype.char.statics] - 22.2.1.3.4 [facet.ctype.char.virtuals] - 22.2.1.4 [locale.codecvt] - 22.2.1.4.1 [locale.codecvt.members] - 22.2.1.4.2 [locale.codecvt.virtuals] - 22.2.1.5 [locale.codecvt.byname] - 22.2.2 [category.numeric] - 22.2.2.1 [locale.num.get] - 22.2.2.1.1 [facet.num.get.members] - 22.2.2.1.2 [facet.num.get.virtuals] - 22.2.2.2 [locale.nm.put] - 22.2.2.2.1 [facet.num.put.members] - 22.2.2.2.2 [facet.num.put.virtuals] - 22.2.3 [facet.numpunct] - 22.2.3.1 [locale.numpunct] - 22.2.3.1.1 [facet.numpunct.members] - 22.2.3.1.2 [facet.numpunct.virtuals] - 22.2.3.2 [locale.numpunct.byname] - 22.2.4 [category.collate] - 22.2.4.1 [locale.collate] - 22.2.4.1.1 [locale.collate.members] - 22.2.4.1.2 [locale.collate.virtuals] - 22.2.4.2 [locale.collate.byname] - 22.2.5 [category.time] - 22.2.5.1 [locale.time.get] - 22.2.5.1.1 [locale.time.get.members] - 22.2.5.1.2 [locale.time.get.virtuals] - 22.2.5.2 [locale.time.get.byname] - 22.2.5.3 [locale.time.put] - 22.2.5.3.1 [locale.time.put.members] - 22.2.5.3.2 [locale.time.put.virtuals] - 22.2.5.4 [locale.time.put.byname] - 22.2.6 [category.monetary] - 22.2.6.1 [locale.money.get] - 22.2.6.1.1 [locale.money.get.members] - 22.2.6.1.2 [locale.money.get.virtuals] - 22.2.6.2 [locale.money.put] - 22.2.6.2.1 [locale.money.put.members] - 22.2.6.2.2 [locale.money.put.virtuals] - 22.2.6.3 [locale.moneypunct] - 22.2.6.3.1 [locale.moneypunct.members] - 22.2.6.3.2 [locale.moneypunct.virtuals] - 22.2.6.4 [locale.moneypunct.byname] - 22.2.7 [category.messages] - 22.2.7.1 [locale.messages] - 22.2.7.1.1 [locale.messages.members] - 22.2.7.1.2 [locale.messages.virtuals] - 22.2.7.2 [locale.messages.byname] - 22.2.8 [facets.examples] - 22.3 [locale.stdcvt] - 22.4 [c.locales] + 22.1 [localization.general] + 22.2 [locale.syn] + 22.3 [locales] + 22.3.1 [locale] + 22.3.1.1 [locale.types] + 22.3.1.1.1 [locale.category] + 22.3.1.1.2 [locale.facet] + 22.3.1.1.3 [locale.id] + 22.3.1.2 [locale.cons] + 22.3.1.3 [locale.members] + 22.3.1.4 [locale.operators] + 22.3.1.5 [locale.statics] + 22.3.2 [locale.global.templates] + 22.3.3 [locale.convenience] + 22.3.3.1 [classification] + 22.3.3.2 [conversions] + 22.3.3.2.1 [conversions.character] + 22.3.3.2.2 [conversions.string] + 22.3.3.2.3 [conversions.buffer] + 22.4 [locale.categories] + 22.4.1 [category.ctype] + 22.4.1.1 [locale.ctype] + 22.4.1.1.1 [locale.ctype.members] + 22.4.1.1.2 [locale.ctype.virtuals] + 22.4.1.2 [locale.ctype.byname] + 22.4.1.3 [facet.ctype.special] + 22.4.1.3.1 [facet.ctype.char.dtor] + 22.4.1.3.2 [facet.ctype.char.members] + 22.4.1.3.3 [facet.ctype.char.statics] + 22.4.1.3.4 [facet.ctype.char.virtuals] + 22.4.1.4 [locale.codecvt] + 22.4.1.4.1 [locale.codecvt.members] + 22.4.1.4.2 [locale.codecvt.virtuals] + 22.4.1.5 [locale.codecvt.byname] + 22.4.2 [category.numeric] + 22.4.2.1 [locale.num.get] + 22.4.2.1.1 [facet.num.get.members] + 22.4.2.1.2 [facet.num.get.virtuals] + 22.4.2.2 [locale.nm.put] + 22.4.2.2.1 [facet.num.put.members] + 22.4.2.2.2 [facet.num.put.virtuals] + 22.4.3 [facet.numpunct] + 22.4.3.1 [locale.numpunct] + 22.4.3.1.1 [facet.numpunct.members] + 22.4.3.1.2 [facet.numpunct.virtuals] + 22.4.3.2 [locale.numpunct.byname] + 22.4.4 [category.collate] + 22.4.4.1 [locale.collate] + 22.4.4.1.1 [locale.collate.members] + 22.4.4.1.2 [locale.collate.virtuals] + 22.4.4.2 [locale.collate.byname] + 22.4.5 [category.time] + 22.4.5.1 [locale.time.get] + 22.4.5.1.1 [locale.time.get.members] + 22.4.5.1.2 [locale.time.get.virtuals] + 22.4.5.2 [locale.time.get.byname] + 22.4.5.3 [locale.time.put] + 22.4.5.3.1 [locale.time.put.members] + 22.4.5.3.2 [locale.time.put.virtuals] + 22.4.5.4 [locale.time.put.byname] + 22.4.6 [category.monetary] + 22.4.6.1 [locale.money.get] + 22.4.6.1.1 [locale.money.get.members] + 22.4.6.1.2 [locale.money.get.virtuals] + 22.4.6.2 [locale.money.put] + 22.4.6.2.1 [locale.money.put.members] + 22.4.6.2.2 [locale.money.put.virtuals] + 22.4.6.3 [locale.moneypunct] + 22.4.6.3.1 [locale.moneypunct.members] + 22.4.6.3.2 [locale.moneypunct.virtuals] + 22.4.6.4 [locale.moneypunct.byname] + 22.4.7 [category.messages] + 22.4.7.1 [locale.messages] + 22.4.7.1.1 [locale.messages.members] + 22.4.7.1.2 [locale.messages.virtuals] + 22.4.7.2 [locale.messages.byname] + 22.4.8 [facets.examples] + 22.5 [locale.stdcvt] + 22.6 [c.locales] 23 [containers] - 23.1 [container.requirements] - 23.1.1 [container.requirements.general] - 23.1.2 [container.requirements.dataraces] - 23.1.3 [sequence.reqmts] - 23.1.4 [associative.reqmts] - 23.1.4.1 [associative.reqmts.except] - 23.1.5 [unord.req] - 23.1.5.1 [unord.req.except] - 23.1.6 [container.concepts] - 23.1.6.1 [container.concepts.free] - 23.1.6.2 [container.concepts.member] - 23.1.6.3 [container.concepts.maps] - 23.2 [sequences] - 23.2.1 [array] - 23.2.1.1 [array.cons] - 23.2.1.2 [array.special] - 23.2.1.3 [array.size] - 23.2.1.4 [array.data] - 23.2.1.5 [array.fill] - 23.2.1.6 [array.zero] - 23.2.1.7 [array.tuple] - 23.2.2 [deque] - 23.2.2.1 [deque.cons] - 23.2.2.2 [deque.capacity] - 23.2.2.3 [deque.modifiers] - 23.2.2.4 [deque.special] - 23.2.3 [forwardlist] - 23.2.3.1 [forwardlist.cons] - 23.2.3.2 [forwardlist.iter] - 23.2.3.3 [forwardlist.access] - 23.2.3.4 [forwardlist.modifiers] - 23.2.3.5 [forwardlist.ops] - 23.2.3.6 [forwardlist.spec] - 23.2.4 [list] - 23.2.4.1 [list.cons] - 23.2.4.2 [list.capacity] - 23.2.4.3 [list.modifiers] - 23.2.4.4 [list.ops] - 23.2.4.5 [list.special] - 23.2.5 [container.adaptors] - 23.2.5.1 [queue] - 23.2.5.1.1 [queue.defn] - 23.2.5.1.2 [queue.ops] - 23.2.5.1.3 [queue.special] - 23.2.5.2 [priority.queue] - 23.2.5.2.1 [priqueue.cons] - 23.2.5.2.2 [priqueue.members] - 23.2.5.2.3 [priqueue.special] - 23.2.5.3 [stack] - 23.2.5.3.1 [stack.defn] - 23.2.5.3.2 [stack.ops] - 23.2.5.3.3 [stack.special] - 23.2.6 [vector] - 23.2.6.1 [vector.cons] - 23.2.6.2 [vector.capacity] - 23.2.6.3 [vector.data] - 23.2.6.4 [vector.modifiers] - 23.2.6.5 [vector.special] - 23.2.7 [vector.bool] - 23.3 [associative] - 23.3.1 [map] - 23.3.1.1 [map.cons] - 23.3.1.2 [map.access] - 23.3.1.3 [map.modifiers] - 23.3.1.4 [map.ops] - 23.3.1.5 [map.special] - 23.3.2 [multimap] - 23.3.2.1 [multimap.cons] - 23.3.2.2 [multimap.modifiers] - 23.3.2.3 [multimap.ops] - 23.3.2.4 [multimap.special] - 23.3.3 [set] - 23.3.3.1 [set.cons] - 23.3.3.2 [set.special] - 23.3.4 [multiset] - 23.3.4.1 [multiset.cons] - 23.3.4.2 [multiset.special] - 23.4 [unord] - 23.4.1 [unord.map] - 23.4.1.1 [unord.map.cnstr] - 23.4.1.2 [unord.map.elem] - 23.4.1.3 [unord.map.swap] - 23.4.2 [unord.multimap] - 23.4.2.1 [unord.multimap.cnstr] - 23.4.2.2 [unord.multimap.swap] - 23.4.3 [unord.set] - 23.4.3.1 [unord.set.cnstr] - 23.4.3.2 [unord.set.swap] - 23.4.4 [unord.multiset] - 23.4.4.1 [unord.multiset.cnstr] - 23.4.4.2 [unord.multiset.swap] + 23.1 [containers.general] + 23.2 [container.requirements] + 23.2.1 [container.requirements.general] + 23.2.2 [container.requirements.dataraces] + 23.2.3 [sequence.reqmts] + 23.2.4 [associative.reqmts] + 23.2.4.1 [associative.reqmts.except] + 23.2.5 [unord.req] + 23.2.5.1 [unord.req.except] + 23.2.6 [container.concepts] + 23.2.6.1 [container.concepts.free] + 23.2.6.2 [container.concepts.member] + 23.2.6.3 [container.concepts.maps] + 23.3 [sequences] + 23.3.1 [array] + 23.3.1.1 [array.cons] + 23.3.1.2 [array.special] + 23.3.1.3 [array.size] + 23.3.1.4 [array.data] + 23.3.1.5 [array.fill] + 23.3.1.6 [array.zero] + 23.3.1.7 [array.tuple] + 23.3.2 [deque] + 23.3.2.1 [deque.cons] + 23.3.2.2 [deque.capacity] + 23.3.2.3 [deque.modifiers] + 23.3.2.4 [deque.special] + 23.3.3 [forwardlist] + 23.3.3.1 [forwardlist.cons] + 23.3.3.2 [forwardlist.iter] + 23.3.3.3 [forwardlist.access] + 23.3.3.4 [forwardlist.modifiers] + 23.3.3.5 [forwardlist.ops] + 23.3.3.6 [forwardlist.spec] + 23.3.4 [list] + 23.3.4.1 [list.cons] + 23.3.4.2 [list.capacity] + 23.3.4.3 [list.modifiers] + 23.3.4.4 [list.ops] + 23.3.4.5 [list.special] + 23.3.5 [container.adaptors] + 23.3.5.1 [queue] + 23.3.5.1.1 [queue.defn] + 23.3.5.1.2 [queue.ops] + 23.3.5.1.3 [queue.special] + 23.3.5.2 [priority.queue] + 23.3.5.2.1 [priqueue.cons] + 23.3.5.2.2 [priqueue.members] + 23.3.5.2.3 [priqueue.special] + 23.3.5.3 [stack] + 23.3.5.3.1 [stack.defn] + 23.3.5.3.2 [stack.ops] + 23.3.5.3.3 [stack.special] + 23.3.6 [vector] + 23.3.6.1 [vector.cons] + 23.3.6.2 [vector.capacity] + 23.3.6.3 [vector.data] + 23.3.6.4 [vector.modifiers] + 23.3.6.5 [vector.special] + 23.3.7 [vector.bool] + 23.4 [associative] + 23.4.1 [map] + 23.4.1.1 [map.cons] + 23.4.1.2 [map.access] + 23.4.1.3 [map.modifiers] + 23.4.1.4 [map.ops] + 23.4.1.5 [map.special] + 23.4.2 [multimap] + 23.4.2.1 [multimap.cons] + 23.4.2.2 [multimap.modifiers] + 23.4.2.3 [multimap.ops] + 23.4.2.4 [multimap.special] + 23.4.3 [set] + 23.4.3.1 [set.cons] + 23.4.3.2 [set.special] + 23.4.4 [multiset] + 23.4.4.1 [multiset.cons] + 23.4.4.2 [multiset.special] + 23.5 [unord] + 23.5.1 [unord.map] + 23.5.1.1 [unord.map.cnstr] + 23.5.1.2 [unord.map.elem] + 23.5.1.3 [unord.map.swap] + 23.5.2 [unord.multimap] + 23.5.2.1 [unord.multimap.cnstr] + 23.5.2.2 [unord.multimap.swap] + 23.5.3 [unord.set] + 23.5.3.1 [unord.set.cnstr] + 23.5.3.2 [unord.set.swap] + 23.5.4 [unord.multiset] + 23.5.4.1 [unord.multiset.cnstr] + 23.5.4.2 [unord.multiset.swap] 24 [iterators] - 24.1 [iterator.concepts] - 24.1.1 [iterator.iterators] - 24.1.2 [input.iterators] - 24.1.3 [output.iterators] - 24.1.4 [forward.iterators] - 24.1.5 [bidirectional.iterators] - 24.1.6 [random.access.iterators] - 24.1.7 [shuffle.iterators] - 24.1.8 [iterator.concepts.range] - 24.2 [iterator.synopsis] - 24.3 [iterator.operations] - 24.4 [predef.iterators] - 24.4.1 [reverse.iterators] - 24.4.1.1 [reverse.iterator] - 24.4.1.2 [reverse.iter.requirements] - 24.4.1.3 [reverse.iter.ops] - 24.4.1.3.1 [reverse.iter.cons] - 24.4.1.3.2 [reverse.iter.op=] - 24.4.1.3.3 [reverse.iter.conv] - 24.4.1.3.4 [reverse.iter.op.star] - 24.4.1.3.5 [reverse.iter.opref] - 24.4.1.3.6 [reverse.iter.op++] - 24.4.1.3.7 [reverse.iter.op--] - 24.4.1.3.8 [reverse.iter.op+] - 24.4.1.3.9 [reverse.iter.op+=] - 24.4.1.3.10 [reverse.iter.op-] - 24.4.1.3.11 [reverse.iter.op-=] - 24.4.1.3.12 [reverse.iter.opindex] - 24.4.1.3.13 [reverse.iter.op==] - 24.4.1.3.14 [reverse.iter.op<] - 24.4.1.3.15 [reverse.iter.op!=] - 24.4.1.3.16 [reverse.iter.op>] - 24.4.1.3.17 [reverse.iter.op>=] - 24.4.1.3.18 [reverse.iter.op<=] - 24.4.1.3.19 [reverse.iter.opdiff] - 24.4.1.3.20 [reverse.iter.opsum] - 24.4.1.4 [reverse.iter.maps] - 24.4.2 [insert.iterators] - 24.4.2.1 [back.insert.iterator] - 24.4.2.2 [back.insert.iter.ops] - 24.4.2.2.1 [back.insert.iter.cons] - 24.4.2.2.2 [back.insert.iter.op=] - 24.4.2.2.3 [back.insert.iter.op*] - 24.4.2.2.4 [back.insert.iter.op++] - 24.4.2.2.5 [back.inserter] - 24.4.2.2.6 [back.insert.iter.maps] - 24.4.2.3 [front.insert.iterator] - 24.4.2.4 [front.insert.iter.ops] - 24.4.2.4.1 [front.insert.iter.cons] - 24.4.2.4.2 [front.insert.iter.op=] - 24.4.2.4.3 [front.insert.iter.op*] - 24.4.2.4.4 [front.insert.iter.op++] - 24.4.2.4.5 [front.inserter] - 24.4.2.4.6 [front.insert.iter.maps] - 24.4.2.5 [insert.iterator] - 24.4.2.6 [insert.iter.ops] - 24.4.2.6.1 [insert.iter.cons] - 24.4.2.6.2 [insert.iter.op=] - 24.4.2.6.3 [insert.iter.op*] - 24.4.2.6.4 [insert.iter.op++] - 24.4.2.6.5 [inserter] - 24.4.2.6.6 [insert.iter.maps] - 24.4.3 [move.iterators] - 24.4.3.1 [move.iterator] - 24.4.3.2 [move.iter.requirements] - 24.4.3.3 [move.iter.ops] - 24.4.3.3.1 [move.iter.op.const] - 24.4.3.3.2 [move.iter.op=] - 24.4.3.3.3 [move.iter.op.conv] - 24.4.3.3.4 [move.iter.op.star] - 24.4.3.3.5 [move.iter.op.ref] - 24.4.3.3.6 [move.iter.op.incr] - 24.4.3.3.7 [move.iter.op.decr] - 24.4.3.3.8 [move.iter.op.+] - 24.4.3.3.9 [move.iter.op.+=] - 24.4.3.3.10 [move.iter.op.-] - 24.4.3.3.11 [move.iter.op.-=] - 24.4.3.3.12 [move.iter.op.index] - 24.4.3.3.13 [move.iter.op.comp] - 24.4.3.3.14 [move.iter.nonmember] - 24.4.3.3.15 [move.iter.maps] - 24.5 [stream.iterators] - 24.5.1 [istream.iterator] - 24.5.1.1 [istream.iterator.cons] - 24.5.1.2 [istream.iterator.ops] - 24.5.2 [ostream.iterator] - 24.5.2.1 [ostream.iterator.cons.des] - 24.5.2.2 [ostream.iterator.ops] - 24.5.3 [istreambuf.iterator] - 24.5.3.1 [istreambuf.iterator::proxy] - 24.5.3.2 [istreambuf.iterator.cons] - 24.5.3.3 [istreambuf.iterator::op*] - 24.5.3.4 [istreambuf.iterator::op++] - 24.5.3.5 [istreambuf.iterator::equal] - 24.5.3.6 [istreambuf.iterator::op==] - 24.5.3.7 [istreambuf.iterator::op!=] - 24.5.4 [ostreambuf.iterator] - 24.5.4.1 [ostreambuf.iter.cons] - 24.5.4.2 [ostreambuf.iter.ops] + 24.1 [iterators.general] + 24.2 [iterator.concepts] + 24.2.1 [iterator.iterators] + 24.2.2 [input.iterators] + 24.2.3 [output.iterators] + 24.2.4 [forward.iterators] + 24.2.5 [bidirectional.iterators] + 24.2.6 [random.access.iterators] + 24.2.7 [shuffle.iterators] + 24.2.8 [iterator.concepts.range] + 24.3 [iterator.syn] + 24.4 [iterator.operations] + 24.5 [predef.iterators] + 24.5.1 [reverse.iterators] + 24.5.1.1 [reverse.iterator] + 24.5.1.2 [reverse.iter.ops] + 24.5.1.2.1 [reverse.iter.cons] + 24.5.1.2.2 [reverse.iter.op=] + 24.5.1.2.3 [reverse.iter.conv] + 24.5.1.2.4 [reverse.iter.op.star] + 24.5.1.2.5 [reverse.iter.opref] + 24.5.1.2.6 [reverse.iter.op++] + 24.5.1.2.7 [reverse.iter.op--] + 24.5.1.2.8 [reverse.iter.op+] + 24.5.1.2.9 [reverse.iter.op+=] + 24.5.1.2.10 [reverse.iter.op-] + 24.5.1.2.11 [reverse.iter.op-=] + 24.5.1.2.12 [reverse.iter.opindex] + 24.5.1.2.13 [reverse.iter.op==] + 24.5.1.2.14 [reverse.iter.op<] + 24.5.1.2.15 [reverse.iter.op!=] + 24.5.1.2.16 [reverse.iter.op>] + 24.5.1.2.17 [reverse.iter.op>=] + 24.5.1.2.18 [reverse.iter.op<=] + 24.5.1.2.19 [reverse.iter.opdiff] + 24.5.1.2.20 [reverse.iter.opsum] + 24.5.1.3 [reverse.iter.maps] + 24.5.2 [move.iterators] + 24.5.2.1 [move.iterator] + 24.5.2.2 [move.iter.ops] + 24.5.2.2.1 [move.iter.op.const] + 24.5.2.2.2 [move.iter.op=] + 24.5.2.2.3 [move.iter.op.conv] + 24.5.2.2.4 [move.iter.op.star] + 24.5.2.2.5 [move.iter.op.ref] + 24.5.2.2.6 [move.iter.op.incr] + 24.5.2.2.7 [move.iter.op.decr] + 24.5.2.2.8 [move.iter.op.+] + 24.5.2.2.9 [move.iter.op.+=] + 24.5.2.2.10 [move.iter.op.-] + 24.5.2.2.11 [move.iter.op.-=] + 24.5.2.2.12 [move.iter.op.index] + 24.5.2.2.13 [move.iter.op.comp] + 24.5.2.2.14 [move.iter.nonmember] + 24.5.2.2.15 [move.iter.maps] + 24.6 [stream.iterators] + 24.6.1 [istream.iterator] + 24.6.1.1 [istream.iterator.cons] + 24.6.1.2 [istream.iterator.ops] + 24.6.2 [ostream.iterator] + 24.6.2.1 [ostream.iterator.cons.des] + 24.6.2.2 [ostream.iterator.ops] + 24.6.3 [istreambuf.iterator] + 24.6.3.1 [istreambuf.iterator::proxy] + 24.6.3.2 [istreambuf.iterator.cons] + 24.6.3.3 [istreambuf.iterator::op*] + 24.6.3.4 [istreambuf.iterator::op++] + 24.6.3.5 [istreambuf.iterator::equal] + 24.6.3.6 [istreambuf.iterator::op==] + 24.6.3.7 [istreambuf.iterator::op!=] + 24.6.4 [ostreambuf.iterator] + 24.6.4.1 [ostreambuf.iter.cons] + 24.6.4.2 [ostreambuf.iter.ops] + 24.7 [insert.iterators] + 24.7.1 [back.insert.iterator] + 24.7.2 [back.insert.iter.ops] + 24.7.2.1 [back.insert.iter.cons] + 24.7.2.2 [back.insert.iter.op=] + 24.7.2.3 [back.insert.iter.op*] + 24.7.2.4 [back.insert.iter.op++] + 24.7.2.5 [back.inserter] + 24.7.2.6 [back.insert.iter.maps] + 24.7.3 [front.insert.iterator] + 24.7.4 [front.insert.iter.ops] + 24.7.4.1 [front.insert.iter.cons] + 24.7.4.2 [front.insert.iter.op=] + 24.7.4.3 [front.insert.iter.op*] + 24.7.4.4 [front.insert.iter.op++] + 24.7.4.5 [front.inserter] + 24.7.4.6 [front.insert.iter.maps] + 24.7.5 [insert.iterator] + 24.7.6 [insert.iter.ops] + 24.7.6.1 [insert.iter.cons] + 24.7.6.2 [insert.iter.op=] + 24.7.6.3 [insert.iter.op*] + 24.7.6.4 [insert.iter.op++] + 24.7.6.5 [inserter] + 24.7.6.6 [insert.iter.maps] 25 [algorithms] - 25.1 [alg.nonmodifying] - 25.1.1 [alg.all_of] - 25.1.2 [alg.any_of] - 25.1.3 [alg.none_of] - 25.1.4 [alg.foreach] - 25.1.5 [alg.find] - 25.1.6 [alg.find.end] - 25.1.7 [alg.find.first.of] - 25.1.8 [alg.adjacent.find] - 25.1.9 [alg.count] - 25.1.10 [mismatch] - 25.1.11 [alg.equal] - 25.1.12 [alg.search] - 25.2 [alg.modifying.operations] - 25.2.1 [alg.copy] - 25.2.2 [alg.move] - 25.2.3 [alg.swap] - 25.2.4 [alg.transform] - 25.2.5 [alg.replace] - 25.2.6 [alg.fill] - 25.2.7 [alg.generate] - 25.2.8 [alg.remove] - 25.2.9 [alg.unique] - 25.2.10 [alg.reverse] - 25.2.11 [alg.rotate] - 25.2.12 [alg.random.shuffle] - 25.2.13 [alg.partitions] - 25.3 [alg.sorting] - 25.3.1 [alg.sort] - 25.3.1.1 [sort] - 25.3.1.2 [stable.sort] - 25.3.1.3 [partial.sort] - 25.3.1.4 [partial.sort.copy] - 25.3.1.5 [is.sorted] - 25.3.2 [alg.nth.element] - 25.3.3 [alg.binary.search] - 25.3.3.1 [lower.bound] - 25.3.3.2 [upper.bound] - 25.3.3.3 [equal.range] - 25.3.3.4 [binary.search] - 25.3.4 [alg.merge] - 25.3.5 [alg.set.operations] - 25.3.5.1 [includes] - 25.3.5.2 [set.union] - 25.3.5.3 [set.intersection] - 25.3.5.4 [set.difference] - 25.3.5.5 [set.symmetric.difference] - 25.3.6 [alg.heap.operations] - 25.3.6.1 [push.heap] - 25.3.6.2 [pop.heap] - 25.3.6.3 [make.heap] - 25.3.6.4 [sort.heap] - 25.3.6.5 [is.heap] - 25.3.7 [alg.min.max] - 25.3.8 [alg.lex.comparison] - 25.3.9 [alg.permutation.generators] - 25.4 [alg.c.library] + 25.1 [algorithms.general] + 25.2 [algorithms.syn] + 25.3 [alg.nonmodifying] + 25.3.1 [alg.all_of] + 25.3.2 [alg.any_of] + 25.3.3 [alg.none_of] + 25.3.4 [alg.foreach] + 25.3.5 [alg.find] + 25.3.6 [alg.find.end] + 25.3.7 [alg.find.first.of] + 25.3.8 [alg.adjacent.find] + 25.3.9 [alg.count] + 25.3.10 [mismatch] + 25.3.11 [alg.equal] + 25.3.12 [alg.search] + 25.4 [alg.modifying.operations] + 25.4.1 [alg.copy] + 25.4.2 [alg.move] + 25.4.3 [alg.swap] + 25.4.4 [alg.transform] + 25.4.5 [alg.replace] + 25.4.6 [alg.fill] + 25.4.7 [alg.generate] + 25.4.8 [alg.remove] + 25.4.9 [alg.unique] + 25.4.10 [alg.reverse] + 25.4.11 [alg.rotate] + 25.4.12 [alg.random.shuffle] + 25.4.13 [alg.partitions] + 25.5 [alg.sorting] + 25.5.1 [alg.sort] + 25.5.1.1 [sort] + 25.5.1.2 [stable.sort] + 25.5.1.3 [partial.sort] + 25.5.1.4 [partial.sort.copy] + 25.5.1.5 [is.sorted] + 25.5.2 [alg.nth.element] + 25.5.3 [alg.binary.search] + 25.5.3.1 [lower.bound] + 25.5.3.2 [upper.bound] + 25.5.3.3 [equal.range] + 25.5.3.4 [binary.search] + 25.5.4 [alg.merge] + 25.5.5 [alg.set.operations] + 25.5.5.1 [includes] + 25.5.5.2 [set.union] + 25.5.5.3 [set.intersection] + 25.5.5.4 [set.difference] + 25.5.5.5 [set.symmetric.difference] + 25.5.6 [alg.heap.operations] + 25.5.6.1 [push.heap] + 25.5.6.2 [pop.heap] + 25.5.6.3 [make.heap] + 25.5.6.4 [sort.heap] + 25.5.6.5 [is.heap] + 25.5.7 [alg.min.max] + 25.5.8 [alg.lex.comparison] + 25.5.9 [alg.permutation.generators] + 25.6 [alg.c.library] 26 [numerics] - 26.1 [numeric.requirements] - 26.2 [cfenv] - 26.2.1 [cfenv.syn] - 26.2.2 [fenv] - 26.3 [complex.numbers] - 26.3.1 [complex.synopsis] - 26.3.2 [complex] - 26.3.3 [complex.special] - 26.3.4 [complex.members] - 26.3.5 [complex.member.ops] - 26.3.6 [complex.ops] - 26.3.7 [complex.value.ops] - 26.3.8 [complex.transcendentals] - 26.3.9 [cmplx.over] - 26.3.10 [ccmplx] - 26.3.11 [cmplxh] - 26.4 [rand] - 26.4.1 [rand.req] - 26.4.1.1 [rand.req.genl] - 26.4.1.2 [rand.req.urng] - 26.4.1.3 [rand.req.eng] - 26.4.1.4 [rand.req.adapt] - 26.4.1.5 [rand.req.dist] - 26.4.2 [rand.synopsis] - 26.4.3 [rand.eng] - 26.4.3.1 [rand.eng.lcong] - 26.4.3.2 [rand.eng.mers] - 26.4.3.3 [rand.eng.sub] - 26.4.4 [rand.adapt] - 26.4.4.1 [rand.adapt.disc] - 26.4.4.2 [rand.adapt.ibits] - 26.4.4.3 [rand.adapt.shuf] - X [rand.adapt.xor] - 26.4.5 [rand.predef] - 26.4.6 [rand.device] - 26.4.7 [rand.util] - 26.4.7.1 [rand.util.seedseq] - 26.4.7.2 [rand.util.canonical] - 26.4.8 [rand.dist] - 26.4.8.1 [rand.dist.uni] - 26.4.8.1.1 [rand.dist.uni.int] - 26.4.8.1.2 [rand.dist.uni.real] - 26.4.8.2 [rand.dist.bern] - 26.4.8.2.1 [rand.dist.bern.bernoulli] - 26.4.8.2.2 [rand.dist.bern.bin] - 26.4.8.2.3 [rand.dist.bern.geo] - 26.4.8.2.4 [rand.dist.bern.negbin] - 26.4.8.3 [rand.dist.pois] - 26.4.8.3.1 [rand.dist.pois.poisson] - 26.4.8.3.2 [rand.dist.pois.exp] - 26.4.8.3.3 [rand.dist.pois.gamma] - 26.4.8.3.4 [rand.dist.pois.weibull] - 26.4.8.3.5 [rand.dist.pois.extreme] - 26.4.8.4 [rand.dist.norm] - 26.4.8.4.1 [rand.dist.norm.normal] - 26.4.8.4.2 [rand.dist.norm.lognormal] - 26.4.8.4.3 [rand.dist.norm.chisq] - 26.4.8.4.4 [rand.dist.norm.cauchy] - 26.4.8.4.5 [rand.dist.norm.f] - 26.4.8.4.6 [rand.dist.norm.t] - 26.4.8.5 [rand.dist.samp] - 26.4.8.5.1 [rand.dist.samp.discrete] - 26.4.8.5.2 [rand.dist.samp.pconst] - 26.4.8.5.3 [rand.dist.samp.genpdf] - 26.5 [numarray] - 26.5.1 [valarray.synopsis] - 26.5.2 [template.valarray] - 26.5.2.1 [valarray.cons] - 26.5.2.2 [valarray.assign] - 26.5.2.3 [valarray.access] - 26.5.2.4 [valarray.sub] - 26.5.2.5 [valarray.unary] - 26.5.2.6 [valarray.cassign] - 26.5.2.7 [valarray.members] - 26.5.3 [valarray.nonmembers] - 26.5.3.1 [valarray.binary] - 26.5.3.2 [valarray.comparison] - 26.5.3.3 [valarray.transcend] - 26.5.3.4 [valarray.special] - 26.5.4 [class.slice] - 26.5.4.1 [cons.slice] - 26.5.4.2 [slice.access] - 26.5.5 [template.slice.array] - 26.5.5.1 [slice.arr.assign] - 26.5.5.2 [slice.arr.comp.assign] - 26.5.5.3 [slice.arr.fill] - 26.5.6 [class.gslice] - 26.5.6.1 [gslice.cons] - 26.5.6.2 [gslice.access] - 26.5.7 [template.gslice.array] - 26.5.7.1 [gslice.array.assign] - 26.5.7.2 [gslice.array.comp.assign] - 26.5.7.3 [gslice.array.fill] - 26.5.8 [template.mask.array] - 26.5.8.1 [mask.array.assign] - 26.5.8.2 [mask.array.comp.assign] - 26.5.8.3 [mask.array.fill] - 26.5.9 [template.indirect.array] - 26.5.9.1 [indirect.array.assign] - 26.5.9.2 [indirect.array.comp.assign] - 26.5.9.3 [indirect.array.fill] - 26.5.9.4 [valarray.concepts] - 26.6 [numeric.ops] - 26.6.1 [accumulate] - 26.6.2 [inner.product] - 26.6.3 [partial.sum] - 26.6.4 [adjacent.difference] - 26.6.5 [numeric.iota] - 26.7 [c.math] + 26.1 [numerics.general] + 26.2 [numeric.requirements] + 26.3 [cfenv] + 26.3.1 [cfenv.syn] + 26.3.2 [fenv] + 26.4 [complex.numbers] + 26.4.1 [complex.syn] + 26.4.2 [complex] + 26.4.3 [complex.special] + 26.4.4 [complex.members] + 26.4.5 [complex.member.ops] + 26.4.6 [complex.ops] + 26.4.7 [complex.value.ops] + 26.4.8 [complex.transcendentals] + 26.4.9 [cmplx.over] + 26.4.10 [ccmplx] + 26.4.11 [cmplxh] + 26.5 [rand] + 26.5.1 [rand.synopsis] + 26.5.2 [rand.concept] + 26.5.2.1 [rand.concept.seedseq] + 26.5.2.2 [rand.concept.urng] + 26.5.2.3 [rand.concept.eng] + 26.5.2.4 [rand.concept.adapt] + 26.5.2.5 [rand.concept.dist] + 26.5.3 [rand.eng] + 26.5.3.1 [rand.eng.lcong] + 26.5.3.2 [rand.eng.mers] + 26.5.3.3 [rand.eng.sub] + 26.5.4 [rand.adapt] + 26.5.4.1 [rand.adapt.disc] + 26.5.4.2 [rand.adapt.ibits] + 26.5.4.3 [rand.adapt.shuf] + 26.5.5 [rand.predef] + 26.5.6 [rand.device] + 26.5.7 [rand.util] + 26.5.7.1 [rand.util.seedseq] + 26.5.7.2 [rand.util.canonical] + 26.5.8 [rand.dist] + 26.5.8.1 [rand.dist.uni] + 26.5.8.1.1 [rand.dist.uni.int] + 26.5.8.1.2 [rand.dist.uni.real] + 26.5.8.2 [rand.dist.bern] + 26.5.8.2.1 [rand.dist.bern.bernoulli] + 26.5.8.2.2 [rand.dist.bern.bin] + 26.5.8.2.3 [rand.dist.bern.geo] + 26.5.8.2.4 [rand.dist.bern.negbin] + 26.5.8.3 [rand.dist.pois] + 26.5.8.3.1 [rand.dist.pois.poisson] + 26.5.8.3.2 [rand.dist.pois.exp] + 26.5.8.3.3 [rand.dist.pois.gamma] + 26.5.8.3.4 [rand.dist.pois.weibull] + 26.5.8.3.5 [rand.dist.pois.extreme] + 26.5.8.4 [rand.dist.norm] + 26.5.8.4.1 [rand.dist.norm.normal] + 26.5.8.4.2 [rand.dist.norm.lognormal] + 26.5.8.4.3 [rand.dist.norm.chisq] + 26.5.8.4.4 [rand.dist.norm.cauchy] + 26.5.8.4.5 [rand.dist.norm.f] + 26.5.8.4.6 [rand.dist.norm.t] + 26.5.8.5 [rand.dist.samp] + 26.5.8.5.1 [rand.dist.samp.discrete] + 26.5.8.5.2 [rand.dist.samp.pconst] + 26.5.8.5.3 [rand.dist.samp.plinear] + 26.6 [numarray] + 26.6.1 [valarray.syn] + 26.6.2 [template.valarray] + 26.6.2.1 [valarray.cons] + 26.6.2.2 [valarray.assign] + 26.6.2.3 [valarray.access] + 26.6.2.4 [valarray.sub] + 26.6.2.5 [valarray.unary] + 26.6.2.6 [valarray.cassign] + 26.6.2.7 [valarray.members] + 26.6.3 [valarray.nonmembers] + 26.6.3.1 [valarray.binary] + 26.6.3.2 [valarray.comparison] + 26.6.3.3 [valarray.transcend] + 26.6.3.4 [valarray.special] + 26.6.4 [class.slice] + 26.6.4.1 [cons.slice] + 26.6.4.2 [slice.access] + 26.6.5 [template.slice.array] + 26.6.5.1 [slice.arr.assign] + 26.6.5.2 [slice.arr.comp.assign] + 26.6.5.3 [slice.arr.fill] + 26.6.6 [class.gslice] + 26.6.6.1 [gslice.cons] + 26.6.6.2 [gslice.access] + 26.6.7 [template.gslice.array] + 26.6.7.1 [gslice.array.assign] + 26.6.7.2 [gslice.array.comp.assign] + 26.6.7.3 [gslice.array.fill] + 26.6.8 [template.mask.array] + 26.6.8.1 [mask.array.assign] + 26.6.8.2 [mask.array.comp.assign] + 26.6.8.3 [mask.array.fill] + 26.6.9 [template.indirect.array] + 26.6.9.1 [indirect.array.assign] + 26.6.9.2 [indirect.array.comp.assign] + 26.6.9.3 [indirect.array.fill] + 26.6.9.4 [valarray.concepts] + 26.7 [numeric.ops] + 26.7.1 [accumulate] + 26.7.2 [inner.product] + 26.7.3 [partial.sum] + 26.7.4 [adjacent.difference] + 26.7.5 [numeric.iota] + 26.8 [c.math] 27 [input.output] - 27.1 [iostreams.requirements] - 27.1.1 [iostream.limits.imbue] - 27.1.2 [iostreams.limits.pos] - 27.1.3 [iostreams.threadsafety] - 27.2 [iostream.forward] - 27.3 [iostream.objects] - 27.3.1 [narrow.stream.objects] - 27.3.2 [wide.stream.objects] - 27.4 [iostreams.base] - 27.4.1 [stream.types] - 27.4.2 [ios.base] - 27.4.2.1 [ios.types] - 27.4.2.1.1 [ios::failure] - 27.4.2.1.2 [ios::fmtflags] - 27.4.2.1.3 [ios::iostate] - 27.4.2.1.4 [ios::openmode] - 27.4.2.1.5 [ios::seekdir] - 27.4.2.1.6 [ios::Init] - 27.4.2.2 [fmtflags.state] - 27.4.2.3 [ios.base.locales] - 27.4.2.4 [ios.members.static] - 27.4.2.5 [ios.base.storage] - 27.4.2.6 [ios.base.callback] - 27.4.2.7 [ios.base.cons] - 27.4.3 [fpos] - 27.4.3.1 [fpos.members] - 27.4.3.2 [fpos.operations] - 27.4.4 [ios] - 27.4.4.1 [basic.ios.cons] - 27.4.4.2 [basic.ios.members] - 27.4.4.3 [iostate.flags] - 27.4.5 [std.ios.manip] - 27.4.5.1 [fmtflags.manip] - 27.4.5.2 [adjustfield.manip] - 27.4.5.3 [basefield.manip] - 27.4.5.4 [floatfield.manip] - 27.4.5.5 [error.reporting] - 27.5 [stream.buffers] - 27.5.1 [streambuf.reqts] - 27.5.2 [streambuf] - 27.5.2.1 [streambuf.cons] - 27.5.2.2 [streambuf.members] - 27.5.2.2.1 [streambuf.locales] - 27.5.2.2.2 [streambuf.buffer] - 27.5.2.2.3 [streambuf.pub.get] - 27.5.2.2.4 [streambuf.pub.pback] - 27.5.2.2.5 [streambuf.pub.put] - 27.5.2.3 [streambuf.protected] - 27.5.2.3.1 [streambuf.assign] - 27.5.2.3.2 [streambuf.get.area] - 27.5.2.3.3 [streambuf.put.area] - 27.5.2.4 [streambuf.virtuals] - 27.5.2.4.1 [streambuf.virt.locales] - 27.5.2.4.2 [streambuf.virt.buffer] - 27.5.2.4.3 [streambuf.virt.get] - 27.5.2.4.4 [streambuf.virt.pback] - 27.5.2.4.5 [streambuf.virt.put] - 27.6 [iostream.format] - 27.6.1 [input.streams] - 27.6.1.1 [istream] - 27.6.1.1.1 [istream.cons] - 27.6.1.1.2 [istream.assign] - 27.6.1.1.3 [istream::sentry] - 27.6.1.2 [istream.formatted] - 27.6.1.2.1 [istream.formatted.reqmts] - 27.6.1.2.2 [istream.formatted.arithmetic] - 27.6.1.2.3 [istream::extractors] - 27.6.1.3 [istream.unformatted] - 27.6.1.4 [istream.manip] - 27.6.1.5 [iostreamclass] - 27.6.1.5.1 [iostream.cons] - 27.6.1.5.2 [iostream.dest] - 27.6.1.5.3 [iostream.assign] - 27.6.2 [output.streams] - 27.6.2.1 [ostream] - 27.6.2.2 [ostream.cons] - 27.6.2.3 [ostream.assign] - 27.6.2.4 [ostream::sentry] - 27.6.2.5 [ostream.seeks] - 27.6.2.6 [ostream.formatted] - 27.6.2.6.1 [ostream.formatted.reqmts] - 27.6.2.6.2 [ostream.inserters.arithmetic] - 27.6.2.6.3 [ostream.inserters] - 27.6.2.6.4 [ostream.inserters.character] - 27.6.2.7 [ostream.unformatted] - 27.6.2.8 [ostream.manip] - 27.6.3 [std.manip] - 27.6.4 [ext.manip] - 27.7 [string.streams] - 27.7.1 [stringbuf] - 27.7.1.1 [stringbuf.cons] - 27.7.1.2 [stringbuf.assign] - 27.7.1.3 [stringbuf.members] - 27.7.1.4 [stringbuf.virtuals] - 27.7.2 [istringstream] - 27.7.2.1 [istringstream.cons] - 27.7.2.2 [istringstream.assign] - 27.7.2.3 [istringstream.members] - 27.7.3 [ostringstream] - 27.7.3.1 [ostringstream.cons] - 27.7.3.2 [ostringstream.assign] - 27.7.3.3 [ostringstream.members] - 27.7.4 [stringstream] - 27.7.5 [stringstream.cons] - 27.7.5.1 [stringstream.assign] - 27.7.6 [stringstream.members] - 27.8 [file.streams] - 27.8.1 [fstreams] - 27.8.1.1 [filebuf] - 27.8.1.2 [filebuf.cons] - 27.8.1.3 [filebuf.assign] - 27.8.1.4 [filebuf.members] - 27.8.1.5 [filebuf.virtuals] - 27.8.1.6 [ifstream] - 27.8.1.7 [ifstream.cons] - 27.8.1.8 [ifstream.assign] - 27.8.1.9 [ifstream.members] - 27.8.1.10 [ofstream] - 27.8.1.11 [ofstream.cons] - 27.8.1.12 [ofstream.assign] - 27.8.1.13 [ofstream.members] - 27.8.1.14 [fstream] - 27.8.1.15 [fstream.cons] - 27.8.1.16 [fstream.assign] - 27.8.1.17 [fstream.members] - 27.8.2 [c.files] + 27.1 [input.output.general] + 27.2 [iostreams.requirements] + 27.2.1 [iostream.limits.imbue] + 27.2.2 [iostreams.limits.pos] + 27.2.3 [iostreams.threadsafety] + 27.3 [iostream.forward] + 27.4 [iostream.objects] + 27.4.1 [narrow.stream.objects] + 27.4.2 [wide.stream.objects] + 27.5 [iostreams.base] + 27.5.1 [stream.types] + 27.5.2 [ios.base] + 27.5.2.1 [ios.types] + 27.5.2.1.1 [ios::failure] + 27.5.2.1.2 [ios::fmtflags] + 27.5.2.1.3 [ios::iostate] + 27.5.2.1.4 [ios::openmode] + 27.5.2.1.5 [ios::seekdir] + 27.5.2.1.6 [ios::Init] + 27.5.2.2 [fmtflags.state] + 27.5.2.3 [ios.base.locales] + 27.5.2.4 [ios.members.static] + 27.5.2.5 [ios.base.storage] + 27.5.2.6 [ios.base.callback] + 27.5.2.7 [ios.base.cons] + 27.5.3 [fpos] + 27.5.3.1 [fpos.members] + 27.5.3.2 [fpos.operations] + 27.5.4 [ios] + 27.5.4.1 [basic.ios.cons] + 27.5.4.2 [basic.ios.members] + 27.5.4.3 [iostate.flags] + 27.5.5 [std.ios.manip] + 27.5.5.1 [fmtflags.manip] + 27.5.5.2 [adjustfield.manip] + 27.5.5.3 [basefield.manip] + 27.5.5.4 [floatfield.manip] + 27.5.5.5 [error.reporting] + 27.6 [stream.buffers] + 27.6.1 [streambuf.reqts] + 27.6.2 [streambuf] + 27.6.2.1 [streambuf.cons] + 27.6.2.2 [streambuf.members] + 27.6.2.2.1 [streambuf.locales] + 27.6.2.2.2 [streambuf.buffer] + 27.6.2.2.3 [streambuf.pub.get] + 27.6.2.2.4 [streambuf.pub.pback] + 27.6.2.2.5 [streambuf.pub.put] + 27.6.2.3 [streambuf.protected] + 27.6.2.3.1 [streambuf.assign] + 27.6.2.3.2 [streambuf.get.area] + 27.6.2.3.3 [streambuf.put.area] + 27.6.2.4 [streambuf.virtuals] + 27.6.2.4.1 [streambuf.virt.locales] + 27.6.2.4.2 [streambuf.virt.buffer] + 27.6.2.4.3 [streambuf.virt.get] + 27.6.2.4.4 [streambuf.virt.pback] + 27.6.2.4.5 [streambuf.virt.put] + 27.7 [iostream.format] + 27.7.1 [input.streams] + 27.7.1.1 [istream] + 27.7.1.1.1 [istream.cons] + 27.7.1.1.2 [istream.assign] + 27.7.1.1.3 [istream::sentry] + 27.7.1.2 [istream.formatted] + 27.7.1.2.1 [istream.formatted.reqmts] + 27.7.1.2.2 [istream.formatted.arithmetic] + 27.7.1.2.3 [istream::extractors] + 27.7.1.3 [istream.unformatted] + 27.7.1.4 [istream.manip] + 27.7.1.5 [iostreamclass] + 27.7.1.5.1 [iostream.cons] + 27.7.1.5.2 [iostream.dest] + 27.7.1.5.3 [iostream.assign] + 27.7.1.6 [istream.rvalue] + 27.7.2 [output.streams] + 27.7.2.1 [ostream] + 27.7.2.2 [ostream.cons] + 27.7.2.3 [ostream.assign] + 27.7.2.4 [ostream::sentry] + 27.7.2.5 [ostream.seeks] + 27.7.2.6 [ostream.formatted] + 27.7.2.6.1 [ostream.formatted.reqmts] + 27.7.2.6.2 [ostream.inserters.arithmetic] + 27.7.2.6.3 [ostream.inserters] + 27.7.2.6.4 [ostream.inserters.character] + 27.7.2.7 [ostream.unformatted] + 27.7.2.8 [ostream.manip] + 27.7.2.9 [ostream.rvalue] + 27.7.3 [std.manip] + 27.7.4 [ext.manip] + 27.8 [string.streams] + 27.8.1 [stringbuf] + 27.8.1.1 [stringbuf.cons] + 27.8.1.2 [stringbuf.assign] + 27.8.1.3 [stringbuf.members] + 27.8.1.4 [stringbuf.virtuals] + 27.8.2 [istringstream] + 27.8.2.1 [istringstream.cons] + 27.8.2.2 [istringstream.assign] + 27.8.2.3 [istringstream.members] + 27.8.3 [ostringstream] + 27.8.3.1 [ostringstream.cons] + 27.8.3.2 [ostringstream.assign] + 27.8.3.3 [ostringstream.members] + 27.8.4 [stringstream] + 27.8.5 [stringstream.cons] + 27.8.5.1 [stringstream.assign] + 27.8.6 [stringstream.members] + 27.9 [file.streams] + 27.9.1 [fstreams] + 27.9.1.1 [filebuf] + 27.9.1.2 [filebuf.cons] + 27.9.1.3 [filebuf.assign] + 27.9.1.4 [filebuf.members] + 27.9.1.5 [filebuf.virtuals] + 27.9.1.6 [ifstream] + 27.9.1.7 [ifstream.cons] + 27.9.1.8 [ifstream.assign] + 27.9.1.9 [ifstream.members] + 27.9.1.10 [ofstream] + 27.9.1.11 [ofstream.cons] + 27.9.1.12 [ofstream.assign] + 27.9.1.13 [ofstream.members] + 27.9.1.14 [fstream] + 27.9.1.15 [fstream.cons] + 27.9.1.16 [fstream.assign] + 27.9.1.17 [fstream.members] + 27.9.2 [c.files] 28 [re] - 28.1 [re.def] - 28.1.1 [defns.regex.collating.element] - 28.1.2 [defns.regex.finite.state.machine] - 28.1.3 [defns.regex.format.specifier] - 28.1.4 [defns.regex.matched] - 28.1.5 [defns.regex.primary.equivalence.class] - 28.1.6 [defns.regex.regular.expression] - 28.1.7 [defns.regex.subexpression] - 28.2 [re.req] - 28.3 [re.sum] + 28.1 [re.general] + 28.2 [re.def] + 28.2.1 [defns.regex.collating.element] + 28.2.2 [defns.regex.finite.state.machine] + 28.2.3 [defns.regex.format.specifier] + 28.2.4 [defns.regex.matched] + 28.2.5 [defns.regex.primary.equivalence.class] + 28.2.6 [defns.regex.regular.expression] + 28.2.7 [defns.regex.subexpression] + 28.3 [re.req] 28.4 [re.syn] 28.5 [re.const] 28.5.1 [re.synopt] @@ -1429,73 +1429,63 @@ 28.12.2.4 [re.tokiter.incr] 28.13 [re.grammar] 29 [atomics] - 29.1 [atomics.order] - 29.2 [atomics.lockfree] - 29.3 [atomics.types] - 29.3.1 [atomics.types.integral] - 29.3.2 [atomics.types.address] - 29.3.3 [atomics.types.generic] - 29.4 [atomics.types.operations] - 29.5 [atomics.flag] - 29.6 [atomics.fences] + 29.1 [atomics.general] + 29.2 [atomics.syn] + 29.3 [atomics.order] + 29.4 [atomics.lockfree] + 29.5 [atomics.types] + 29.5.1 [atomics.types.integral] + 29.5.2 [atomics.types.address] + 29.5.3 [atomics.types.generic] + 29.6 [atomics.types.operations] + 29.7 [atomics.flag] + 29.8 [atomics.fences] 30 [thread] - 30.1 [thread.req] - 30.1.1 [thread.req.paramname] - 30.1.2 [thread.req.exception] - 30.1.3 [thread.req.native] - 30.1.4 [thread.req.timing] - 30.2 [thread.threads] - 30.2.1 [thread.thread.class] - 30.2.1.1 [thread.thread.id] - 30.2.1.2 [thread.thread.constr] - 30.2.1.3 [thread.thread.destr] - 30.2.1.4 [thread.thread.assign] - 30.2.1.5 [thread.thread.member] - 30.2.1.6 [thread.thread.static] - 30.2.1.7 [thread.thread.algorithm] - 30.2.2 [thread.thread.this] - 30.3 [thread.mutex] - 30.3.1 [thread.mutex.requirements] - 30.3.1.1 [thread.mutex.class] - 30.3.1.2 [thread.mutex.recursive] - 30.3.2 [thread.timedmutex.requirements] - 30.3.2.1 [thread.timedmutex.class] - 30.3.2.2 [thread.timedmutex.recursive] - 30.3.3 [thread.lock] - 30.3.3.1 [thread.lock.guard] - 30.3.3.2 [thread.lock.unique] - 30.3.3.2.1 [thread.lock.unique.cons] - 30.3.3.2.2 [thread.lock.unique.locking] - 30.3.3.2.3 [thread.lock.unique.mod] - 30.3.3.2.4 [thread.lock.unique.obs] - 30.3.4 [thread.lock.algorithm] - 30.3.5 [thread.once] - 30.3.5.1 [thread.once.onceflag] - 30.3.5.2 [thread.once.callonce] - 30.4 [thread.condition] - 30.4.1 [thread.condition.condvar] - 30.4.2 [thread.condition.condvarany] - 30.5 [futures] - 30.5.1 [futures.overview] - 30.5.2 [futures.errors] - 30.5.3 [futures.future_error] - 30.5.4 [futures.unique_future] - 30.5.5 [future.shared_future] - 30.5.6 [futures.promise] - 30.5.7 [futures.allocators] - 30.5.8 [futures.task] -X [datetime] - X [datetime.req] - X [datetime.syn] - X [datetime.duration] - X [datetime.nanoseconds] - X [datetime.microseconds] - X [datetime.milliseconds] - X [datetime.seconds] - X [datetime.minutes] - X [datetime.hours] - X [datetime.system] - X [datetime.nonmembers] + 30.1 [thread.general] + 30.2 [thread.req] + 30.2.1 [thread.req.paramname] + 30.2.2 [thread.req.exception] + 30.2.3 [thread.req.native] + 30.2.4 [thread.req.timing] + 30.3 [thread.threads] + 30.3.1 [thread.thread.class] + 30.3.1.1 [thread.thread.id] + 30.3.1.2 [thread.thread.constr] + 30.3.1.3 [thread.thread.destr] + 30.3.1.4 [thread.thread.assign] + 30.3.1.5 [thread.thread.member] + 30.3.1.6 [thread.thread.static] + 30.3.1.7 [thread.thread.algorithm] + 30.3.2 [thread.thread.this] + 30.4 [thread.mutex] + 30.4.1 [thread.mutex.requirements] + 30.4.1.1 [thread.mutex.class] + 30.4.1.2 [thread.mutex.recursive] + 30.4.2 [thread.timedmutex.requirements] + 30.4.2.1 [thread.timedmutex.class] + 30.4.2.2 [thread.timedmutex.recursive] + 30.4.3 [thread.lock] + 30.4.3.1 [thread.lock.guard] + 30.4.3.2 [thread.lock.unique] + 30.4.3.2.1 [thread.lock.unique.cons] + 30.4.3.2.2 [thread.lock.unique.locking] + 30.4.3.2.3 [thread.lock.unique.mod] + 30.4.3.2.4 [thread.lock.unique.obs] + 30.4.4 [thread.lock.algorithm] + 30.4.5 [thread.once] + 30.4.5.1 [thread.once.onceflag] + 30.4.5.2 [thread.once.callonce] + 30.5 [thread.condition] + 30.5.1 [thread.condition.condvar] + 30.5.2 [thread.condition.condvarany] + 30.6 [futures] + 30.6.1 [futures.overview] + 30.6.2 [futures.errors] + 30.6.3 [futures.future_error] + 30.6.4 [futures.promise] + 30.6.5 [futures.unique_future] + 30.6.6 [future.shared_future] + 30.6.7 [futures.task] A [gram] A.1 [gram.key] A.2 [gram.lex] @@ -1572,7 +1562,6 @@ D [depr] D.10.3 [std.iterator.tags] D.10.4 [iterator.backward] E [xref] -X [garbage.collection] TR1 1 [tr.intro] TR1 1.1 [tr.description] diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index a3ffb48281d1..9433c1752e53 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -50,6 +50,7 @@ #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" +#include "llvm/LLVMContext.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringExtras.h" @@ -660,6 +661,11 @@ PICLevel("pic-level", llvm::cl::desc("Value for __PIC__")); static llvm::cl::opt<bool> StaticDefine("static-define", llvm::cl::desc("Should __STATIC__ be defined")); +static llvm::cl::opt<int> +StackProtector("stack-protector", + llvm::cl::desc("Enable stack protectors"), + llvm::cl::init(-1)); + static void InitializeLanguageStandard(LangOptions &Options, LangKind LK, TargetInfo *Target, const llvm::StringMap<bool> &Features) { @@ -779,6 +785,9 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK, if (AccessControl) Options.AccessControl = 1; + // OpenCL and C++ both have bool, true, false keywords. + Options.Bool = Options.OpenCL | Options.CPlusPlus; + Options.MathErrno = MathErrno; Options.InstantiationDepth = TemplateDepth; @@ -814,6 +823,15 @@ static void InitializeLanguageStandard(LangOptions &Options, LangKind LK, Options.Static = StaticDefine; + switch (StackProtector) { + default: + assert(StackProtector <= 2 && "Invalid value for -stack-protector"); + case -1: break; + case 0: Options.setStackProtectorMode(LangOptions::SSPOff); break; + case 1: Options.setStackProtectorMode(LangOptions::SSPOn); break; + case 2: Options.setStackProtectorMode(LangOptions::SSPReq); break; + } + if (MainFileName.getPosition()) Options.setMainFileName(MainFileName.c_str()); } @@ -1729,7 +1747,8 @@ static llvm::raw_ostream* ComputeOutFile(const std::string& InFile, /// static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF, const std::string &InFile, ProgActions PA, - const llvm::StringMap<bool> &Features) { + const llvm::StringMap<bool> &Features, + llvm::LLVMContext& Context) { llvm::OwningPtr<llvm::raw_ostream> OS; llvm::OwningPtr<ASTConsumer> Consumer; bool ClearSourceMgr = false; @@ -1796,7 +1815,7 @@ static void ProcessInputFile(Preprocessor &PP, PreprocessorFactory &PPF, InitializeCompileOptions(Opts, PP.getLangOptions(), Features); Consumer.reset(CreateBackendConsumer(Act, PP.getDiagnostics(), PP.getLangOptions(), Opts, InFile, - OS.get())); + OS.get(), Context)); break; } @@ -2088,9 +2107,10 @@ InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input files>")); int main(int argc, char **argv) { llvm::sys::PrintStackTraceOnErrorSignal(); llvm::PrettyStackTraceProgram X(argc, argv); + llvm::LLVMContext Context; llvm::cl::ParseCommandLineOptions(argc, argv, "LLVM 'Clang' Compiler: http://clang.llvm.org\n"); - + llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); @@ -2264,7 +2284,7 @@ int main(int argc, char **argv) { ((PathDiagnosticClient*)DiagClient.get())->SetPreprocessor(PP.get()); // Process the source file. - ProcessInputFile(*PP, PPFactory, InFile, ProgAction, Features); + ProcessInputFile(*PP, PPFactory, InFile, ProgAction, Features, Context); HeaderInfo.ClearFileInfo(); DiagClient->setLangOptions(0); diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index 804bef4058c9..323283e653b4 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -219,7 +219,7 @@ int main(int argc, const char **argv) { int Res = 0; if (C.get()) - Res = C->Execute(); + Res = TheDriver.ExecuteCompilation(*C); llvm::llvm_shutdown(); diff --git a/tools/index-test/index-test.cpp b/tools/index-test/index-test.cpp index 5606e7576690..552b7b01498a 100644 --- a/tools/index-test/index-test.cpp +++ b/tools/index-test/index-test.cpp @@ -125,16 +125,19 @@ int main(int argc, char **argv) { if (Point.D) { llvm::raw_ostream &OS = llvm::outs(); - assert(Point.D && "If no node was found we should have exited with error"); OS << "Declaration node at point: " << Point.D->getDeclKindName() << " "; if (NamedDecl *ND = dyn_cast<NamedDecl>(Point.D)) OS << ND->getNameAsString(); OS << "\n"; + if (const char *Comment = AST->getASTContext().getCommentForDecl(Point.D)) + OS << "Comment associated with this declaration:\n" << Comment << "\n"; + if (Point.Node) { OS << "Statement node at point: " << Point.Node->getStmtClassName() << " "; - Point.Node->printPretty(OS, AST->getASTContext()); + Point.Node->printPretty(OS, AST->getASTContext(), 0, + PrintingPolicy(AST->getASTContext().getLangOptions())); OS << "\n"; } } diff --git a/utils/test/TestRunner.py b/utils/test/TestRunner.py index f1a1365f6bf4..9020622350dc 100755 --- a/utils/test/TestRunner.py +++ b/utils/test/TestRunner.py @@ -37,7 +37,8 @@ class TestStatus: kNames = ['Pass','XFail','Fail','XPass','NoRunLine','Invalid'] @staticmethod - def getName(code): return TestStatus.kNames[code] + def getName(code): + return TestStatus.kNames[code] def mkdir_p(path): if not path: diff --git a/www/analyzer/latest_checker.html.incl b/www/analyzer/latest_checker.html.incl index 62b9c540b409..4f030bbc2f8b 100644 --- a/www/analyzer/latest_checker.html.incl +++ b/www/analyzer/latest_checker.html.incl @@ -1 +1 @@ -<b><a href="http://checker.minormatter.com/checker-0.211.tar.bz2">checker-0.211.tar.bz2</a></b> (built June 15, 2009) +<b><a href="http://checker.minormatter.com/checker-0.212.tar.bz2">checker-0.212.tar.bz2</a></b> (built July 2, 2009) diff --git a/www/cxx_status.html b/www/cxx_status.html index 19d3a5c7dbe8..2af2b3294623 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -24,6 +24,7 @@ <!--*************************************************************************--> <h1>C++ Support in Clang</h1> <!--*************************************************************************--> +<p>Last updated: $Date: 2009-06-27 21:33:58 +0200 (Sat, 27 Jun 2009) $</p> <p> This page tracks the status of C++ support in Clang.<br> |