diff options
Diffstat (limited to 'include/clang')
80 files changed, 1881 insertions, 1097 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 4f29e5d8a618..3fc5aabde32c 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -45,6 +45,8 @@ namespace clang { class SourceManager; class TargetInfo; // Decls + class CXXMethodDecl; + class CXXRecordDecl; class Decl; class FieldDecl; class ObjCIvarDecl; @@ -57,6 +59,7 @@ namespace clang { class TypeDecl; class TypedefDecl; class UsingDecl; + class UsingShadowDecl; namespace Builtin { class Context; } @@ -105,6 +108,9 @@ class ASTContext { llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> ASTRecordLayouts; llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts; + /// KeyFunctions - A cache mapping from CXXRecordDecls to key functions. + llvm::DenseMap<const CXXRecordDecl*, const CXXMethodDecl*> KeyFunctions; + /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; @@ -183,8 +189,10 @@ class ASTContext { llvm::DenseMap<const VarDecl *, MemberSpecializationInfo *> InstantiatedFromStaticDataMember; - /// \brief Keeps track of the UnresolvedUsingDecls from which UsingDecls - /// where created during instantiation. + /// \brief Keeps track of the declaration from which a UsingDecl was + /// created during instantiation. The source declaration is always + /// a UsingDecl, an UnresolvedUsingValueDecl, or an + /// UnresolvedUsingTypenameDecl. /// /// For example: /// \code @@ -203,8 +211,10 @@ class ASTContext { /// /// This mapping will contain an entry that maps from the UsingDecl in /// B<int> to the UnresolvedUsingDecl in B<T>. - llvm::DenseMap<UsingDecl *, NamedDecl *> - InstantiatedFromUnresolvedUsingDecl; + llvm::DenseMap<UsingDecl *, NamedDecl *> InstantiatedFromUsingDecl; + + llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*> + InstantiatedFromUsingShadowDecl; llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; @@ -282,14 +292,18 @@ public: void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, TemplateSpecializationKind TSK); - /// \brief If this using decl is instantiated from an unresolved using decl, + /// \brief If the given using decl is an instantiation of a + /// (possibly unresolved) using decl from a template instantiation, /// return it. - NamedDecl *getInstantiatedFromUnresolvedUsingDecl(UsingDecl *UUD); + NamedDecl *getInstantiatedFromUsingDecl(UsingDecl *Inst); - /// \brief Note that the using decl \p Inst is an instantiation of - /// the unresolved using decl \p Tmpl of a class template. - void setInstantiatedFromUnresolvedUsingDecl(UsingDecl *Inst, NamedDecl *Tmpl); + /// \brief Remember that the using decl \p Inst is an instantiation + /// of the using decl \p Pattern of a class template. + void setInstantiatedFromUsingDecl(UsingDecl *Inst, NamedDecl *Pattern); + void setInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst, + UsingShadowDecl *Pattern); + UsingShadowDecl *getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst); FieldDecl *getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field); @@ -380,9 +394,10 @@ public: /// equivalent to calling T.withConst(). QualType getConstType(QualType T) { return T.withConst(); } - /// getNoReturnType - Add the noreturn attribute to the given type which must - /// be a FunctionType or a pointer to an allowable type or a BlockPointer. - QualType getNoReturnType(QualType T); + /// getNoReturnType - Add or remove the noreturn attribute to the given type + /// which must be a FunctionType or a pointer to an allowable type or a + /// BlockPointer. + QualType getNoReturnType(QualType T, bool AddNoReturn = true); /// getComplexType - Return the uniqued reference to the type for a complex /// number with the specified element type. @@ -569,7 +584,7 @@ public: /// getSizeType - Return the unique type for "size_t" (C99 7.17), defined /// in <stddef.h>. The sizeof operator requires this (C99 6.5.3.4p4). - QualType getSizeType() const; + CanQualType getSizeType() const; /// getWCharType - In C++, this returns the unique wchar_t type. In C99, this /// returns a type compatible with the type defined in <stddef.h> as defined @@ -735,12 +750,12 @@ public: DeclarationName getNameForTemplate(TemplateName Name); + TemplateName getOverloadedTemplateName(NamedDecl * const *Begin, + NamedDecl * const *End); + TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateDecl *Template); - TemplateName getQualifiedTemplateName(NestedNameSpecifier *NNS, - bool TemplateKeyword, - OverloadedFunctionDecl *Template); TemplateName getDependentTemplateName(NestedNameSpecifier *NNS, const IdentifierInfo *Name); @@ -843,6 +858,13 @@ public: const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D); + /// getKeyFunction - Get the key function for the given record decl. + /// The key function is, according to the Itanium C++ ABI section 5.2.3: + /// + /// ...the first non-pure virtual function that is not inline at the point + /// of class definition. + const CXXMethodDecl *getKeyFunction(const CXXRecordDecl *RD); + void CollectObjCIvars(const ObjCInterfaceDecl *OI, llvm::SmallVectorImpl<FieldDecl*> &Fields); @@ -1108,9 +1130,9 @@ public: void setObjCImplementation(ObjCCategoryDecl *CatD, ObjCCategoryImplDecl *ImplD); - /// \brief Allocate an uninitialized DeclaratorInfo. + /// \brief Allocate an uninitialized TypeSourceInfo. /// - /// The caller should initialize the memory held by DeclaratorInfo using + /// The caller should initialize the memory held by TypeSourceInfo using /// the TypeLoc wrappers. /// /// \param T the type that will be the basis for type source info. This type @@ -1119,13 +1141,13 @@ public: /// /// \param Size the size of the type info to create, or 0 if the size /// should be calculated based on the type. - DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0); + TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0); - /// \brief Allocate a DeclaratorInfo where all locations have been + /// \brief Allocate a TypeSourceInfo where all locations have been /// initialized to a given location, which defaults to the empty /// location. - DeclaratorInfo * - getTrivialDeclaratorInfo(QualType T, SourceLocation Loc = SourceLocation()); + TypeSourceInfo * + getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()); private: ASTContext(const ASTContext&); // DO NOT IMPLEMENT diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 9b1187770f6a..af8d23692e19 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -172,6 +172,12 @@ inline bool operator!=(CanQual<T> x, CanQual<U> y) { /// \brief Represents a canonical, potentially-qualified type. typedef CanQual<Type> CanQualType; +inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, + CanQualType T) { + DB << static_cast<QualType>(T); + return DB; +} + //----------------------------------------------------------------------------// // Internal proxy classes used by canonical types //----------------------------------------------------------------------------// diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index f7944771efce..ff2b30227860 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -35,17 +35,17 @@ class TypeLoc; /// /// A client can read the relevant info using TypeLoc wrappers, e.g: /// @code -/// TypeLoc TL = DeclaratorInfo->getTypeLoc(); +/// TypeLoc TL = TypeSourceInfo->getTypeLoc(); /// if (PointerLoc *PL = dyn_cast<PointerLoc>(&TL)) /// PL->getStarLoc().print(OS, SrcMgr); /// @endcode /// -class DeclaratorInfo { +class TypeSourceInfo { QualType Ty; // Contains a memory block after the class, used for type source information, // allocated by ASTContext. friend class ASTContext; - DeclaratorInfo(QualType ty) : Ty(ty) { } + TypeSourceInfo(QualType ty) : Ty(ty) { } public: /// \brief Return the type wrapped by this type source info. QualType getType() const { return Ty; } @@ -322,18 +322,18 @@ public: }; /// \brief Represents a ValueDecl that came out of a declarator. -/// Contains type source information through DeclaratorInfo. +/// Contains type source information through TypeSourceInfo. class DeclaratorDecl : public ValueDecl { - DeclaratorInfo *DeclInfo; + TypeSourceInfo *DeclInfo; protected: DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, DeclaratorInfo *DInfo) - : ValueDecl(DK, DC, L, N, T), DeclInfo(DInfo) {} + DeclarationName N, QualType T, TypeSourceInfo *TInfo) + : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} public: - DeclaratorInfo *getDeclaratorInfo() const { return DeclInfo; } - void setDeclaratorInfo(DeclaratorInfo *DInfo) { DeclInfo = DInfo; } + TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; } + void setTypeSourceInfo(TypeSourceInfo *TInfo) { DeclInfo = TInfo; } SourceLocation getTypeSpecStartLoc() const; @@ -348,15 +348,23 @@ public: /// which it was evaluated (if any), and whether or not the statement /// is an integral constant expression (if known). struct EvaluatedStmt { - EvaluatedStmt() : WasEvaluated(false), CheckedICE(false), IsICE(false) { } + EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false), + CheckingICE(false), IsICE(false) { } /// \brief Whether this statement was already evaluated. bool WasEvaluated : 1; + /// \brief Whether this statement is being evaluated. + bool IsEvaluating : 1; + /// \brief Whether we already checked whether this statement was an /// integral constant expression. bool CheckedICE : 1; + /// \brief Whether we are checking whether this statement is an + /// integral constant expression. + bool CheckingICE : 1; + /// \brief Whether this statement is an integral constant /// expression. Only valid if CheckedICE is true. bool IsICE : 1; @@ -432,8 +440,8 @@ private: friend class StmtIteratorBase; protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, DeclaratorInfo *DInfo, StorageClass SC) - : DeclaratorDecl(DK, DC, L, Id, T, DInfo), Init(), + QualType T, TypeSourceInfo *TInfo, StorageClass SC) + : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), DeclaredInCondition(false) { SClass = SC; @@ -453,7 +461,7 @@ public: static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, DeclaratorInfo *DInfo, StorageClass S); + QualType T, TypeSourceInfo *TInfo, StorageClass S); virtual ~VarDecl(); virtual void Destroy(ASTContext& C); @@ -504,23 +512,45 @@ public: void setInit(ASTContext &C, Expr *I); - /// \brief Note that constant evaluation has computed the given - /// value for this variable's initializer. - void setEvaluatedValue(ASTContext &C, const APValue &Value) const { + EvaluatedStmt *EnsureEvaluatedStmt() const { EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); if (!Eval) { Stmt *S = Init.get<Stmt *>(); - Eval = new (C) EvaluatedStmt; + Eval = new (getASTContext()) EvaluatedStmt; Eval->Value = S; Init = Eval; } + return Eval; + } + + /// \brief Check whether we are in the process of checking whether the + /// initializer can be evaluated. + bool isEvaluatingValue() const { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) + return Eval->IsEvaluating; + return false; + } + + /// \brief Note that we now are checking whether the initializer can be + /// evaluated. + void setEvaluatingValue() const { + EvaluatedStmt *Eval = EnsureEvaluatedStmt(); + Eval->IsEvaluating = true; + } + + /// \brief Note that constant evaluation has computed the given + /// value for this variable's initializer. + void setEvaluatedValue(const APValue &Value) const { + EvaluatedStmt *Eval = EnsureEvaluatedStmt(); + Eval->IsEvaluating = false; Eval->WasEvaluated = true; Eval->Evaluated = Value; } /// \brief Return the already-evaluated value of this variable's - /// initializer, or NULL if the value is not yet known. + /// initializer, or NULL if the value is not yet known. Returns pointer + /// to untyped APValue if the value could not be evaluated. APValue *getEvaluatedValue() const { if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) if (Eval->WasEvaluated) @@ -548,17 +578,27 @@ public: return Init.get<EvaluatedStmt *>()->IsICE; } - /// \brief Note that we now know whether the initializer is an + /// \brief Check whether we are in the process of checking the initializer + /// is an integral constant expression. + bool isCheckingICE() const { + if (EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>()) + return Eval->CheckingICE; + + return false; + } + + /// \brief Note that we now are checking whether the initializer is an /// integral constant expression. - void setInitKnownICE(ASTContext &C, bool IsICE) const { - EvaluatedStmt *Eval = Init.dyn_cast<EvaluatedStmt *>(); - if (!Eval) { - Stmt *S = Init.get<Stmt *>(); - Eval = new (C) EvaluatedStmt; - Eval->Value = S; - Init = Eval; - } + void setCheckingICE() const { + EvaluatedStmt *Eval = EnsureEvaluatedStmt(); + Eval->CheckingICE = true; + } + /// \brief Note that we now know whether the initializer is an + /// integral constant expression. + void setInitKnownICE(bool IsICE) const { + EvaluatedStmt *Eval = EnsureEvaluatedStmt(); + Eval->CheckingICE = false; Eval->CheckedICE = true; Eval->IsICE = IsICE; } @@ -712,7 +752,7 @@ class ImplicitParamDecl : public VarDecl { protected: ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType Tw) - : VarDecl(DK, DC, L, Id, Tw, /*DInfo=*/0, VarDecl::None) {} + : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None) {} public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, @@ -739,16 +779,16 @@ class ParmVarDecl : public VarDecl { protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) - : VarDecl(DK, DC, L, Id, T, DInfo, S), objcDeclQualifier(OBJC_TQ_None) { + : VarDecl(DK, DC, L, Id, T, TInfo, S), objcDeclQualifier(OBJC_TQ_None) { setDefaultArg(DefArg); } public: static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,IdentifierInfo *Id, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg); ObjCDeclQualifier getObjCDeclQualifier() const { @@ -822,8 +862,8 @@ public: } QualType getOriginalType() const { - if (getDeclaratorInfo()) - return getDeclaratorInfo()->getType(); + if (getTypeSourceInfo()) + return getTypeSourceInfo()->getType(); return getType(); } @@ -907,9 +947,9 @@ private: protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName N, QualType T, DeclaratorInfo *DInfo, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass S, bool isInline) - : DeclaratorDecl(DK, DC, L, N, T, DInfo), + : DeclaratorDecl(DK, DC, L, N, T, TInfo), DeclContext(DK), ParamInfo(0), Body(), SClass(S), IsInline(isInline), @@ -936,7 +976,7 @@ public: static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, - DeclaratorInfo *DInfo, + TypeSourceInfo *TInfo, StorageClass S = None, bool isInline = false, bool hasWrittenPrototype = true); @@ -1272,15 +1312,15 @@ class FieldDecl : public DeclaratorDecl { Expr *BitWidth; protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable) - : DeclaratorDecl(DK, DC, L, Id, T, DInfo), Mutable(Mutable), BitWidth(BW) { + : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Mutable(Mutable), BitWidth(BW) { } public: static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, - DeclaratorInfo *DInfo, Expr *BW, bool Mutable); + TypeSourceInfo *TInfo, Expr *BW, bool Mutable); /// isMutable - Determines whether this field is mutable (C++ only). bool isMutable() const { return Mutable; } @@ -1383,28 +1423,28 @@ public: class TypedefDecl : public TypeDecl { /// UnderlyingType - This is the type the typedef is set to. - DeclaratorInfo *DInfo; + TypeSourceInfo *TInfo; TypedefDecl(DeclContext *DC, SourceLocation L, - IdentifierInfo *Id, DeclaratorInfo *DInfo) - : TypeDecl(Typedef, DC, L, Id), DInfo(DInfo) {} + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} virtual ~TypedefDecl() {} public: static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - DeclaratorInfo *DInfo); + TypeSourceInfo *TInfo); - DeclaratorInfo *getTypeDeclaratorInfo() const { - return DInfo; + TypeSourceInfo *getTypeSourceInfo() const { + return TInfo; } QualType getUnderlyingType() const { - return DInfo->getType(); + return TInfo->getType(); } - void setTypeDeclaratorInfo(DeclaratorInfo *newType) { - DInfo = newType; + void setTypeSourceInfo(TypeSourceInfo *newType) { + TInfo = newType; } // Implement isa/cast/dyncast/etc. @@ -1554,6 +1594,12 @@ class EnumDecl : public TagDecl { /// have a different type than this does. QualType IntegerType; + /// PromotionType - The integer type that values of this type should + /// promote to. In C, enumerators are generally of an integer type + /// directly, but gcc-style large enumerators (and all enumerators + /// in C++) are of the enum type instead. + QualType PromotionType; + /// \brief If the enumeration was instantiated from an enumeration /// within a class or function template, this pointer refers to the /// enumeration declared within the template. @@ -1583,7 +1629,8 @@ public: /// declaration as being defined; it's enumerators have already been /// added (via DeclContext::addDecl). NewType is the new underlying /// type of the enumeration type. - void completeDefinition(ASTContext &C, QualType NewType); + void completeDefinition(ASTContext &C, QualType NewType, + QualType PromotionType); // enumerator_iterator - Iterates through the enumerators of this // enumeration. @@ -1597,6 +1644,13 @@ public: return enumerator_iterator(this->decls_end()); } + /// getPromotionType - Return the integer type that enumerators + /// should promote to. + QualType getPromotionType() const { return PromotionType; } + + /// \brief Set the promotion type. + void setPromotionType(QualType T) { PromotionType = T; } + /// getIntegerType - Return the integer type this enum decl corresponds to. /// This returns a null qualtype for an enum forward definition. QualType getIntegerType() const { return IntegerType; } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index e1f948fdd550..497f86347a86 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -91,7 +91,7 @@ public: IDNS_Ordinary = 0x8, IDNS_ObjCProtocol = 0x10, IDNS_ObjCImplementation = 0x20, - IDNS_ObjCCategoryImpl = 0x40, + IDNS_ObjCCategoryName = 0x40, IDNS_OrdinaryFriend = 0x80, IDNS_TagFriend = 0x100, IDNS_Using = 0x200 @@ -916,6 +916,9 @@ public: /// only happens with friends. void addHiddenDecl(Decl *D); + /// @brief Removes a declaration from this context. + void removeDecl(Decl *D); + /// lookup_iterator - An iterator that provides access to the results /// of looking up a name within this context. typedef NamedDecl **lookup_iterator; @@ -1003,6 +1006,8 @@ public: static bool classof(const Name##Decl *D) { return true; } #include "clang/AST/DeclNodes.def" + void dumpDeclContext() const; + private: void LoadLexicalDeclsFromExternalStorage() const; void LoadVisibleDeclsFromExternalStorage() const; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 990403e7dc2e..5507e99e45a9 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -88,108 +88,6 @@ namespace llvm { namespace clang { -/// OverloadedFunctionDecl - An instance of this class represents a -/// set of overloaded functions. All of the functions have the same -/// name and occur within the same scope. -/// -/// An OverloadedFunctionDecl has no ownership over the FunctionDecl -/// nodes it contains. Rather, the FunctionDecls are owned by the -/// enclosing scope (which also owns the OverloadedFunctionDecl -/// node). OverloadedFunctionDecl is used primarily to store a set of -/// overloaded functions for name lookup. -class OverloadedFunctionDecl : public NamedDecl { -protected: - OverloadedFunctionDecl(DeclContext *DC, DeclarationName N) - : NamedDecl(OverloadedFunction, DC, SourceLocation(), N) { } - - /// Functions - the set of overloaded functions contained in this - /// overload set. - llvm::SmallVector<AnyFunctionDecl, 4> Functions; - - // FIXME: This should go away when we stop using - // OverloadedFunctionDecl to store conversions in CXXRecordDecl. - friend class CXXRecordDecl; - -public: - typedef llvm::SmallVector<AnyFunctionDecl, 4>::iterator function_iterator; - typedef llvm::SmallVector<AnyFunctionDecl, 4>::const_iterator - function_const_iterator; - - static OverloadedFunctionDecl *Create(ASTContext &C, DeclContext *DC, - DeclarationName N); - - /// \brief Add a new overloaded function or function template to the set - /// of overloaded function templates. - void addOverload(AnyFunctionDecl F); - - function_iterator function_begin() { return Functions.begin(); } - function_iterator function_end() { return Functions.end(); } - function_const_iterator function_begin() const { return Functions.begin(); } - function_const_iterator function_end() const { return Functions.end(); } - - /// \brief Returns the number of overloaded functions stored in - /// this set. - unsigned size() const { return Functions.size(); } - - // Implement isa/cast/dyncast/etc. - static bool classof(const Decl *D) { - return D->getKind() == OverloadedFunction; - } - static bool classof(const OverloadedFunctionDecl *D) { return true; } -}; - -/// \brief Provides uniform iteration syntax for an overload set, function, -/// or function template. -class OverloadIterator { - /// \brief An overloaded function set, function declaration, or - /// function template declaration. - NamedDecl *D; - - /// \brief If the declaration is an overloaded function set, this is the - /// iterator pointing to the current position within that overloaded - /// function set. - OverloadedFunctionDecl::function_iterator Iter; - -public: - typedef AnyFunctionDecl value_type; - typedef value_type reference; - typedef NamedDecl *pointer; - typedef int difference_type; - typedef std::forward_iterator_tag iterator_category; - - OverloadIterator() : D(0) { } - - OverloadIterator(FunctionDecl *FD) : D(FD) { } - OverloadIterator(FunctionTemplateDecl *FTD) - : D(reinterpret_cast<NamedDecl*>(FTD)) { } - OverloadIterator(OverloadedFunctionDecl *Ovl) - : D(Ovl), Iter(Ovl->function_begin()) { } - - OverloadIterator(NamedDecl *ND); - - reference operator*() const; - - pointer operator->() const { return (**this).get(); } - - OverloadIterator &operator++(); - - OverloadIterator operator++(int) { - OverloadIterator Temp(*this); - ++(*this); - return Temp; - } - - bool Equals(const OverloadIterator &Other) const; -}; - -inline bool operator==(const OverloadIterator &X, const OverloadIterator &Y) { - return X.Equals(Y); -} - -inline bool operator!=(const OverloadIterator &X, const OverloadIterator &Y) { - return !(X == Y); -} - /// CXXBaseSpecifier - A base class of a C++ class. /// /// Each CXXBaseSpecifier represents a single, direct base class (or @@ -210,6 +108,7 @@ class CXXBaseSpecifier { /// Range - The source code range that covers the full base /// specifier, including the "virtual" (if present) and access /// specifier (if present). + // FIXME: Move over to a TypeLoc! SourceRange Range; /// Virtual - Whether this is a virtual base class or not. @@ -635,6 +534,10 @@ public: /// [dcl.init.aggr]). void setAggregate(bool Agg) { Aggregate = Agg; } + /// setMethodAsVirtual - Make input method virtual and set the necesssary + /// special function bits and other bits accordingly. + void setMethodAsVirtual(FunctionDecl *Method); + /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class /// that is an aggregate that has no non-static non-POD data members, no /// reference data members, no user-defined copy assignment operator and no @@ -753,7 +656,7 @@ public: /// \brief Determine whether this particular class is a specialization or /// instantiation of a class template or member class of a class template, /// and how it was instantiated or specialized. - TemplateSpecializationKind getTemplateSpecializationKind(); + TemplateSpecializationKind getTemplateSpecializationKind() const; /// \brief Set the kind of specialization or template instantiation this is. void setTemplateSpecializationKind(TemplateSpecializationKind TSK); @@ -762,7 +665,7 @@ public: CXXConstructorDecl *getDefaultConstructor(ASTContext &Context); /// getDestructor - Returns the destructor decl for this class. - const CXXDestructorDecl *getDestructor(ASTContext &Context); + CXXDestructorDecl *getDestructor(ASTContext &Context); /// isLocalClass - If the class is a local class [class.local], returns /// the enclosing function declaration. @@ -802,6 +705,30 @@ public: /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than /// tangling input and output in \p Paths bool isDerivedFrom(CXXRecordDecl *Base, CXXBasePaths &Paths) const; + + /// \brief Determine whether this class is provably not derived from + /// the type \p Base. + bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const; + + /// \brief Function type used by forallBases() as a callback. + /// + /// \param Base the definition of the base class + /// + /// \returns true if this base matched the search criteria + typedef bool ForallBasesCallback(const CXXRecordDecl *BaseDefinition, + void *UserData); + + /// \brief Determines if the given callback holds for all the direct + /// or indirect base classes of this type. + /// + /// The class itself does not count as a base class. This routine + /// returns false if the class has non-computable base classes. + /// + /// \param AllowShortCircuit if false, forces the callback to be called + /// for every base class, even if a dependent or non-matching base was + /// found. + bool forallBases(ForallBasesCallback *BaseMatches, void *UserData, + bool AllowShortCircuit = true) const; /// \brief Function type used by lookupInBases() to determine whether a /// specific base class subobject matches the lookup criteria. @@ -902,15 +829,15 @@ public: class CXXMethodDecl : public FunctionDecl { protected: CXXMethodDecl(Kind DK, CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, DeclaratorInfo *DInfo, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isStatic, bool isInline) - : FunctionDecl(DK, RD, L, N, T, DInfo, (isStatic ? Static : None), + : FunctionDecl(DK, RD, L, N, T, TInfo, (isStatic ? Static : None), isInline) {} public: static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, bool isStatic = false, bool isInline = false); @@ -968,6 +895,8 @@ public: return getType()->getAs<FunctionProtoType>()->getTypeQuals(); } + bool hasInlineBody() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= CXXMethod && D->getKind() <= CXXConversion; @@ -990,12 +919,13 @@ public: /// }; /// @endcode class CXXBaseOrMemberInitializer { - /// BaseOrMember - This points to the entity being initialized, - /// which is either a base class (a Type) or a non-static data - /// member. When the low bit is 1, it's a base - /// class; when the low bit is 0, it's a member. - uintptr_t BaseOrMember; - + /// \brief Either the base class name (stored as a TypeSourceInfo*) or the + /// field being initialized. + llvm::PointerUnion<TypeSourceInfo *, FieldDecl *> BaseOrMember; + + /// \brief The source location for the field name. + SourceLocation MemberLocation; + /// Args - The arguments used to initialize the base or member. Stmt **Args; unsigned NumArgs; @@ -1020,8 +950,8 @@ class CXXBaseOrMemberInitializer { /// and AnonUnionMember holds field decl for au_i1. llvm::PointerUnion<CXXConstructorDecl *, FieldDecl *> CtorOrAnonUnion; - /// IdLoc - Location of the id in ctor-initializer list. - SourceLocation IdLoc; + /// LParenLoc - Location of the left paren of the ctor-initializer. + SourceLocation LParenLoc; /// RParenLoc - Location of the right paren of the ctor-initializer. SourceLocation RParenLoc; @@ -1029,18 +959,22 @@ class CXXBaseOrMemberInitializer { public: /// CXXBaseOrMemberInitializer - Creates a new base-class initializer. explicit - CXXBaseOrMemberInitializer(QualType BaseType, Expr **Args, unsigned NumArgs, - CXXConstructorDecl *C, - SourceLocation L, SourceLocation R); + CXXBaseOrMemberInitializer(ASTContext &Context, + TypeSourceInfo *TInfo, CXXConstructorDecl *C, + SourceLocation L, + Expr **Args, unsigned NumArgs, + SourceLocation R); /// CXXBaseOrMemberInitializer - Creates a new member initializer. explicit - CXXBaseOrMemberInitializer(FieldDecl *Member, Expr **Args, unsigned NumArgs, - CXXConstructorDecl *C, - SourceLocation L, SourceLocation R); + CXXBaseOrMemberInitializer(ASTContext &Context, + FieldDecl *Member, SourceLocation MemberLoc, + CXXConstructorDecl *C, SourceLocation L, + Expr **Args, unsigned NumArgs, + SourceLocation R); - /// ~CXXBaseOrMemberInitializer - Destroy the base or member initializer. - ~CXXBaseOrMemberInitializer(); + /// \brief Destroy the base or member initializer. + void Destroy(ASTContext &Context); /// arg_iterator - Iterates through the member initialization /// arguments. @@ -1050,54 +984,54 @@ public: /// arguments. typedef ConstExprIterator const_arg_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; } + bool isBaseInitializer() const { return BaseOrMember.is<TypeSourceInfo*>(); } /// isMemberInitializer - Returns true when this initializer is /// initializing a non-static data member. - bool isMemberInitializer() const { return (BaseOrMember & 0x1) == 0; } - - /// getBaseClass - If this is a base class initializer, returns the - /// type used to specify the initializer. The resulting type will be - /// a class type or a typedef of a class type. If this is not a base - /// class initializer, returns NULL. - Type *getBaseClass() { - if (isBaseInitializer()) - return reinterpret_cast<Type*>(BaseOrMember & ~0x01); - else - return 0; - } + bool isMemberInitializer() const { return BaseOrMember.is<FieldDecl*>(); } - /// getBaseClass - If this is a base class initializer, returns the - /// type used to specify the initializer. The resulting type will be - /// a class type or a typedef of a class type. If this is not a base - /// class initializer, returns NULL. - const Type *getBaseClass() const { - if (isBaseInitializer()) - return reinterpret_cast<const Type*>(BaseOrMember & ~0x01); - else - return 0; - } + /// If this is a base class initializer, returns the type of the + /// base class with location information. Otherwise, returns an NULL + /// type location. + TypeLoc getBaseClassLoc() const; + /// If this is a base class initializer, returns the type of the base class. + /// Otherwise, returns NULL. + const Type *getBaseClass() const; + Type *getBaseClass(); + + /// \brief Returns the declarator information for a base class initializer. + TypeSourceInfo *getBaseClassInfo() const { + return BaseOrMember.dyn_cast<TypeSourceInfo *>(); + } + /// getMember - If this is a member initializer, returns the /// declaration of the non-static data member being /// initialized. Otherwise, returns NULL. FieldDecl *getMember() { if (isMemberInitializer()) - return reinterpret_cast<FieldDecl *>(BaseOrMember); + return BaseOrMember.get<FieldDecl*>(); else return 0; } - void setMember(FieldDecl * anonUnionField) { - BaseOrMember = reinterpret_cast<uintptr_t>(anonUnionField); + SourceLocation getMemberLocation() const { + return MemberLocation; } + void setMember(FieldDecl *Member) { + assert(isMemberInitializer()); + BaseOrMember = Member; + } + + /// \brief Determine the source location of the initializer. + SourceLocation getSourceLocation() const; + + /// \brief Determine the source range covering the entire initializer. + SourceRange getSourceRange() const; + FieldDecl *getAnonUnionMember() const { return CtorOrAnonUnion.dyn_cast<FieldDecl *>(); } @@ -1109,7 +1043,7 @@ public: return CtorOrAnonUnion.dyn_cast<CXXConstructorDecl *>(); } - SourceLocation getSourceLocation() const { return IdLoc; } + SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } /// arg_begin() - Retrieve an iterator to the first initializer argument. @@ -1155,9 +1089,9 @@ class CXXConstructorDecl : public CXXMethodDecl { unsigned NumBaseOrMemberInitializers; CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, DeclaratorInfo *DInfo, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isExplicit, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXConstructor, RD, L, N, T, DInfo, false, isInline), + : CXXMethodDecl(CXXConstructor, RD, L, N, T, TInfo, false, isInline), Explicit(isExplicit), ImplicitlyDefined(false), BaseOrMemberInitializers(0), NumBaseOrMemberInitializers(0) { setImplicit(isImplicitlyDeclared); @@ -1167,7 +1101,7 @@ class CXXConstructorDecl : public CXXMethodDecl { public: static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, bool isExplicit, bool isInline, bool isImplicitlyDeclared); @@ -1294,7 +1228,7 @@ class CXXDestructorDecl : public CXXMethodDecl { CXXDestructorDecl(CXXRecordDecl *RD, SourceLocation L, DeclarationName N, QualType T, bool isInline, bool isImplicitlyDeclared) - : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*DInfo=*/0, false, isInline), + : CXXMethodDecl(CXXDestructor, RD, L, N, T, /*TInfo=*/0, false, isInline), ImplicitlyDefined(false), OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -1349,15 +1283,15 @@ class CXXConversionDecl : public CXXMethodDecl { bool Explicit : 1; CXXConversionDecl(CXXRecordDecl *RD, SourceLocation L, - DeclarationName N, QualType T, DeclaratorInfo *DInfo, + DeclarationName N, QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicit) - : CXXMethodDecl(CXXConversion, RD, L, N, T, DInfo, false, isInline), + : CXXMethodDecl(CXXConversion, RD, L, N, T, TInfo, false, isInline), Explicit(isExplicit) { } public: static CXXConversionDecl *Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation L, DeclarationName N, - QualType T, DeclaratorInfo *DInfo, + QualType T, TypeSourceInfo *TInfo, bool isInline, bool isExplicit); /// isExplicit - Whether this is an explicit conversion operator diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index c2b48cee36f4..32405ee81260 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -131,6 +131,25 @@ public: return DK == DK_DeclID || DK == DK_ID_Vector; } + void remove(NamedDecl *D) { + assert(!isNull() && "removing from empty list"); + if (NamedDecl *Singleton = getAsDecl()) { + assert(Singleton == D && "list is different singleton"); + (void)Singleton; + Data = 0; + return; + } + + VectorTy &Vec = *getAsVector(); + VectorTy::iterator I = std::find(Vec.begin(), Vec.end(), + reinterpret_cast<uintptr_t>(D)); + assert(I != Vec.end() && "list does not contain decl"); + Vec.erase(I); + + assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D)) + == Vec.end() && "list still contains decl"); + } + /// getLookupResult - Return an array of all the decls that this list /// represents. DeclContext::lookup_result getLookupResult(ASTContext &Context) { @@ -200,11 +219,37 @@ public: } VectorTy &Vec = *getAsVector(); - if (isa<UsingDirectiveDecl>(D) || - D->getIdentifierNamespace() == Decl::IDNS_Tag) + + // Using directives end up in a special entry which contains only + // other using directives, so all this logic is wasted for them. + // But avoiding the logic wastes time in the far-more-common case + // that we're *not* adding a new using directive. + + // Tag declarations always go at the end of the list so that an + // iterator which points at the first tag will start a span of + // decls that only contains tags. + if (D->getIdentifierNamespace() == Decl::IDNS_Tag) Vec.push_back(reinterpret_cast<uintptr_t>(D)); - else if (reinterpret_cast<NamedDecl *>(Vec.back()) - ->getIdentifierNamespace() == Decl::IDNS_Tag) { + + // Resolved using declarations go at the front of the list so that + // they won't show up in other lookup results. Unresolved using + // declarations (which are always in IDNS_Using | IDNS_Ordinary) + // follow that so that the using declarations will be contiguous. + else if (D->getIdentifierNamespace() & Decl::IDNS_Using) { + VectorTy::iterator I = Vec.begin(); + if (D->getIdentifierNamespace() != Decl::IDNS_Using) { + while (I != Vec.end() && + reinterpret_cast<NamedDecl *>(*I) + ->getIdentifierNamespace() == Decl::IDNS_Using) + ++I; + } + Vec.insert(I, reinterpret_cast<uintptr_t>(D)); + + // All other declarations go at the end of the list, but before any + // tag declarations. But we can be clever about tag declarations + // because there can only ever be one in a scope. + } else if (reinterpret_cast<NamedDecl *>(Vec.back()) + ->getIdentifierNamespace() == Decl::IDNS_Tag) { uintptr_t TagD = Vec.back(); Vec.back() = reinterpret_cast<uintptr_t>(D); Vec.push_back(TagD); diff --git a/include/clang/AST/DeclNodes.def b/include/clang/AST/DeclNodes.def index ec1b3b055cab..082299c41f50 100644 --- a/include/clang/AST/DeclNodes.def +++ b/include/clang/AST/DeclNodes.def @@ -75,7 +75,6 @@ DECL(TranslationUnit, Decl) ABSTRACT_DECL(Named, Decl) - DECL(OverloadedFunction, NamedDecl) DECL(Namespace, NamedDecl) DECL(UsingDirective, NamedDecl) DECL(NamespaceAlias, NamedDecl) @@ -143,7 +142,7 @@ DECL_CONTEXT_BASE(ObjCContainer) LAST_DECL_CONTEXT(Block) // Declaration ranges -DECL_RANGE(Named, OverloadedFunction, ObjCCompatibleAlias) +DECL_RANGE(Named, Namespace, ObjCCompatibleAlias) DECL_RANGE(ObjCContainer, ObjCContainer, ObjCImplementation) DECL_RANGE(Field, Field, ObjCAtDefsField) DECL_RANGE(Type, Typedef, TemplateTypeParm) diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 897776cdb9b8..fd8c3ef7fc55 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -578,14 +578,14 @@ public: private: ObjCIvarDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, DeclaratorInfo *DInfo, AccessControl ac, Expr *BW) - : FieldDecl(ObjCIvar, DC, L, Id, T, DInfo, BW, /*Mutable=*/false), + QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW) + : FieldDecl(ObjCIvar, DC, L, Id, T, TInfo, BW, /*Mutable=*/false), DeclAccess(ac) {} public: static ObjCIvarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, - DeclaratorInfo *DInfo, + TypeSourceInfo *TInfo, AccessControl ac, Expr *BW = NULL); void setAccessControl(AccessControl ac) { DeclAccess = ac; } @@ -612,7 +612,7 @@ private: ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *BW) : FieldDecl(ObjCAtDefsField, DC, L, Id, T, - /*DInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? + /*TInfo=*/0, // FIXME: Do ObjCAtDefs have declarators ? BW, /*Mutable=*/false) {} public: diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 3ecc4bb52b4c..d8b004a049ce 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -573,7 +573,7 @@ class TemplateTypeParmDecl : public TypeDecl { bool ParameterPack : 1; /// \brief The default template argument, if any. - DeclaratorInfo *DefaultArgument; + TypeSourceInfo *DefaultArgument; TemplateTypeParmDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, bool Typename, QualType Type, bool ParameterPack) @@ -601,7 +601,7 @@ public: QualType getDefaultArgument() const { return DefaultArgument->getType(); } /// \brief Retrieves the default argument's source information, if any. - DeclaratorInfo *getDefaultArgumentInfo() const { return DefaultArgument; } + TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument; } /// \brief Retrieves the location of the default argument declaration. SourceLocation getDefaultArgumentLoc() const; @@ -613,7 +613,7 @@ public: /// \brief Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. - void setDefaultArgument(DeclaratorInfo *DefArg, bool Inherited) { + void setDefaultArgument(TypeSourceInfo *DefArg, bool Inherited) { DefaultArgument = DefArg; InheritedDefault = Inherited; } @@ -652,15 +652,15 @@ class NonTypeTemplateParmDecl NonTypeTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, - DeclaratorInfo *DInfo) - : VarDecl(NonTypeTemplateParm, DC, L, Id, T, DInfo, VarDecl::None), + TypeSourceInfo *TInfo) + : VarDecl(NonTypeTemplateParm, DC, L, Id, T, TInfo, VarDecl::None), TemplateParmPosition(D, P), DefaultArgument(0) { } public: static NonTypeTemplateParmDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D, - unsigned P, IdentifierInfo *Id, QualType T, DeclaratorInfo *DInfo); + unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo); using TemplateParmPosition::getDepth; using TemplateParmPosition::getPosition; diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 676bd2ca7336..fcb4ae52e7eb 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -387,10 +387,11 @@ struct DenseMapInfo<clang::DeclarationName> { isEqual(clang::DeclarationName LHS, clang::DeclarationName RHS) { return LHS == RHS; } - - static inline bool isPod() { return true; } }; +template <> +struct isPodLike<clang::DeclarationName> { static const bool value = true; }; + } // end namespace llvm #endif diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 7cf9aabc6d6f..469598ff3723 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -309,6 +309,15 @@ public: /// ParenExpr or CastExprs, returning their operand. Expr *IgnoreParenNoopCasts(ASTContext &Ctx); + /// \brief Determine whether this expression is a default function argument. + /// + /// Default arguments are implicitly generated in the abstract syntax tree + /// by semantic analysis for function calls, object constructions, etc. in + /// C++. Default arguments are represented by \c CXXDefaultArgExpr nodes; + /// this routine also looks through any implicit casts to determine whether + /// the expression is a default argument. + bool isDefaultArgument() const; + const Expr* IgnoreParens() const { return const_cast<Expr*>(this)->IgnoreParens(); } @@ -389,7 +398,7 @@ class DeclRefExpr : public Expr { // indicate whether (1) the declaration's name was explicitly qualified and // (2) the declaration's name was followed by an explicit template // argument list. - llvm::PointerIntPair<NamedDecl *, 2> DecoratedD; + llvm::PointerIntPair<ValueDecl *, 2> DecoratedD; // Loc - The location of the declaration name itself. SourceLocation Loc; @@ -427,7 +436,7 @@ class DeclRefExpr : public Expr { } DeclRefExpr(NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - NamedDecl *D, SourceLocation NameLoc, + ValueDecl *D, SourceLocation NameLoc, const TemplateArgumentListInfo *TemplateArgs, QualType T); @@ -436,13 +445,13 @@ protected: /// declaration reference expression. void computeDependence(); - DeclRefExpr(StmtClass SC, NamedDecl *d, QualType t, SourceLocation l) : + DeclRefExpr(StmtClass SC, ValueDecl *d, QualType t, SourceLocation l) : Expr(SC, t, false, false), DecoratedD(d, 0), Loc(l) { computeDependence(); } public: - DeclRefExpr(NamedDecl *d, QualType t, SourceLocation l) : + DeclRefExpr(ValueDecl *d, QualType t, SourceLocation l) : Expr(DeclRefExprClass, t, false, false), DecoratedD(d, 0), Loc(l) { computeDependence(); } @@ -454,14 +463,14 @@ public: static DeclRefExpr *Create(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, - NamedDecl *D, + ValueDecl *D, SourceLocation NameLoc, QualType T, const TemplateArgumentListInfo *TemplateArgs = 0); - NamedDecl *getDecl() { return DecoratedD.getPointer(); } - const NamedDecl *getDecl() const { return DecoratedD.getPointer(); } - void setDecl(NamedDecl *NewD) { DecoratedD.setPointer(NewD); } + ValueDecl *getDecl() { return DecoratedD.getPointer(); } + const ValueDecl *getDecl() const { return DecoratedD.getPointer(); } + void setDecl(ValueDecl *NewD) { DecoratedD.setPointer(NewD); } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } @@ -686,11 +695,6 @@ public: SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } - // FIXME: The logic for computing the value of a predefined expr should go - // into a method here that takes the inner-most code decl (a block, function - // or objc method) that the expr lives in. This would allow sema and codegen - // to be consistent for things like sizeof(__func__) etc. - virtual SourceRange getSourceRange() const { return SourceRange(Loc); } static bool classof(const Stmt *T) { @@ -975,7 +979,7 @@ class SizeOfAlignOfExpr : public Expr { bool isSizeof : 1; // true if sizeof, false if alignof. bool isType : 1; // true if operand is a type, false if an expression union { - DeclaratorInfo *Ty; + TypeSourceInfo *Ty; Stmt *Ex; } Argument; SourceLocation OpLoc, RParenLoc; @@ -984,15 +988,15 @@ protected: virtual void DoDestroy(ASTContext& C); public: - SizeOfAlignOfExpr(bool issizeof, DeclaratorInfo *DInfo, + SizeOfAlignOfExpr(bool issizeof, TypeSourceInfo *TInfo, QualType resultType, SourceLocation op, SourceLocation rp) : Expr(SizeOfAlignOfExprClass, resultType, false, // Never type-dependent (C++ [temp.dep.expr]p3). // Value-dependent if the argument is type-dependent. - DInfo->getType()->isDependentType()), + TInfo->getType()->isDependentType()), isSizeof(issizeof), isType(true), OpLoc(op), RParenLoc(rp) { - Argument.Ty = DInfo; + Argument.Ty = TInfo; } SizeOfAlignOfExpr(bool issizeof, Expr *E, @@ -1017,7 +1021,7 @@ public: QualType getArgumentType() const { return getArgumentTypeInfo()->getType(); } - DeclaratorInfo *getArgumentTypeInfo() const { + TypeSourceInfo *getArgumentTypeInfo() const { assert(isArgumentType() && "calling getArgumentType() when arg is expr"); return Argument.Ty; } @@ -1030,8 +1034,8 @@ public: } void setArgument(Expr *E) { Argument.Ex = E; isType = false; } - void setArgument(DeclaratorInfo *DInfo) { - Argument.Ty = DInfo; + void setArgument(TypeSourceInfo *TInfo) { + Argument.Ty = TInfo; isType = true; } @@ -1252,7 +1256,7 @@ class MemberExpr : public Expr { /// MemberDecl - This is the decl being referenced by the field/member name. /// In X.F, this is the decl referenced by F. - NamedDecl *MemberDecl; + ValueDecl *MemberDecl; /// MemberLoc - This is the location of the member name. SourceLocation MemberLoc; @@ -1305,12 +1309,12 @@ class MemberExpr : public Expr { } MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, - SourceRange qualrange, NamedDecl *memberdecl, SourceLocation l, + SourceRange qualrange, ValueDecl *memberdecl, SourceLocation l, const TemplateArgumentListInfo *targs, QualType ty); public: - MemberExpr(Expr *base, bool isarrow, NamedDecl *memberdecl, SourceLocation l, - QualType ty) + MemberExpr(Expr *base, bool isarrow, ValueDecl *memberdecl, + SourceLocation l, QualType ty) : Expr(MemberExprClass, ty, base->isTypeDependent(), base->isValueDependent()), Base(base), MemberDecl(memberdecl), MemberLoc(l), IsArrow(isarrow), @@ -1323,7 +1327,7 @@ public: static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifier *qual, SourceRange qualrange, - NamedDecl *memberdecl, + ValueDecl *memberdecl, SourceLocation l, const TemplateArgumentListInfo *targs, QualType ty); @@ -1335,8 +1339,8 @@ public: /// /// The returned declaration will either be a FieldDecl or (in C++) /// a CXXMethodDecl. - NamedDecl *getMemberDecl() const { return MemberDecl; } - void setMemberDecl(NamedDecl *D) { MemberDecl = D; } + ValueDecl *getMemberDecl() const { return MemberDecl; } + void setMemberDecl(ValueDecl *D) { MemberDecl = D; } /// \brief Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., @@ -1576,7 +1580,14 @@ public: CK_FloatingCast, /// CK_MemberPointerToBoolean - Member pointer to boolean - CK_MemberPointerToBoolean + CK_MemberPointerToBoolean, + + /// CK_AnyPointerToObjCPointerCast - Casting any pointer to objective-c + /// pointer + CK_AnyPointerToObjCPointerCast, + /// CK_AnyPointerToBlockPointerCast - Casting any pointer to block + /// pointer + CK_AnyPointerToBlockPointerCast }; @@ -1607,6 +1618,14 @@ public: const Expr *getSubExpr() const { return cast<Expr>(Op); } void setSubExpr(Expr *E) { Op = E; } + /// \brief Retrieve the cast subexpression as it was written in the source + /// code, looking through any implicit casts or other intermediate nodes + /// introduced by semantic analysis. + Expr *getSubExprAsWritten(); + const Expr *getSubExprAsWritten() const { + return const_cast<CastExpr *>(this)->getSubExprAsWritten(); + } + static bool classof(const Stmt *T) { StmtClass SC = T->getStmtClass(); if (SC >= CXXNamedCastExprClass && SC <= CXXFunctionalCastExprClass) diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 23844ce5d967..00ea202abde7 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -527,6 +527,7 @@ public: const_arg_iterator arg_begin() const { return Args; } const_arg_iterator arg_end() const { return Args + NumArgs; } + Expr **getArgs() const { return reinterpret_cast<Expr **>(Args); } unsigned getNumArgs() const { return NumArgs; } /// getArg - Return the specified argument. @@ -1410,18 +1411,26 @@ public: /// \brief Represents a C++ member access expression where the actual /// member referenced could not be resolved because the base /// expression or the member name was dependent. +/// +/// Like UnresolvedMemberExprs, these can be either implicit or +/// explicit accesses. It is only possible to get one of these with +/// an implicit access if a qualifier is provided. class CXXDependentScopeMemberExpr : public Expr { /// \brief The expression for the base pointer or class reference, - /// e.g., the \c x in x.f. + /// e.g., the \c x in x.f. Can be null in implicit accesses. Stmt *Base; + /// \brief The type of the base expression. Never null, even for + /// implicit accesses. + QualType BaseType; + /// \brief Whether this member expression used the '->' operator or /// the '.' operator. bool IsArrow : 1; /// \brief Whether this member expression has explicitly-specified template /// arguments. - bool HasExplicitTemplateArgumentList : 1; + bool HasExplicitTemplateArgs : 1; /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; @@ -1452,9 +1461,7 @@ class CXXDependentScopeMemberExpr : public Expr { /// \brief Retrieve the explicit template argument list that followed the /// member template name, if any. ExplicitTemplateArgumentList *getExplicitTemplateArgumentList() { - if (!HasExplicitTemplateArgumentList) - return 0; - + assert(HasExplicitTemplateArgs); return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1); } @@ -1466,7 +1473,7 @@ class CXXDependentScopeMemberExpr : public Expr { } CXXDependentScopeMemberExpr(ASTContext &C, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -1477,7 +1484,8 @@ class CXXDependentScopeMemberExpr : public Expr { public: CXXDependentScopeMemberExpr(ASTContext &C, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, + bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -1485,15 +1493,15 @@ public: DeclarationName Member, SourceLocation MemberLoc) : Expr(CXXDependentScopeMemberExprClass, C.DependentTy, true, true), - Base(Base), IsArrow(IsArrow), HasExplicitTemplateArgumentList(false), - OperatorLoc(OperatorLoc), + Base(Base), BaseType(BaseType), IsArrow(IsArrow), + HasExplicitTemplateArgs(false), OperatorLoc(OperatorLoc), Qualifier(Qualifier), QualifierRange(QualifierRange), FirstQualifierFoundInScope(FirstQualifierFoundInScope), Member(Member), MemberLoc(MemberLoc) { } static CXXDependentScopeMemberExpr * Create(ASTContext &C, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -1502,11 +1510,21 @@ public: SourceLocation MemberLoc, const TemplateArgumentListInfo *TemplateArgs); + /// \brief True if this is an implicit access, i.e. one in which the + /// member being accessed was not written in the source. The source + /// location of the operator is invalid in this case. + bool isImplicitAccess() const { return Base == 0; } + /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. - Expr *getBase() { return cast<Expr>(Base); } + Expr *getBase() const { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } void setBase(Expr *E) { Base = E; } + QualType getBaseType() const { return BaseType; } + /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } @@ -1551,60 +1569,59 @@ public: /// \brief Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. - bool hasExplicitTemplateArgumentList() const { - return HasExplicitTemplateArgumentList; + bool hasExplicitTemplateArgs() const { + return HasExplicitTemplateArgs; } /// \brief Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { - if (hasExplicitTemplateArgumentList()) - getExplicitTemplateArgumentList()->copyInto(List); + assert(HasExplicitTemplateArgs); + getExplicitTemplateArgumentList()->copyInto(List); } /// \brief Retrieve the location of the left angle bracket following the /// member name ('<'), if any. SourceLocation getLAngleLoc() const { - if (!HasExplicitTemplateArgumentList) - return SourceLocation(); - + assert(HasExplicitTemplateArgs); return getExplicitTemplateArgumentList()->LAngleLoc; } /// \brief Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { - if (!HasExplicitTemplateArgumentList) - return 0; - + assert(HasExplicitTemplateArgs); return getExplicitTemplateArgumentList()->getTemplateArgs(); } /// \brief Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { - if (!HasExplicitTemplateArgumentList) - return 0; - + assert(HasExplicitTemplateArgs); return getExplicitTemplateArgumentList()->NumTemplateArgs; } /// \brief Retrieve the location of the right angle bracket following the /// template arguments ('>'). SourceLocation getRAngleLoc() const { - if (!HasExplicitTemplateArgumentList) - return SourceLocation(); - + assert(HasExplicitTemplateArgs); return getExplicitTemplateArgumentList()->RAngleLoc; } virtual SourceRange getSourceRange() const { - if (HasExplicitTemplateArgumentList) - return SourceRange(Base->getSourceRange().getBegin(), - getRAngleLoc()); + SourceRange Range; + if (!isImplicitAccess()) + Range.setBegin(Base->getSourceRange().getBegin()); + else if (getQualifier()) + Range.setBegin(getQualifierRange().getBegin()); + else + Range.setBegin(MemberLoc); - return SourceRange(Base->getSourceRange().getBegin(), - MemberLoc); + if (hasExplicitTemplateArgs()) + Range.setEnd(getRAngleLoc()); + else + Range.setEnd(MemberLoc); + return Range; } static bool classof(const Stmt *T) { @@ -1618,17 +1635,31 @@ public: }; /// \brief Represents a C++ member access expression for which lookup -/// produced a set of overloaded functions. These are replaced with -/// MemberExprs in the final AST. +/// produced a set of overloaded functions. +/// +/// The member access may be explicit or implicit: +/// struct A { +/// int a, b; +/// int explicitAccess() { return this->a + this->A::b; } +/// int implicitAccess() { return a + A::b; } +/// }; +/// +/// In the final AST, an explicit access always becomes a MemberExpr. +/// An implicit access may become either a MemberExpr or a +/// DeclRefExpr, depending on whether the member is static. class UnresolvedMemberExpr : public Expr { /// The results. These are undesugared, which is to say, they may /// include UsingShadowDecls. UnresolvedSet Results; /// \brief The expression for the base pointer or class reference, - /// e.g., the \c x in x.f. + /// e.g., the \c x in x.f. This can be null if this is an 'unbased' + /// member expression Stmt *Base; + /// \brief The type of the base expression; never null. + QualType BaseType; + /// \brief Whether this member expression used the '->' operator or /// the '.' operator. bool IsArrow : 1; @@ -1672,7 +1703,7 @@ class UnresolvedMemberExpr : public Expr { UnresolvedMemberExpr(QualType T, bool Dependent, bool HasUnresolvedUsing, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -1683,7 +1714,7 @@ class UnresolvedMemberExpr : public Expr { public: static UnresolvedMemberExpr * Create(ASTContext &C, bool Dependent, bool HasUnresolvedUsing, - Expr *Base, bool IsArrow, + Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifier *Qualifier, SourceRange QualifierRange, @@ -1704,11 +1735,21 @@ public: unsigned getNumDecls() const { return Results.size(); } + /// \brief True if this is an implicit access, i.e. one in which the + /// member being accessed was not written in the source. The source + /// location of the operator is invalid in this case. + bool isImplicitAccess() const { return Base == 0; } + /// \brief Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. - Expr *getBase() { return cast<Expr>(Base); } + Expr *getBase() { + assert(!isImplicitAccess()); + return cast<Expr>(Base); + } void setBase(Expr *E) { Base = E; } + QualType getBaseType() const { return BaseType; } + /// \brief Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } @@ -1772,7 +1813,14 @@ public: } virtual SourceRange getSourceRange() const { - SourceRange Range = Base->getSourceRange(); + SourceRange Range; + if (!isImplicitAccess()) + Range.setBegin(Base->getSourceRange().getBegin()); + else if (getQualifier()) + Range.setBegin(getQualifierRange().getBegin()); + else + Range.setBegin(MemberLoc); + if (hasExplicitTemplateArgs()) Range.setEnd(getRAngleLoc()); else diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 5d2973ea9dab..a8334b694080 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -119,13 +119,6 @@ private: /// VBaseOffsets - Contains a map from vbase classes to their offset. /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) llvm::DenseMap<const CXXRecordDecl *, uint64_t> VBaseOffsets; - - /// KeyFunction - The key function, according to the Itanium C++ ABI, - /// section 5.2.3: - /// - /// ...the first non-pure virtual function that is not inline at the point - /// of class definition. - const CXXMethodDecl *KeyFunction; }; /// CXXInfo - If the record layout is for a C++ record, this will have @@ -154,8 +147,7 @@ private: const std::pair<const CXXRecordDecl *, uint64_t> *bases, unsigned numbases, const std::pair<const CXXRecordDecl *, uint64_t> *vbases, - unsigned numvbases, - const CXXMethodDecl *KeyFunction) + unsigned numvbases) : Size(size), DataSize(datasize), FieldOffsets(0), Alignment(alignment), FieldCount(fieldcount), CXXInfo(new CXXRecordLayoutInfo) { if (FieldCount > 0) { @@ -171,7 +163,6 @@ private: CXXInfo->BaseOffsets[bases[i].first] = bases[i].second; for (unsigned i = 0; i != numvbases; ++i) CXXInfo->VBaseOffsets[vbases[i].first] = vbases[i].second; - CXXInfo->KeyFunction = KeyFunction; } ~ASTRecordLayout() { @@ -254,13 +245,6 @@ public: return CXXInfo->VBaseOffsets[VBase]; } - /// getKeyFunction - Get the key function. - const CXXMethodDecl *getKeyFunction() const { - assert(CXXInfo && "Record layout does not have C++ specific info!"); - - return CXXInfo->KeyFunction; - } - primary_base_info_iterator primary_base_begin() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 64eea2429c5d..09ea4ca2101b 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -68,10 +68,11 @@ public: Stmt **handlers, unsigned numHandlers); virtual SourceRange getSourceRange() const { - return SourceRange(TryLoc, Stmts.back()->getLocEnd()); + return SourceRange(getTryLoc(), getEndLoc()); } SourceLocation getTryLoc() const { return TryLoc; } + SourceLocation getEndLoc() const { return Stmts.back()->getLocEnd(); } CompoundStmt *getTryBlock() { return llvm::cast<CompoundStmt>(Stmts[0]); } const CompoundStmt *getTryBlock() const { diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index b46b3dc5d2d2..fe037992ad2f 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -29,7 +29,7 @@ namespace clang { class Decl; class Expr; -class DeclaratorInfo; +class TypeSourceInfo; /// \brief Represents a template argument within a class template /// specialization. @@ -267,7 +267,7 @@ struct TemplateArgumentLocInfo { private: union { Expr *Expression; - DeclaratorInfo *Declarator; + TypeSourceInfo *Declarator; struct { unsigned QualifierRange[2]; unsigned TemplateNameLoc; @@ -277,7 +277,7 @@ private: #ifndef NDEBUG enum Kind { K_None, - K_DeclaratorInfo, + K_TypeSourceInfo, K_Expression, K_Template } Kind; @@ -291,10 +291,10 @@ public: #endif {} - TemplateArgumentLocInfo(DeclaratorInfo *DInfo) - : Declarator(DInfo) + TemplateArgumentLocInfo(TypeSourceInfo *TInfo) + : Declarator(TInfo) #ifndef NDEBUG - , Kind(K_DeclaratorInfo) + , Kind(K_TypeSourceInfo) #endif {} @@ -316,8 +316,8 @@ public: Template.TemplateNameLoc = TemplateNameLoc.getRawEncoding(); } - DeclaratorInfo *getAsDeclaratorInfo() const { - assert(Kind == K_DeclaratorInfo); + TypeSourceInfo *getAsTypeSourceInfo() const { + assert(Kind == K_TypeSourceInfo); return Declarator; } @@ -342,7 +342,7 @@ public: void validateForArgument(const TemplateArgument &Arg) { switch (Arg.getKind()) { case TemplateArgument::Type: - assert(Kind == K_DeclaratorInfo); + assert(Kind == K_TypeSourceInfo); break; case TemplateArgument::Expression: case TemplateArgument::Declaration: @@ -356,7 +356,7 @@ public: assert(Kind == K_None); break; case TemplateArgument::Null: - llvm::llvm_unreachable("source info for null template argument?"); + llvm_unreachable("source info for null template argument?"); } } #endif @@ -376,8 +376,8 @@ public: : Argument(Argument), LocInfo(Opaque) { } - TemplateArgumentLoc(const TemplateArgument &Argument, DeclaratorInfo *DInfo) - : Argument(Argument), LocInfo(DInfo) { + TemplateArgumentLoc(const TemplateArgument &Argument, TypeSourceInfo *TInfo) + : Argument(Argument), LocInfo(TInfo) { assert(Argument.getKind() == TemplateArgument::Type); } @@ -412,9 +412,9 @@ public: return LocInfo; } - DeclaratorInfo *getSourceDeclaratorInfo() const { + TypeSourceInfo *getTypeSourceInfo() const { assert(Argument.getKind() == TemplateArgument::Type); - return LocInfo.getAsDeclaratorInfo(); + return LocInfo.getAsTypeSourceInfo(); } Expr *getSourceExpression() const { diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 8ef8fb51416c..aafe96381192 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -31,7 +31,34 @@ struct PrintingPolicy; class QualifiedTemplateName; class NamedDecl; class TemplateDecl; -class OverloadedFunctionDecl; + +/// \brief A structure for storing the information associated with an +/// overloaded template name. +class OverloadedTemplateStorage { + union { + unsigned Size; + NamedDecl *Storage[1]; + }; + + friend class ASTContext; + + OverloadedTemplateStorage(unsigned Size) : Size(Size) {} + + NamedDecl **getStorage() { + return &Storage[1]; + } + NamedDecl * const *getStorage() const { + return &Storage[1]; + } + +public: + typedef NamedDecl *const *iterator; + + unsigned size() const { return Size; } + + iterator begin() const { return getStorage(); } + iterator end() const { return getStorage() + size(); } +}; /// \brief Represents a C++ template name within the type system. /// @@ -61,7 +88,8 @@ class OverloadedFunctionDecl; /// specifier in the typedef. "apply" is a nested template, and can /// only be understood in the context of class TemplateName { - typedef llvm::PointerUnion4<TemplateDecl *, OverloadedFunctionDecl *, + typedef llvm::PointerUnion4<TemplateDecl *, + OverloadedTemplateStorage *, QualifiedTemplateName *, DependentTemplateName *> StorageType; @@ -74,8 +102,8 @@ class TemplateName { public: TemplateName() : Storage() { } explicit TemplateName(TemplateDecl *Template) : Storage(Template) { } - explicit TemplateName(OverloadedFunctionDecl *FunctionTemplates) - : Storage(FunctionTemplates) { } + explicit TemplateName(OverloadedTemplateStorage *Storage) + : Storage(Storage) { } explicit TemplateName(QualifiedTemplateName *Qual) : Storage(Qual) { } explicit TemplateName(DependentTemplateName *Dep) : Storage(Dep) { } @@ -98,7 +126,9 @@ public: /// name refers to, if known. If the template name does not refer to a /// specific set of function templates because it is a dependent name or /// refers to a single template, returns NULL. - OverloadedFunctionDecl *getAsOverloadedFunctionDecl() const; + OverloadedTemplateStorage *getAsOverloadedTemplate() const { + return Storage.dyn_cast<OverloadedTemplateStorage *>(); + } /// \brief Retrieve the underlying qualified template name /// structure, if any. @@ -166,19 +196,14 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { /// \brief The template declaration or set of overloaded function templates /// that this qualified name refers to. - NamedDecl *Template; + TemplateDecl *Template; friend class ASTContext; QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, TemplateDecl *Template) : Qualifier(NNS, TemplateKeyword? 1 : 0), - Template(reinterpret_cast<NamedDecl *>(Template)) { } - - QualifiedTemplateName(NestedNameSpecifier *NNS, bool TemplateKeyword, - OverloadedFunctionDecl *Template) - : Qualifier(NNS, TemplateKeyword? 1 : 0), - Template(reinterpret_cast<NamedDecl *>(Template)) { } + Template(Template) { } public: /// \brief Return the nested name specifier that qualifies this name. @@ -188,26 +213,20 @@ public: /// keyword. bool hasTemplateKeyword() const { return Qualifier.getInt(); } - /// \brief The template declaration or set of overloaded functions that - /// that qualified name refers to. - NamedDecl *getDecl() const { return Template; } + /// \brief The template declaration that this qualified name refers + /// to. + TemplateDecl *getDecl() const { return Template; } /// \brief The template declaration to which this qualified name - /// refers, or NULL if this qualified name refers to a set of overloaded - /// function templates. - TemplateDecl *getTemplateDecl() const; - - /// \brief The set of overloaded function tempaltes to which this qualified - /// name refers, or NULL if this qualified name refers to a single - /// template declaration. - OverloadedFunctionDecl *getOverloadedFunctionDecl() const; + /// refers. + TemplateDecl *getTemplateDecl() const { return Template; } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getQualifier(), hasTemplateKeyword(), getDecl()); + Profile(ID, getQualifier(), hasTemplateKeyword(), getTemplateDecl()); } static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, - bool TemplateKeyword, NamedDecl *Template) { + bool TemplateKeyword, TemplateDecl *Template) { ID.AddPointer(NNS); ID.AddBoolean(TemplateKeyword); ID.AddPointer(Template); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 349487f8794b..d22a646ece5b 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -35,7 +35,9 @@ namespace clang { TypeAlignmentInBits = 3, TypeAlignment = 1 << TypeAlignmentInBits }; - class Type; class ExtQuals; + class Type; + class ExtQuals; + class QualType; } namespace llvm { @@ -59,6 +61,9 @@ namespace llvm { } enum { NumLowBitsAvailable = clang::TypeAlignmentInBits }; }; + + template <> + struct isPodLike<clang::QualType> { static const bool value = true; }; } namespace clang { @@ -76,6 +81,7 @@ namespace clang { class ObjCInterfaceDecl; class ObjCProtocolDecl; class ObjCMethodDecl; + class UnresolvedUsingTypenameDecl; class Expr; class Stmt; class SourceLocation; @@ -791,6 +797,10 @@ public: /// isPODType - Return true if this is a plain-old-data type (C++ 3.9p10). bool isPODType() const; + /// isLiteralType - Return true if this is a literal type + /// (C++0x [basic.types]p10) + bool isLiteralType() const; + /// isVariablyModifiedType (C99 6.7.5.2p2) - Return true for variable array /// types that have a non-constant expression. This does not include "[]". bool isVariablyModifiedType() const; @@ -808,8 +818,9 @@ public: bool isBooleanType() const; bool isCharType() const; bool isWideCharType() const; + bool isAnyCharacterType() const; bool isIntegralType() const; - + /// Floating point categories. bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double) /// isComplexType() does *not* include complex integers (a GCC extension). @@ -1859,6 +1870,38 @@ public: }; +/// \brief Represents the dependent type named by a dependently-scoped +/// typename using declaration, e.g. +/// using typename Base<T>::foo; +/// Template instantiation turns these into the underlying type. +class UnresolvedUsingType : public Type { + UnresolvedUsingTypenameDecl *Decl; + + UnresolvedUsingType(UnresolvedUsingTypenameDecl *D) + : Type(UnresolvedUsing, QualType(), true), Decl(D) {} + friend class ASTContext; // ASTContext creates these. +public: + + UnresolvedUsingTypenameDecl *getDecl() const { return Decl; } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == UnresolvedUsing; + } + static bool classof(const UnresolvedUsingType *) { return true; } + + void Profile(llvm::FoldingSetNodeID &ID) { + return Profile(ID, Decl); + } + static void Profile(llvm::FoldingSetNodeID &ID, + UnresolvedUsingTypenameDecl *D) { + ID.AddPointer(D); + } +}; + + class TypedefType : public Type { TypedefDecl *Decl; protected: diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index f08ca6bf469b..a9b7f7e94337 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -19,7 +19,7 @@ namespace clang { class ParmVarDecl; - class DeclaratorInfo; + class TypeSourceInfo; class UnqualTypeLoc; // Predeclare all the type nodes. @@ -340,16 +340,20 @@ public: } }; + struct TypeSpecLocInfo { SourceLocation NameLoc; }; /// \brief A reasonable base class for TypeLocs that correspond to /// types that are written as a type-specifier. -template <class Derived, class TypeClass, class LocalData = TypeSpecLocInfo> -class TypeSpecTypeLoc - : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> { +class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, + TypeSpecTypeLoc, + Type, + TypeSpecLocInfo> { public: + enum { LocalDataSize = sizeof(TypeSpecLocInfo) }; + SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; } @@ -362,31 +366,79 @@ public: void initializeLocal(SourceLocation Loc) { setNameLoc(Loc); } + + static bool classof(const TypeLoc *TL); + static bool classof(const TypeSpecTypeLoc *TL) { return true; } }; + /// \brief Wrapper for source info for typedefs. -class TypedefTypeLoc : public TypeSpecTypeLoc<TypedefTypeLoc,TypedefType> { +class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypedefTypeLoc, + TypedefType> { public: TypedefDecl *getTypedefDecl() const { return getTypePtr()->getDecl(); } }; +/// \brief Wrapper for source info for unresolved typename using decls. +class UnresolvedUsingTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + UnresolvedUsingTypeLoc, + UnresolvedUsingType> { +public: + UnresolvedUsingTypenameDecl *getDecl() const { + return getTypePtr()->getDecl(); + } +}; + +/// \brief Wrapper for source info for tag types. Note that this only +/// records source info for the name itself; a type written 'struct foo' +/// should be represented as an ElaboratedTypeLoc. We currently +/// only do that when C++ is enabled because of the expense of +/// creating an ElaboratedType node for so many type references in C. +class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TagTypeLoc, + TagType> { +public: + TagDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + +/// \brief Wrapper for source info for record types. +class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, + RecordTypeLoc, + RecordType> { +public: + RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; + +/// \brief Wrapper for source info for enum types. +class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, + EnumTypeLoc, + EnumType> { +public: + EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } +}; /// \brief Wrapper for source info for builtin types. -class BuiltinTypeLoc : public TypeSpecTypeLoc<BuiltinTypeLoc, - BuiltinType> { +class BuiltinTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + BuiltinTypeLoc, + BuiltinType> { }; /// \brief Wrapper for template type parameters. -class TemplateTypeParmTypeLoc : public TypeSpecTypeLoc<TemplateTypeParmTypeLoc, - TemplateTypeParmType> { +class TemplateTypeParmTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TemplateTypeParmTypeLoc, + TemplateTypeParmType> { }; /// \brief Wrapper for substituted template type parameters. class SubstTemplateTypeParmTypeLoc : - public TypeSpecTypeLoc<SubstTemplateTypeParmTypeLoc, - SubstTemplateTypeParmType> { + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + SubstTemplateTypeParmTypeLoc, + SubstTemplateTypeParmType> { }; @@ -889,7 +941,7 @@ public: assert(size == Loc.getFullDataSize()); // We're potentially copying Expr references here. We don't - // bother retaining them because DeclaratorInfos live forever, so + // bother retaining them because TypeSourceInfos live forever, so // as long as the Expr was retained when originally written into // the TypeLoc, we're okay. memcpy(Data, Loc.Data, size); @@ -916,7 +968,7 @@ public: break; case TemplateArgument::Type: - Info = TemplateArgumentLocInfo((DeclaratorInfo*) 0); + Info = TemplateArgumentLocInfo((TypeSourceInfo*) 0); break; case TemplateArgument::Template: @@ -944,63 +996,84 @@ private: } }; -// None of these types have proper implementations yet. +//===----------------------------------------------------------------------===// +// +// All of these need proper implementations. +// +//===----------------------------------------------------------------------===// -class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> { +// FIXME: size expression and attribute locations (or keyword if we +// ever fully support altivec syntax). +class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + VectorTypeLoc, + VectorType> { }; +// FIXME: size expression and attribute locations. class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc, ExtVectorTypeLoc, ExtVectorType> { }; +// FIXME: attribute locations. // For some reason, this isn't a subtype of VectorType. class DependentSizedExtVectorTypeLoc : - public TypeSpecTypeLoc<DependentSizedExtVectorTypeLoc, - DependentSizedExtVectorType> { + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + DependentSizedExtVectorTypeLoc, + DependentSizedExtVectorType> { }; -class FixedWidthIntTypeLoc : public TypeSpecTypeLoc<FixedWidthIntTypeLoc, - FixedWidthIntType> { +// FIXME: I'm not sure how you actually specify these; with attributes? +class FixedWidthIntTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + FixedWidthIntTypeLoc, + FixedWidthIntType> { }; -class ComplexTypeLoc : public TypeSpecTypeLoc<ComplexTypeLoc, - ComplexType> { +// FIXME: location of the '_Complex' keyword. +class ComplexTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + ComplexTypeLoc, + ComplexType> { }; -class TypeOfExprTypeLoc : public TypeSpecTypeLoc<TypeOfExprTypeLoc, - TypeOfExprType> { +// FIXME: location of the 'typeof' and parens (the expression is +// carried by the type). +class TypeOfExprTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypeOfExprTypeLoc, + TypeOfExprType> { }; -class TypeOfTypeLoc : public TypeSpecTypeLoc<TypeOfTypeLoc, TypeOfType> { +// FIXME: location of the 'typeof' and parens; also the TypeSourceInfo +// for the inner type, or (maybe) just express that inline to the TypeLoc. +class TypeOfTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypeOfTypeLoc, + TypeOfType> { }; -class DecltypeTypeLoc : public TypeSpecTypeLoc<DecltypeTypeLoc, DecltypeType> { -}; - -class TagTypeLoc : public TypeSpecTypeLoc<TagTypeLoc, TagType> { -}; - -class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, - RecordTypeLoc, - RecordType> { -}; - -class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, - EnumTypeLoc, - EnumType> { +// FIXME: location of the 'decltype' and parens. +class DecltypeTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + DecltypeTypeLoc, + DecltypeType> { }; -class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc, - ElaboratedType> { +// FIXME: location of the tag keyword. +class ElaboratedTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + ElaboratedTypeLoc, + ElaboratedType> { }; -class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc, - QualifiedNameType> { +// FIXME: locations for the nested name specifier; at the very least, +// a SourceRange. +class QualifiedNameTypeLoc : + public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + QualifiedNameTypeLoc, + QualifiedNameType> { }; -class TypenameTypeLoc : public TypeSpecTypeLoc<TypenameTypeLoc, - TypenameType> { +// FIXME: locations for the typename keyword and nested name specifier. +class TypenameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + TypenameTypeLoc, + TypenameType> { }; } diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h index 00e2b7f83219..c3b1c68b1fb6 100644 --- a/include/clang/AST/TypeLocBuilder.h +++ b/include/clang/AST/TypeLocBuilder.h @@ -59,9 +59,35 @@ class TypeLocBuilder { grow(Requested); } - /// Pushes space for a new TypeLoc onto the given type. Invalidates + /// Pushes space for a typespec TypeLoc. Invalidates any TypeLocs + /// previously retrieved from this builder. + TypeSpecTypeLoc pushTypeSpec(QualType T) { + size_t LocalSize = TypeSpecTypeLoc::LocalDataSize; + return cast<TypeSpecTypeLoc>(pushImpl(T, LocalSize)); + } + + + /// Pushes space for a new TypeLoc of the given type. Invalidates /// any TypeLocs previously retrieved from this builder. template <class TyLocType> TyLocType push(QualType T) { + size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); + return cast<TyLocType>(pushImpl(T, LocalSize)); + } + + /// Creates a TypeSourceInfo for the given type. + TypeSourceInfo *getTypeSourceInfo(ASTContext& Context, QualType T) { +#ifndef NDEBUG + assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + + size_t FullDataSize = Capacity - Index; + TypeSourceInfo *DI = Context.CreateTypeSourceInfo(T, FullDataSize); + memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); + return DI; + } + +private: + TypeLoc pushImpl(QualType T, size_t LocalSize) { #ifndef NDEBUG QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); assert(TLast == LastTy && @@ -69,8 +95,6 @@ class TypeLocBuilder { LastTy = T; #endif - size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); - // If we need to grow, grow by a factor of 2. if (LocalSize > Index) { size_t RequiredCapacity = Capacity + (LocalSize - Index); @@ -82,22 +106,9 @@ class TypeLocBuilder { Index -= LocalSize; - return cast<TyLocType>(TypeLoc(T, &Buffer[Index])); - } - - /// Creates a DeclaratorInfo for the given type. - DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) { -#ifndef NDEBUG - assert(T == LastTy && "type doesn't match last type pushed!"); -#endif - - size_t FullDataSize = Capacity - Index; - DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize); - memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); - return DI; + return TypeLoc(T, &Buffer[Index]); } - private: /// Grow to the given capacity. void grow(size_t NewCapacity) { assert(NewCapacity > Capacity); diff --git a/include/clang/AST/TypeLocVisitor.h b/include/clang/AST/TypeLocVisitor.h index a62bb3f853bc..95ec175a53a4 100644 --- a/include/clang/AST/TypeLocVisitor.h +++ b/include/clang/AST/TypeLocVisitor.h @@ -33,7 +33,7 @@ public: case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); #include "clang/AST/TypeLocNodes.def" } - llvm::llvm_unreachable("unexpected type loc class!"); + llvm_unreachable("unexpected type loc class!"); } RetTy Visit(UnqualTypeLoc TyLoc) { diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index c2721236af02..b9d37992a670 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -71,6 +71,7 @@ TYPE(ExtVector, VectorType) ABSTRACT_TYPE(Function, Type) TYPE(FunctionProto, FunctionType) TYPE(FunctionNoProto, FunctionType) +DEPENDENT_TYPE(UnresolvedUsing, Type) NON_CANONICAL_TYPE(Typedef, Type) NON_CANONICAL_TYPE(TypeOfExpr, Type) NON_CANONICAL_TYPE(TypeOf, Type) diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 652f4f70bd16..1a050d29c860 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -50,13 +50,6 @@ namespace llvm { static bool isEqual(clang::QualType LHS, clang::QualType RHS) { return LHS == RHS; } - - static bool isPod() { - // QualType isn't *technically* a POD type. However, we can get - // away with calling it a POD type since its copy constructor, - // copy assignment operator, and destructor are all trivial. - return true; - } }; } diff --git a/include/clang/Analysis/PathDiagnostic.h b/include/clang/Analysis/PathDiagnostic.h index cad702cbdb2e..970b523e1b43 100644 --- a/include/clang/Analysis/PathDiagnostic.h +++ b/include/clang/Analysis/PathDiagnostic.h @@ -179,9 +179,7 @@ private: PathDiagnosticPiece& operator=(const PathDiagnosticPiece &P); protected: - PathDiagnosticPiece(const std::string& s, Kind k, DisplayHint hint = Below); - - PathDiagnosticPiece(const char* s, Kind k, DisplayHint hint = Below); + PathDiagnosticPiece(llvm::StringRef s, Kind k, DisplayHint hint = Below); PathDiagnosticPiece(Kind k, DisplayHint hint = Below); @@ -242,7 +240,7 @@ private: PathDiagnosticLocation Pos; public: PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, - const std::string& s, + llvm::StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange = true) : PathDiagnosticPiece(s, k), Pos(pos) { @@ -261,11 +259,7 @@ class PathDiagnosticEventPiece : public PathDiagnosticSpotPiece { public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, - const std::string& s, bool addPosRange = true) - : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {} - - PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, const char* s, - bool addPosRange = true) + llvm::StringRef s, bool addPosRange = true) : PathDiagnosticSpotPiece(pos, s, Event, addPosRange) {} ~PathDiagnosticEventPiece(); @@ -280,14 +274,7 @@ class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece { public: PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, - const std::string& s) - : PathDiagnosticPiece(s, ControlFlow) { - LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); - } - - PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, - const PathDiagnosticLocation &endPos, - const char* s) + llvm::StringRef s) : PathDiagnosticPiece(s, ControlFlow) { LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); } @@ -384,22 +371,19 @@ class PathDiagnostic : public llvm::FoldingSetNode { public: PathDiagnostic(); - PathDiagnostic(const char* bugtype, const char* desc, const char* category); - - PathDiagnostic(const std::string& bugtype, const std::string& desc, - const std::string& category); + PathDiagnostic(llvm::StringRef bugtype, llvm::StringRef desc, + llvm::StringRef category); ~PathDiagnostic(); - const std::string& getDescription() const { return Desc; } - const std::string& getBugType() const { return BugType; } - const std::string& getCategory() const { return Category; } + llvm::StringRef getDescription() const { return Desc; } + llvm::StringRef getBugType() const { return BugType; } + llvm::StringRef getCategory() const { return Category; } typedef std::deque<std::string>::const_iterator meta_iterator; meta_iterator meta_begin() const { return OtherDesc.begin(); } meta_iterator meta_end() const { return OtherDesc.end(); } - void addMeta(const std::string& s) { OtherDesc.push_back(s); } - void addMeta(const char* s) { OtherDesc.push_back(s); } + void addMeta(llvm::StringRef s) { OtherDesc.push_back(s); } PathDiagnosticLocation getLocation() const { assert(Size > 0 && "getLocation() requires a non-empty PathDiagnostic."); diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index 8b1a329c0335..abc33b778482 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -15,9 +15,10 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H #define LLVM_CLANG_ANALYSIS_ANALYSISCONTEXT_H -#include "clang/AST/Stmt.h" +#include "clang/AST/Decl.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Allocator.h" @@ -29,7 +30,10 @@ class CFG; class LiveVariables; class ParentMap; class ImplicitParamDecl; - +class LocationContextManager; +class BlockDataRegion; +class StackFrameContext; + /// AnalysisContext contains the context data for the function or method under /// analysis. class AnalysisContext { @@ -78,7 +82,7 @@ public: class LocationContext : public llvm::FoldingSetNode { public: - enum ContextKind { StackFrame, Scope }; + enum ContextKind { StackFrame, Scope, Block }; private: ContextKind Kind; @@ -91,7 +95,7 @@ protected: : Kind(k), Ctx(ctx), Parent(parent) {} public: - virtual ~LocationContext() {} + virtual ~LocationContext(); ContextKind getKind() const { return Kind; } @@ -114,36 +118,42 @@ public: const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); } + + const StackFrameContext *getCurrentStackFrame() const; + const StackFrameContext * + getStackFrameForDeclContext(const DeclContext *DC) const; - virtual void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, Kind, Ctx, Parent); - } - - static void Profile(llvm::FoldingSetNodeID &ID, ContextKind k, - AnalysisContext *ctx, const LocationContext *parent); + virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; static bool classof(const LocationContext*) { return true; } + +public: + static void ProfileCommon(llvm::FoldingSetNodeID &ID, + ContextKind ck, + AnalysisContext *ctx, + const LocationContext *parent, + const void* data); }; class StackFrameContext : public LocationContext { const Stmt *CallSite; -public: + friend class LocationContextManager; StackFrameContext(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s) : LocationContext(StackFrame, ctx, parent), CallSite(s) {} - - virtual ~StackFrameContext() {} +public: + ~StackFrameContext() {} - Stmt const *getCallSite() const { return CallSite; } - - virtual void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getAnalysisContext(), getParent(), CallSite); - } + const Stmt *getCallSite() const { return CallSite; } + void Profile(llvm::FoldingSetNodeID &ID); + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, - const LocationContext *parent, const Stmt *s); + const LocationContext *parent, const Stmt *s) { + ProfileCommon(ID, StackFrame, ctx, parent, s); + } static bool classof(const LocationContext* Ctx) { return Ctx->getKind() == StackFrame; @@ -152,41 +162,91 @@ public: class ScopeContext : public LocationContext { const Stmt *Enter; - -public: + + friend class LocationContextManager; ScopeContext(AnalysisContext *ctx, const LocationContext *parent, const Stmt *s) : LocationContext(Scope, ctx, parent), Enter(s) {} - - virtual ~ScopeContext() {} - virtual void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getAnalysisContext(), getParent(), Enter); - } +public: + ~ScopeContext() {} + + void Profile(llvm::FoldingSetNodeID &ID); static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, - const LocationContext *parent, const Stmt *s); + const LocationContext *parent, const Stmt *s) { + ProfileCommon(ID, Scope, ctx, parent, s); + } static bool classof(const LocationContext* Ctx) { return Ctx->getKind() == Scope; } }; +class BlockInvocationContext : public LocationContext { + llvm::PointerUnion<const BlockDataRegion *, const BlockDecl *> Data; + + friend class LocationContextManager; + + BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, + const BlockDataRegion *br) + : LocationContext(Block, ctx, parent), Data(br) {} + + BlockInvocationContext(AnalysisContext *ctx, const LocationContext *parent, + const BlockDecl *bd) + : LocationContext(Block, ctx, parent), Data(bd) {} + +public: + ~BlockInvocationContext() {} + + const BlockDataRegion *getBlockRegion() const { + return Data.is<const BlockDataRegion*>() ? + Data.get<const BlockDataRegion*>() : 0; + } + + const BlockDecl *getBlockDecl() const; + + void Profile(llvm::FoldingSetNodeID &ID); + + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + const LocationContext *parent, const BlockDataRegion *br){ + ProfileCommon(ID, Block, ctx, parent, br); + } + + static void Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx, + const LocationContext *parent, const BlockDecl *bd) { + ProfileCommon(ID, Block, ctx, parent, bd); + } + + static bool classof(const LocationContext* Ctx) { + return Ctx->getKind() == Block; + } +}; + class LocationContextManager { llvm::FoldingSet<LocationContext> Contexts; - public: ~LocationContextManager(); - StackFrameContext *getStackFrame(AnalysisContext *ctx, - const LocationContext *parent, - const Stmt *s); + const StackFrameContext *getStackFrame(AnalysisContext *ctx, + const LocationContext *parent, + const Stmt *s); - ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent, - const Stmt *s); + const ScopeContext *getScope(AnalysisContext *ctx, + const LocationContext *parent, + const Stmt *s); + + const BlockInvocationContext * + getBlockInvocation(AnalysisContext *ctx, const LocationContext *parent, + const BlockDataRegion *BR); /// Discard all previously created LocationContext objects. void clear(); +private: + template <typename LOC, typename DATA> + const LOC *getLocationContext(AnalysisContext *ctx, + const LocationContext *parent, + const DATA *d); }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index 18eae9ac9f14..9ef5cce1002b 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -56,8 +56,7 @@ public: const LangOptions &lang, PathDiagnosticClient *pd, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, - bool displayProgress, bool vizdot, bool vizubi, - bool purge, bool eager, bool trim) + bool vizdot, bool vizubi, bool purge, bool eager, bool trim) : Ctx(ctx), Diags(diags), LangInfo(lang), PD(pd), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), @@ -132,7 +131,7 @@ public: } // Get the top level stack frame. - StackFrameContext *getStackFrame(Decl const *D) { + const StackFrameContext *getStackFrame(Decl const *D) { return LocCtxMgr.getStackFrame(AnaCtxMgr.getContext(D), 0, 0); } diff --git a/include/clang/Analysis/PathSensitive/BugType.h b/include/clang/Analysis/PathSensitive/BugType.h index 4f1523a5440d..b75a8189e54c 100644 --- a/include/clang/Analysis/PathSensitive/BugType.h +++ b/include/clang/Analysis/PathSensitive/BugType.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE #define LLVM_CLANG_ANALYSIS_BUGTYPE +#include "clang/Analysis/PathSensitive/BugReporter.h" #include <llvm/ADT/FoldingSet.h> #include <string> diff --git a/include/clang/Analysis/PathSensitive/Checker.h b/include/clang/Analysis/PathSensitive/Checker.h index 91a4b6d1b1eb..a625a7a25690 100644 --- a/include/clang/Analysis/PathSensitive/Checker.h +++ b/include/clang/Analysis/PathSensitive/Checker.h @@ -39,7 +39,7 @@ class CheckerContext { SaveAndRestore<const void*> OldTag; SaveAndRestore<ProgramPoint::Kind> OldPointKind; SaveOr OldHasGen; - const GRState *state; + const GRState *ST; const Stmt *statement; const unsigned size; bool DoneEvaluating; // FIXME: This is not a permanent API change. @@ -53,22 +53,14 @@ public: OldTag(B.Tag, tag), OldPointKind(B.PointKind, K), OldHasGen(B.HasGeneratedNode), - state(st), statement(stmt), size(Dst.size()), - DoneEvaluating(false) {} + ST(st), statement(stmt), size(Dst.size()) {} ~CheckerContext(); - - // FIXME: This were added to support CallAndMessageChecker to indicating - // to GRExprEngine to "stop evaluating" a message expression under certain - // cases. This is *not* meant to be a permanent API change, and was added - // to aid in the transition of removing logic for checks from GRExprEngine. - void setDoneEvaluating() { - DoneEvaluating = true; - } - bool isDoneEvaluating() const { - return DoneEvaluating; + + GRExprEngine &getEngine() { + return Eng; } - + ConstraintManager &getConstraintManager() { return Eng.getConstraintManager(); } @@ -80,7 +72,7 @@ public: ExplodedNodeSet &getNodeSet() { return Dst; } GRStmtNodeBuilder &getNodeBuilder() { return B; } ExplodedNode *&getPredecessor() { return Pred; } - const GRState *getState() { return state ? state : B.GetState(Pred); } + const GRState *getState() { return ST ? ST : B.GetState(Pred); } ASTContext &getASTContext() { return Eng.getContext(); @@ -98,6 +90,10 @@ public: return Eng.getValueManager(); } + SValuator &getSValuator() { + return Eng.getSValuator(); + } + ExplodedNode *GenerateNode(bool autoTransition = true) { assert(statement && "Only transitions with statements currently supported"); ExplodedNode *N = GenerateNodeImpl(statement, getState(), false); @@ -115,6 +111,15 @@ public: return N; } + ExplodedNode *GenerateNode(const GRState *state, ExplodedNode *pred, + bool autoTransition = true) { + assert(statement && "Only transitions with statements currently supported"); + ExplodedNode *N = GenerateNodeImpl(statement, state, pred, false); + if (N && autoTransition) + addTransition(N); + return N; + } + ExplodedNode *GenerateNode(const GRState *state, bool autoTransition = true) { assert(statement && "Only transitions with statements currently supported"); ExplodedNode *N = GenerateNodeImpl(statement, state, false); @@ -138,8 +143,7 @@ public: void addTransition(const GRState *state) { assert(state); - if (state != getState() || - (state && state != B.GetState(Pred))) + if (state != getState() || (ST && ST != B.GetState(Pred))) GenerateNode(state, true); else Dst.Add(Pred); @@ -157,7 +161,14 @@ private: node->markAsSink(); return node; } - + + ExplodedNode *GenerateNodeImpl(const Stmt* stmt, const GRState *state, + ExplodedNode *pred, bool markAsSink) { + ExplodedNode *node = B.generateNode(stmt, state, pred); + if (markAsSink && node) + node->markAsSink(); + return node; + } }; class Checker { @@ -165,7 +176,7 @@ private: friend class GRExprEngine; // FIXME: Remove the 'tag' option. - bool GR_Visit(ExplodedNodeSet &Dst, + void GR_Visit(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, GRExprEngine &Eng, const Stmt *S, @@ -177,7 +188,22 @@ private: _PreVisit(C, S); else _PostVisit(C, S); - return C.isDoneEvaluating(); + } + + bool GR_EvalNilReceiver(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const ObjCMessageExpr *ME, + ExplodedNode *Pred, const GRState *state, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, + ME, state); + return EvalNilReceiver(C, ME); + } + + bool GR_EvalCallExpr(ExplodedNodeSet &Dst, GRStmtNodeBuilder &Builder, + GRExprEngine &Eng, const CallExpr *CE, + ExplodedNode *Pred, void *tag) { + CheckerContext C(Dst, Builder, Eng, Pred, tag, ProgramPoint::PostStmtKind, + CE); + return EvalCallExpr(C, CE); } // FIXME: Remove the 'tag' option. @@ -231,6 +257,14 @@ public: virtual void VisitBranchCondition(GRBranchNodeBuilder &Builder, GRExprEngine &Eng, Stmt *Condition, void *tag) {} + + virtual bool EvalNilReceiver(CheckerContext &C, const ObjCMessageExpr *ME) { + return false; + } + + virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE) { + return false; + } }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index a7302c0602ec..8b20a823c6a1 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -209,8 +209,17 @@ public: protected: /// CheckerVisit - Dispatcher for performing checker-specific logic /// at specific statements. - bool CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, + void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, bool isPrevisit); + + bool CheckerEvalCall(const CallExpr *CE, + ExplodedNodeSet &Dst, + ExplodedNode *Pred); + + void CheckerEvalNilReceiver(const ObjCMessageExpr *ME, + ExplodedNodeSet &Dst, + const GRState *state, + ExplodedNode *Pred); void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE, ExplodedNodeSet &Dst, ExplodedNodeSet &Src, @@ -272,6 +281,13 @@ protected: void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); + /// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs. + void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + /// VisitDeclStmt - Transfer function logic for DeclStmts. void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst); @@ -358,9 +374,10 @@ public: } protected: - void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) { + void EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, + ExplodedNode* Pred, const GRState *state) { assert (Builder && "GRStmtNodeBuilder must be defined."); - getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred); + getTF().EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred, state); } const GRState* MarkBranch(const GRState* St, Stmt* Terminator, diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index d8bc2411750f..421ebbf9bd5e 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -217,6 +217,7 @@ public: /// for the compound literal and 'BegInit' and 'EndInit' represent an /// array of initializer values. const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC, SVal V) const; const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const; @@ -237,7 +238,8 @@ public: /// Get the lvalue for a StringLiteral. SVal getLValue(const StringLiteral *literal) const; - SVal getLValue(const CompoundLiteralExpr *literal) const; + SVal getLValue(const CompoundLiteralExpr *literal, + const LocationContext *LC) const; /// Get the lvalue for an ivar reference. SVal getLValue(const ObjCIvarDecl *decl, SVal base) const; @@ -609,9 +611,10 @@ inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx, cast<DefinedSVal>(UpperBound), Assumption); } -inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL, - SVal V) const { - return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V); +inline const GRState * +GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC, SVal V) const { + return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, LC, V); } inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const { @@ -639,8 +642,9 @@ inline SVal GRState::getLValue(const StringLiteral *literal) const { return getStateManager().StoreMgr->getLValueString(literal); } -inline SVal GRState::getLValue(const CompoundLiteralExpr *literal) const { - return getStateManager().StoreMgr->getLValueCompoundLiteral(literal); +inline SVal GRState::getLValue(const CompoundLiteralExpr *literal, + const LocationContext *LC) const { + return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC); } inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const { diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 40c1ed3224f4..2594618c16db 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -47,7 +47,8 @@ public: GRExprEngine& Engine, GRStmtNodeBuilder& Builder, ObjCMessageExpr* ME, - ExplodedNode* Pred) {} + ExplodedNode* Pred, + const GRState *state) {} // Stores. diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index ed964978a44a..2fe5ea0cf3ab 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -35,6 +35,7 @@ namespace clang { class MemRegionManager; class MemSpaceRegion; class LocationContext; +class StackFrameContext; class VarRegion; //===----------------------------------------------------------------------===// @@ -45,22 +46,37 @@ class VarRegion; class MemRegion : public llvm::FoldingSetNode { friend class MemRegionManager; public: - enum Kind { MemSpaceRegionKind, - SymbolicRegionKind, - AllocaRegionKind, - // Typed regions. - BEG_TYPED_REGIONS, - FunctionTextRegionKind, - BlockTextRegionKind, - BlockDataRegionKind, - CompoundLiteralRegionKind, - StringRegionKind, ElementRegionKind, - // Decl Regions. - BEG_DECL_REGIONS, - VarRegionKind, FieldRegionKind, - ObjCIvarRegionKind, ObjCObjectRegionKind, - END_DECL_REGIONS, - END_TYPED_REGIONS }; + enum Kind { + // Memory spaces. + BEG_MEMSPACES, + GenericMemSpaceRegionKind = BEG_MEMSPACES, + StackLocalsSpaceRegionKind, + StackArgumentsSpaceRegionKind, + HeapSpaceRegionKind, + UnknownSpaceRegionKind, + GlobalsSpaceRegionKind, + END_MEMSPACES = GlobalsSpaceRegionKind, + // Untyped regions. + SymbolicRegionKind, + AllocaRegionKind, + // Typed regions. + BEG_TYPED_REGIONS, + FunctionTextRegionKind = BEG_TYPED_REGIONS, + BlockTextRegionKind, + BlockDataRegionKind, + CompoundLiteralRegionKind, + StringRegionKind, + ElementRegionKind, + // Decl Regions. + BEG_DECL_REGIONS, + VarRegionKind = BEG_DECL_REGIONS, + FieldRegionKind, + ObjCIvarRegionKind, + ObjCObjectRegionKind, + END_DECL_REGIONS = ObjCObjectRegionKind, + END_TYPED_REGIONS = END_DECL_REGIONS + }; + private: const Kind kind; @@ -111,25 +127,102 @@ public: /// MemSpaceRegion - A memory region that represents and "memory space"; /// for example, the set of global variables, the stack frame, etc. class MemSpaceRegion : public MemRegion { - friend class MemRegionManager; - protected: + friend class MemRegionManager; + MemRegionManager *Mgr; - MemSpaceRegion(MemRegionManager *mgr) : MemRegion(MemSpaceRegionKind), - Mgr(mgr) {} + MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind) + : MemRegion(k), Mgr(mgr) { + assert(classof(this)); + } + + MemRegionManager* getMemRegionManager() const { return Mgr; } + +public: + bool isBoundable() const { return false; } + + void Profile(llvm::FoldingSetNodeID &ID) const; - MemRegionManager* getMemRegionManager() const { - return Mgr; + static bool classof(const MemRegion *R) { + Kind k = R->getKind(); + return k >= BEG_MEMSPACES && k <= END_MEMSPACES; } +}; + +class GlobalsSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + GlobalsSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, GlobalsSpaceRegionKind) {} public: - void Profile(llvm::FoldingSetNodeID& ID) const; + static bool classof(const MemRegion *R) { + return R->getKind() == GlobalsSpaceRegionKind; + } +}; + +class HeapSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + + HeapSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == HeapSpaceRegionKind; + } +}; + +class UnknownSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + UnknownSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == UnknownSpaceRegionKind; + } +}; + +class StackSpaceRegion : public MemSpaceRegion { +private: + const StackFrameContext *SFC; - bool isBoundable() const { return false; } +protected: + StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) + : MemSpaceRegion(mgr, k), SFC(sfc) { + assert(classof(this)); + } - static bool classof(const MemRegion* R) { - return R->getKind() == MemSpaceRegionKind; +public: + const StackFrameContext *getStackFrame() const { return SFC; } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion *R) { + Kind k = R->getKind(); + return k >= StackLocalsSpaceRegionKind && + k <= StackArgumentsSpaceRegionKind; + } +}; + +class StackLocalsSpaceRegion : public StackSpaceRegion { +private: + friend class MemRegionManager; + StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) + : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == StackLocalsSpaceRegionKind; + } +}; + +class StackArgumentsSpaceRegion : public StackSpaceRegion { +private: + friend class MemRegionManager; + StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) + : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == StackArgumentsSpaceRegionKind; } }; @@ -149,7 +242,7 @@ public: bool isSubRegionOf(const MemRegion* R) const; static bool classof(const MemRegion* R) { - return R->getKind() > MemSpaceRegionKind; + return R->getKind() > END_MEMSPACES; } }; @@ -237,7 +330,7 @@ public: static bool classof(const MemRegion* R) { unsigned k = R->getKind(); - return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS; + return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS; } }; @@ -295,12 +388,17 @@ public: /// like a closure a block captures the values of externally referenced /// variables. class BlockTextRegion : public CodeTextRegion { + friend class MemRegionManager; + const BlockDecl *BD; + AnalysisContext *AC; CanQualType locTy; -public: - BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg) - : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {} - + + BlockTextRegion(const BlockDecl *bd, CanQualType lTy, + AnalysisContext *ac, const MemRegion* sreg) + : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} + +public: QualType getLocationType(ASTContext &C) const { return locTy; } @@ -308,13 +406,16 @@ public: const BlockDecl *getDecl() const { return BD; } + + AnalysisContext *getAnalysisContext() const { return AC; } virtual void dumpToStream(llvm::raw_ostream& os) const; void Profile(llvm::FoldingSetNodeID& ID) const; static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, - CanQualType, const MemRegion*); + CanQualType, const AnalysisContext*, + const MemRegion*); static bool classof(const MemRegion* R) { return R->getKind() == BlockTextRegionKind; @@ -329,18 +430,45 @@ public: /// variables. /// BlockDataRegion - A region that represents code texts of blocks (closures). class BlockDataRegion : public SubRegion { + friend class MemRegionManager; const BlockTextRegion *BC; - const LocationContext *LC; + const LocationContext *LC; // Can be null */ void *ReferencedVars; -public: - BlockDataRegion(const BlockTextRegion *bc, - const LocationContext *lc, + + BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc, const MemRegion *sreg) : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {} +public: const BlockTextRegion *getCodeRegion() const { return BC; } - typedef const MemRegion * const * referenced_vars_iterator; + const BlockDecl *getDecl() const { return BC->getDecl(); } + + class referenced_vars_iterator { + const MemRegion * const *R; + public: + explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {} + + operator const MemRegion * const *() const { + return R; + } + + const VarRegion* operator*() const { + return cast<VarRegion>(*R); + } + + bool operator==(const referenced_vars_iterator &I) const { + return I.R == R; + } + bool operator!=(const referenced_vars_iterator &I) const { + return I.R != R; + } + referenced_vars_iterator& operator++() { + ++R; + return *this; + } + }; + referenced_vars_iterator referenced_vars_begin() const; referenced_vars_iterator referenced_vars_end() const; @@ -348,9 +476,8 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, - const BlockTextRegion *BC, - const LocationContext *LC, const MemRegion *); + static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *, + const LocationContext *, const MemRegion *); static bool classof(const MemRegion* R) { return R->getKind() == BlockDataRegionKind; @@ -473,25 +600,20 @@ public: static bool classof(const MemRegion* R) { unsigned k = R->getKind(); - return k > BEG_DECL_REGIONS && k < END_DECL_REGIONS; + return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS; } }; class VarRegion : public DeclRegion { friend class MemRegionManager; - // Data. - const LocationContext *LC; - // Constructors and private methods. - VarRegion(const VarDecl* vd, const LocationContext *lC, const MemRegion* sReg) - : DeclRegion(vd, sReg, VarRegionKind), LC(lC) {} + VarRegion(const VarDecl* vd, const MemRegion* sReg) + : DeclRegion(vd, sReg, VarRegionKind) {} static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD, - const LocationContext *LC, const MemRegion *superRegion) { DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); - ID.AddPointer(LC); } void Profile(llvm::FoldingSetNodeID& ID) const; @@ -499,8 +621,8 @@ class VarRegion : public DeclRegion { public: const VarDecl *getDecl() const { return cast<VarDecl>(D); } - const LocationContext *getLocationContext() const { return LC; } - + const StackFrameContext *getStackFrame() const; + QualType getValueType(ASTContext& C) const { // FIXME: We can cache this if needed. return C.getCanonicalType(getDecl()->getType()); @@ -647,17 +769,24 @@ class MemRegionManager { llvm::BumpPtrAllocator& A; llvm::FoldingSet<MemRegion> Regions; - MemSpaceRegion *globals; - MemSpaceRegion *stack; - MemSpaceRegion *stackArguments; - MemSpaceRegion *heap; - MemSpaceRegion *unknown; + GlobalsSpaceRegion *globals; + + const StackFrameContext *cachedStackLocalsFrame; + StackLocalsSpaceRegion *cachedStackLocalsRegion; + + const StackFrameContext *cachedStackArgumentsFrame; + StackArgumentsSpaceRegion *cachedStackArgumentsRegion; + + HeapSpaceRegion *heap; + UnknownSpaceRegion *unknown; MemSpaceRegion *code; public: MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0), - unknown(0), code(0) {} + : C(c), A(a), globals(0), + cachedStackLocalsFrame(0), cachedStackLocalsRegion(0), + cachedStackArgumentsFrame(0), cachedStackArgumentsRegion(0), + heap(0), unknown(0), code(0) {} ~MemRegionManager(); @@ -665,52 +794,60 @@ public: llvm::BumpPtrAllocator &getAllocator() { return A; } - /// getStackRegion - Retrieve the memory region associated with the - /// current stack frame. - MemSpaceRegion *getStackRegion(); + /// getStackLocalsRegion - Retrieve the memory region associated with the + /// specified stack frame. + const StackLocalsSpaceRegion * + getStackLocalsRegion(const StackFrameContext *STC); /// getStackArgumentsRegion - Retrieve the memory region associated with - /// function/method arguments of the current stack frame. - MemSpaceRegion *getStackArgumentsRegion(); + /// function/method arguments of the specified stack frame. + const StackArgumentsSpaceRegion * + getStackArgumentsRegion(const StackFrameContext *STC); /// getGlobalsRegion - Retrieve the memory region associated with /// all global variables. - MemSpaceRegion *getGlobalsRegion(); + const GlobalsSpaceRegion *getGlobalsRegion(); /// getHeapRegion - Retrieve the memory region associated with the /// generic "heap". - MemSpaceRegion *getHeapRegion(); + const HeapSpaceRegion *getHeapRegion(); /// getUnknownRegion - Retrieve the memory region associated with unknown /// memory space. - MemSpaceRegion *getUnknownRegion(); + const MemSpaceRegion *getUnknownRegion(); - MemSpaceRegion *getCodeRegion(); + const MemSpaceRegion *getCodeRegion(); /// getAllocaRegion - Retrieve a region associated with a call to alloca(). - AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt); + const AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt, + const LocationContext *LC); /// getCompoundLiteralRegion - Retrieve the region associated with a /// given CompoundLiteral. - CompoundLiteralRegion* - getCompoundLiteralRegion(const CompoundLiteralExpr* CL); + const CompoundLiteralRegion* + getCompoundLiteralRegion(const CompoundLiteralExpr* CL, + const LocationContext *LC); /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. - SymbolicRegion* getSymbolicRegion(SymbolRef sym); + const SymbolicRegion* getSymbolicRegion(SymbolRef sym); - StringRegion* getStringRegion(const StringLiteral* Str); + const StringRegion* getStringRegion(const StringLiteral* Str); /// getVarRegion - Retrieve or create the memory region associated with /// a specified VarDecl and LocationContext. - VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC); + const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC); + /// getVarRegion - Retrieve or create the memory region associated with + /// a specified VarDecl and super region. + const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR); + /// getElementRegion - Retrieve the memory region associated with the /// associated element type, index, and super region. - ElementRegion *getElementRegion(QualType elementType, SVal Idx, + const ElementRegion *getElementRegion(QualType elementType, SVal Idx, const MemRegion *superRegion, ASTContext &Ctx); - ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, + const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER, const MemRegion *superRegion) { return getElementRegion(ER->getElementType(), ER->getIndex(), superRegion, ER->getContext()); @@ -720,31 +857,44 @@ public: /// a specified FieldDecl. 'superRegion' corresponds to the containing /// memory region (which typically represents the memory representing /// a structure or class). - FieldRegion *getFieldRegion(const FieldDecl* fd, - const MemRegion* superRegion); + const FieldRegion *getFieldRegion(const FieldDecl* fd, + const MemRegion* superRegion); - FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR, - const MemRegion *superRegion) { + const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR, + const MemRegion *superRegion) { return getFieldRegion(FR->getDecl(), superRegion); } /// getObjCObjectRegion - Retrieve or create the memory region associated with /// the instance of a specified Objective-C class. - ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID, - const MemRegion* superRegion); + const ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID, + const MemRegion* superRegion); /// getObjCIvarRegion - Retrieve or create the memory region associated with /// a specified Objective-c instance variable. 'superRegion' corresponds /// to the containing region (which typically represents the Objective-C /// object). - ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, - const MemRegion* superRegion); + const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, + const MemRegion* superRegion); - FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); - BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy); - BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, - const LocationContext *lc); + const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); + const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, + CanQualType locTy, + AnalysisContext *AC); + + /// getBlockDataRegion - Get the memory region associated with an instance + /// of a block. Unlike many other MemRegions, the LocationContext* + /// argument is allowed to be NULL for cases where we have no known + /// context. + const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, + const LocationContext *lc = NULL); + bool isGlobalsRegion(const MemRegion* R) { + assert(R); + return R == globals; + } + +private: template <typename RegionTy, typename A1> RegionTy* getRegion(const A1 a1); @@ -758,13 +908,15 @@ public: RegionTy* getSubRegion(const A1 a1, const A2 a2, const MemRegion* superRegion); - bool isGlobalsRegion(const MemRegion* R) { - assert(R); - return R == globals; - } - -private: - MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region); + template <typename RegionTy, typename A1, typename A2, typename A3> + RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3, + const MemRegion* superRegion); + + template <typename REG> + const REG* LazyAllocate(REG*& region); + + template <typename REG, typename ARG> + const REG* LazyAllocate(REG*& region, ARG a); }; //===----------------------------------------------------------------------===// @@ -774,157 +926,6 @@ private: inline ASTContext& MemRegion::getContext() const { return getMemRegionManager()->getContext(); } - -template<typename RegionTy> struct MemRegionManagerTrait; - -template <typename RegionTy, typename A1> -RegionTy* MemRegionManager::getRegion(const A1 a1) { - - const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion = - MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1); - - llvm::FoldingSetNodeID ID; - RegionTy::ProfileRegion(ID, a1, superRegion); - void* InsertPos; - RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, - InsertPos)); - - if (!R) { - R = (RegionTy*) A.Allocate<RegionTy>(); - new (R) RegionTy(a1, superRegion); - Regions.InsertNode(R, InsertPos); - } - - return R; -} - -template <typename RegionTy, typename A1> -RegionTy* MemRegionManager::getSubRegion(const A1 a1, - const MemRegion *superRegion) { - llvm::FoldingSetNodeID ID; - RegionTy::ProfileRegion(ID, a1, superRegion); - void* InsertPos; - RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, - InsertPos)); - - if (!R) { - R = (RegionTy*) A.Allocate<RegionTy>(); - new (R) RegionTy(a1, superRegion); - Regions.InsertNode(R, InsertPos); - } - - return R; -} - -template <typename RegionTy, typename A1, typename A2> -RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) { - - const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion = - MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2); - - llvm::FoldingSetNodeID ID; - RegionTy::ProfileRegion(ID, a1, a2, superRegion); - void* InsertPos; - RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, - InsertPos)); - - if (!R) { - R = (RegionTy*) A.Allocate<RegionTy>(); - new (R) RegionTy(a1, a2, superRegion); - Regions.InsertNode(R, InsertPos); - } - - return R; -} - -template <typename RegionTy, typename A1, typename A2> -RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, - const MemRegion *superRegion) { - - llvm::FoldingSetNodeID ID; - RegionTy::ProfileRegion(ID, a1, a2, superRegion); - void* InsertPos; - RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, - InsertPos)); - - if (!R) { - R = (RegionTy*) A.Allocate<RegionTy>(); - new (R) RegionTy(a1, a2, superRegion); - Regions.InsertNode(R, InsertPos); - } - - return R; -} - -//===----------------------------------------------------------------------===// -// Traits for constructing regions. -//===----------------------------------------------------------------------===// - -template <> struct MemRegionManagerTrait<AllocaRegion> { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const Expr *, unsigned) { - return MRMgr.getStackRegion(); - } -}; - -template <> struct MemRegionManagerTrait<CompoundLiteralRegion> { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const CompoundLiteralExpr *CL) { - - return CL->isFileScope() ? MRMgr.getGlobalsRegion() - : MRMgr.getStackRegion(); - } -}; - -template <> struct MemRegionManagerTrait<StringRegion> { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const StringLiteral*) { - return MRMgr.getGlobalsRegion(); - } -}; - -template <> struct MemRegionManagerTrait<VarRegion> { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager &MRMgr, - const VarDecl *D, - const LocationContext *LC) { - - // FIXME: Make stack regions have a location context? - - if (D->hasLocalStorage()) { - return isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) - ? MRMgr.getStackArgumentsRegion() : MRMgr.getStackRegion(); - } - - return MRMgr.getGlobalsRegion(); - } -}; - -template <> struct MemRegionManagerTrait<SymbolicRegion> { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - SymbolRef) { - return MRMgr.getUnknownRegion(); - } -}; - -template<> struct MemRegionManagerTrait<FunctionTextRegion> { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const FunctionDecl*) { - return MRMgr.getCodeRegion(); - } -}; -template<> struct MemRegionManagerTrait<BlockTextRegion> { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const BlockDecl*, CanQualType) { - return MRMgr.getCodeRegion(); - } -}; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 55fa83d9ecc3..648710f7ad12 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -73,8 +73,9 @@ public: /// for the compound literal and 'BegInit' and 'EndInit' represent an /// array of initializer values. virtual const GRState *BindCompoundLiteral(const GRState *state, - const CompoundLiteralExpr* cl, - SVal v) = 0; + const CompoundLiteralExpr* cl, + const LocationContext *LC, + SVal v) = 0; /// getInitialStore - Returns the initial "empty" store representing the /// value bindings upon entry to an analyzed function. @@ -93,7 +94,8 @@ public: virtual SVal getLValueString(const StringLiteral* sl) = 0; - virtual SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl) = 0; + SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl, + const LocationContext *LC); virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) = 0; @@ -147,6 +149,12 @@ public: const MemRegion *R, const Expr *E, unsigned Count, InvalidatedSymbols *IS) = 0; + + virtual const GRState *InvalidateRegions(const GRState *state, + const MemRegion * const *Begin, + const MemRegion * const *End, + const Expr *E, unsigned Count, + InvalidatedSymbols *IS); // FIXME: Make out-of-line. virtual const GRState *setExtent(const GRState *state, diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h index 167a102e94ec..8eb319647953 100644 --- a/include/clang/Analysis/PathSensitive/SymbolManager.h +++ b/include/clang/Analysis/PathSensitive/SymbolManager.h @@ -28,10 +28,12 @@ namespace llvm { } namespace clang { - class MemRegion; - class TypedRegion; class ASTContext; class BasicValueFactory; + class MemRegion; + class TypedRegion; + class VarRegion; + class StackFrameContext; } namespace clang { @@ -332,10 +334,13 @@ class SymbolReaper { SetTy TheDead; LiveVariables& Liveness; SymbolManager& SymMgr; + const StackFrameContext *CurrentStackFrame; public: - SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr) - : Liveness(liveness), SymMgr(symmgr) {} + SymbolReaper(LiveVariables& liveness, SymbolManager& symmgr, + const StackFrameContext *currentStackFrame) + : Liveness(liveness), SymMgr(symmgr), CurrentStackFrame(currentStackFrame) + {} ~SymbolReaper() {} @@ -345,10 +350,8 @@ public: return Liveness.isLive(Loc, ExprVal); } - bool isLive(const Stmt* Loc, const VarDecl* VD) const { - return Liveness.isLive(Loc, VD); - } - + bool isLive(const Stmt* Loc, const VarRegion *VR) const; + void markLive(SymbolRef sym); bool maybeDead(SymbolRef sym); diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 78827dfabe2f..5abe1abd5d39 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -333,10 +333,11 @@ static bool isEqual(const clang::ProgramPoint& L, return L == R; } -static bool isPod() { - return true; -} }; + +template <> +struct isPodLike<clang::ProgramPoint> { static const bool value = true; }; + } // end namespace llvm #endif diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index b23a80ed481a..48851d0f2637 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -166,7 +166,7 @@ public: private: /// grow - double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. - void grow(BumpVectorContext &C, size_type MinSize = 0); + void grow(BumpVectorContext &C, size_type MinSize = 1); void construct_range(T *S, T *E, const T &Elt) { for (; S != E; ++S) diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 98c703d94e92..e700cdeb5d6c 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -118,51 +118,51 @@ BUILTIN(__builtin_powf, "fff" , "nc") BUILTIN(__builtin_powl, "LdLdLd", "nc") // Standard unary libc/libm functions with double/float/long double variants: -BUILTIN(__builtin_acos , "dd" , "nc") -BUILTIN(__builtin_acosf, "ff" , "nc") -BUILTIN(__builtin_acosl, "LdLd", "nc") -BUILTIN(__builtin_asin , "dd" , "nc") -BUILTIN(__builtin_asinf, "ff" , "nc") -BUILTIN(__builtin_asinl, "LdLd", "nc") -BUILTIN(__builtin_atan , "dd" , "nc") -BUILTIN(__builtin_atanf, "ff" , "nc") -BUILTIN(__builtin_atanl, "LdLd", "nc") -BUILTIN(__builtin_ceil , "dd" , "nc") -BUILTIN(__builtin_ceilf, "ff" , "nc") -BUILTIN(__builtin_ceill, "LdLd", "nc") -BUILTIN(__builtin_cos , "dd" , "nc") -BUILTIN(__builtin_cosf, "ff" , "nc") -BUILTIN(__builtin_cosh , "dd" , "nc") -BUILTIN(__builtin_coshf, "ff" , "nc") -BUILTIN(__builtin_coshl, "LdLd", "nc") -BUILTIN(__builtin_cosl, "LdLd", "nc") -BUILTIN(__builtin_exp , "dd" , "nc") -BUILTIN(__builtin_expf, "ff" , "nc") -BUILTIN(__builtin_expl, "LdLd", "nc") -BUILTIN(__builtin_floor , "dd" , "nc") -BUILTIN(__builtin_floorf, "ff" , "nc") -BUILTIN(__builtin_floorl, "LdLd", "nc") -BUILTIN(__builtin_log , "dd" , "nc") -BUILTIN(__builtin_log10 , "dd" , "nc") -BUILTIN(__builtin_log10f, "ff" , "nc") -BUILTIN(__builtin_log10l, "LdLd", "nc") -BUILTIN(__builtin_logf, "ff" , "nc") -BUILTIN(__builtin_logl, "LdLd", "nc") -BUILTIN(__builtin_sin , "dd" , "nc") -BUILTIN(__builtin_sinf, "ff" , "nc") -BUILTIN(__builtin_sinh , "dd" , "nc") -BUILTIN(__builtin_sinhf, "ff" , "nc") -BUILTIN(__builtin_sinhl, "LdLd", "nc") -BUILTIN(__builtin_sinl, "LdLd", "nc") -BUILTIN(__builtin_sqrt , "dd" , "nc") -BUILTIN(__builtin_sqrtf, "ff" , "nc") -BUILTIN(__builtin_sqrtl, "LdLd", "nc") -BUILTIN(__builtin_tan , "dd" , "nc") -BUILTIN(__builtin_tanf, "ff" , "nc") -BUILTIN(__builtin_tanh , "dd" , "nc") -BUILTIN(__builtin_tanhf, "ff" , "nc") -BUILTIN(__builtin_tanhl, "LdLd", "nc") -BUILTIN(__builtin_tanl, "LdLd", "nc") +BUILTIN(__builtin_acos , "dd" , "Fnc") +BUILTIN(__builtin_acosf, "ff" , "Fnc") +BUILTIN(__builtin_acosl, "LdLd", "Fnc") +BUILTIN(__builtin_asin , "dd" , "Fnc") +BUILTIN(__builtin_asinf, "ff" , "Fnc") +BUILTIN(__builtin_asinl, "LdLd", "Fnc") +BUILTIN(__builtin_atan , "dd" , "Fnc") +BUILTIN(__builtin_atanf, "ff" , "Fnc") +BUILTIN(__builtin_atanl, "LdLd", "Fnc") +BUILTIN(__builtin_ceil , "dd" , "Fnc") +BUILTIN(__builtin_ceilf, "ff" , "Fnc") +BUILTIN(__builtin_ceill, "LdLd", "Fnc") +BUILTIN(__builtin_cos , "dd" , "Fnc") +BUILTIN(__builtin_cosf, "ff" , "Fnc") +BUILTIN(__builtin_cosh , "dd" , "Fnc") +BUILTIN(__builtin_coshf, "ff" , "Fnc") +BUILTIN(__builtin_coshl, "LdLd", "Fnc") +BUILTIN(__builtin_cosl, "LdLd", "Fnc") +BUILTIN(__builtin_exp , "dd" , "Fnc") +BUILTIN(__builtin_expf, "ff" , "Fnc") +BUILTIN(__builtin_expl, "LdLd", "Fnc") +BUILTIN(__builtin_floor , "dd" , "Fnc") +BUILTIN(__builtin_floorf, "ff" , "Fnc") +BUILTIN(__builtin_floorl, "LdLd", "Fnc") +BUILTIN(__builtin_log , "dd" , "Fnc") +BUILTIN(__builtin_log10 , "dd" , "Fnc") +BUILTIN(__builtin_log10f, "ff" , "Fnc") +BUILTIN(__builtin_log10l, "LdLd", "Fnc") +BUILTIN(__builtin_logf, "ff" , "Fnc") +BUILTIN(__builtin_logl, "LdLd", "Fnc") +BUILTIN(__builtin_sin , "dd" , "Fnc") +BUILTIN(__builtin_sinf, "ff" , "Fnc") +BUILTIN(__builtin_sinh , "dd" , "Fnc") +BUILTIN(__builtin_sinhf, "ff" , "Fnc") +BUILTIN(__builtin_sinhl, "LdLd", "Fnc") +BUILTIN(__builtin_sinl, "LdLd", "Fnc") +BUILTIN(__builtin_sqrt , "dd" , "Fnc") +BUILTIN(__builtin_sqrtf, "ff" , "Fnc") +BUILTIN(__builtin_sqrtl, "LdLd", "Fnc") +BUILTIN(__builtin_tan , "dd" , "Fnc") +BUILTIN(__builtin_tanf, "ff" , "Fnc") +BUILTIN(__builtin_tanh , "dd" , "Fnc") +BUILTIN(__builtin_tanhf, "ff" , "Fnc") +BUILTIN(__builtin_tanhl, "LdLd", "Fnc") +BUILTIN(__builtin_tanl, "LdLd", "Fnc") // C99 complex builtins BUILTIN(__builtin_cabs, "dXd", "Fnc") diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index bbf42ee8c7fe..6315c16dd80a 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -250,7 +250,7 @@ BUILTIN(__builtin_ia32_pmaddwd128, "V8sV8sV8s", "") BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "") BUILTIN(__builtin_ia32_mwait, "vUiUi", "") BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") -BUILTIN(__builtin_ia32_palignr128, "V2LLiV2LLiV2LLic", "") +BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cc", "") BUILTIN(__builtin_ia32_palignr, "V1LLiV1LLiV1LLic", "") BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 00a5bc6e937d..b2523f28d5e0 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -238,7 +238,6 @@ public: DiagnosticClient *getClient() { return Client; } const DiagnosticClient *getClient() const { return Client; } - /// pushMappings - Copies the current DiagMappings and pushes the new copy /// onto the top of the stack. void pushMappings(); @@ -319,7 +318,7 @@ public: /// getCustomDiagID - Return an ID for a diagnostic with the specified message /// and level. If this is the first request for this diagnosic, it is /// registered and created, otherwise the existing ID is returned. - unsigned getCustomDiagID(Level L, const char *Message); + unsigned getCustomDiagID(Level L, llvm::StringRef Message); /// ConvertArgToString - This method converts a diagnostic argument (as an diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 9a342b592ca5..f319cf231a26 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -26,8 +26,8 @@ def note_type_being_defined : Note< /// e.g. to specify the '(' when we expected a ')'. def note_matching : Note<"to match this '%0'">; -def note_using_decl : Note<"using">; -def note_also_found_decl : Note<"also found">; +def note_using : Note<"using">; +def note_also_found : Note<"also found">; // Parse && Lex def err_expected_colon : Error<"expected ':'">; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 3f7d114dda60..efbc787ef0ee 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -60,6 +60,8 @@ def err_drv_I_dash_not_supported : Error< def err_drv_unknown_argument : Error<"unknown argument: '%0'">; def err_drv_invalid_value : Error<"invalid value '%1' in '%0'">; def err_drv_invalid_int_value : Error<"invalid integral value '%1' in '%0'">; +def err_drv_invalid_remap_file : Error< + "invalid option '%0' not of the form <from-file>;<to-file>">; def warn_drv_input_file_unused : Warning< "%0: '%1' input unused when '%2' is present">; @@ -70,7 +72,7 @@ def warn_drv_unused_argument : Warning< def warn_drv_pipe_ignored_with_save_temps : Warning< "-pipe ignored because -save-temps specified">; def warn_drv_not_using_clang_cpp : Warning< - "not using the clang prepreprocessor due to user override">; + "not using the clang preprocessor due to user override">; def warn_drv_not_using_clang_cxx : Warning< "not using the clang compiler for C++ inputs">; def warn_drv_not_using_clang_arch : Warning< diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index cbc287c58c89..252900d18b3f 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -15,8 +15,8 @@ def err_fe_error_reading_stdin : Error<"error reading stdin">; def err_fe_error_backend : Error<"error in backend: %0">, DefaultFatal; def err_fe_invalid_ast_file : Error<"invalid AST file: '%0'">, DefaultFatal; def err_fe_invalid_ast_action : Error<"invalid action for AST input">, DefaultFatal; -def err_fe_invalid_code_complete_file - : Error<"cannot locate code-completion file %0">, DefaultFatal; +def err_fe_invalid_code_complete_file : Error< + "cannot locate code-completion file %0">, DefaultFatal; def err_fe_stdout_binary : Error<"unable to change standard output to binary">, DefaultFatal; def err_fe_dependency_file_requires_MT : Error< @@ -29,6 +29,36 @@ def err_fe_unable_to_find_fixit_file : Error< "FIX-IT could not find file '%0'">; def err_fe_invalid_plugin_name : Error< "unable to find plugin '%0'">; +def err_fe_expected_compiler_job : Error< + "unable to handle compilation, expected exactly one compiler job in '%0'">; +def err_fe_expected_clang_command : Error< + "expected a clang compiler command">; +def err_fe_remap_missing_to_file : Error< + "could not remap file '%0' to the contents of file '%1'">, DefaultFatal; +def err_fe_remap_missing_from_file : Error< + "could not remap from missing file '%0'">, DefaultFatal; +def err_fe_unable_to_load_pch : Error< + "unable to load PCH file">; +def err_fe_unable_to_load_plugin : Error< + "unable to load plugin '%0': '%1'">; +def err_fe_unable_to_create_target : Error< + "unable to create target: '%0'">; +def err_fe_unable_to_interface_with_target : Error< + "unable to interface with target machine">; +def err_fe_unable_to_read_pch_file : Error< + "unable to read PCH file: '%0'">; +def err_fe_not_a_pch_file : Error< + "input is not a PCH file: '%0'">; +def err_fe_pch_malformed_block : Error< + "malformed block record in PCH file: '%0'">; +def err_fe_pch_error_at_end_block : Error< + "error at end of module block in PCH file: '%0'">; +def err_fe_unable_to_open_output : Error< + "unable to open output file '%0': '%1'">; +def err_fe_pth_file_has_no_source_header : Error< + "PTH file '%0' does not designate an original source header file for -include-pth">; +def warn_fe_macro_contains_embedded_newline : Warning< + "macro '%0' contains embedded newline, text after the newline is ignored.">; def err_verify_bogus_characters : Error< "bogus characters before '{{' in expected string">; @@ -45,6 +75,8 @@ def note_fixit_in_macro : Note< def note_fixit_failed : Note< "FIX-IT unable to apply suggested code changes">; def note_fixit_unfixed_error : Note<"FIX-IT detected an error it cannot fix">; +def note_fixit_main_file_unchanged : Note< + "main file unchanged">; def warn_fixit_no_changes : Note< "FIX-IT detected errors it could not fix; no output will be generated">; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index c1c833cf5c66..761478abd3d4 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -113,6 +113,7 @@ def Reorder : DiagGroup<"reorder">; def UndeclaredSelector : DiagGroup<"undeclared-selector">; def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def : DiagGroup<"variadic-macros">; +def VariadicMacros : DiagGroup<"variadic-macros">; def VectorConversions : DiagGroup<"vector-conversions">; // clang specific def VolatileRegisterVar : DiagGroup<"volatile-register-var">; def : DiagGroup<"write-strings">; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 39123d9b371a..d8b5f2dad3c9 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -51,6 +51,9 @@ def err_empty_character : Error<"empty character constant">; def err_unterminated_block_comment : Error<"unterminated /* comment">; def err_invalid_character_to_charify : Error< "invalid argument to convert to character">; + +def err_conflict_marker : Error<"version control conflict marker in file">; + def ext_multichar_character_literal : ExtWarn< "multi-character character constant">, InGroup<MultiChar>; def ext_four_char_character_literal : Extension< @@ -150,9 +153,10 @@ def ext_pp_comma_expr : Extension<"comma operator in operand of #if">; def ext_pp_bad_vaargs_use : Extension< "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro">; def ext_pp_macro_redef : ExtWarn<"%0 macro redefined">; -def ext_variadic_macro : Extension<"variadic macros were introduced in C99">; +def ext_variadic_macro : Extension<"variadic macros were introduced in C99">, + InGroup<VariadicMacros>; def ext_named_variadic_macro : Extension< - "named variadic macros are a GNU extension">; + "named variadic macros are a GNU extension">, InGroup<VariadicMacros>; def ext_embedded_directive : Extension< "embedding a directive within macro arguments is not portable">; def ext_missing_varargs_arg : Extension< @@ -160,18 +164,11 @@ def ext_missing_varargs_arg : Extension< def ext_empty_fnmacro_arg : Extension< "empty macro arguments were standardized in C99">; -def ext_pp_base_file : Extension<"__BASE_FILE__ is a language extension">; -def ext_pp_include_level : Extension< - "__INCLUDE_LEVEL__ is a language extension">; -def ext_pp_timestamp : Extension<"__TIMESTAMP__ is a language extension">; -def ext_pp_counter : Extension< - "__COUNTER__ is a language extension">; - def err_pp_invalid_directive : Error<"invalid preprocessing directive">; def err_pp_hash_error : Error<"#error%0">; def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; def err_pp_error_opening_file : Error< - "error opening file '%0'">, DefaultFatal; + "error opening file '%0': %1">, DefaultFatal; def err_pp_empty_filename : Error<"empty filename">; def err_pp_include_too_deep : Error<"#include nested too deeply">; def err_pp_expects_filename : Error<"expected \"FILENAME\" or <FILENAME>">; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 43107044720e..bf188cf14f91 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -166,6 +166,8 @@ def err_use_of_tag_name_without_tag : Error< "use of tagged type %0 without '%1' tag">; def err_expected_ident_in_using : Error< "expected an identifier in using directive">; +def err_unexected_colon_in_nested_name_spec : Error< + "unexpected ':' in nested name specifier">; /// Objective-C parser diagnostics def err_objc_no_attributes_on_category : Error< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a0e03fed1600..a890323e6c0d 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -105,7 +105,11 @@ def err_using_typename_non_type : Error< "'typename' keyword used on a non-type">; def err_using_dependent_value_is_type : Error< "dependent using declaration resolved to type without 'typename'">; -def err_using_decl_nested_name_specifier_is_not_a_base_class : Error< +def err_using_decl_nested_name_specifier_is_not_class : Error< + "using declaration in class refers into '%0', which is not a class">; +def err_using_decl_nested_name_specifier_is_current_class : Error< + "using declaration refers to its own class">; +def err_using_decl_nested_name_specifier_is_not_base_class : Error< "using declaration refers into '%0', which is not a base class of %1">; def err_using_decl_can_not_refer_to_class_member : Error< "using declaration can not refer to class member">; @@ -117,8 +121,17 @@ def err_using_decl_destructor : Error< "using declaration can not refer to a destructor">; def err_using_decl_template_id : Error< "using declaration can not refer to a template specialization">; -def note_using_decl_target : Note< - "target of using declaration">; +def note_using_decl_target : Note<"target of using declaration">; +def note_using_decl_conflict : Note<"conflicting declaration">; +def err_using_decl_redeclaration : Error<"redeclaration of using decl">; +def err_using_decl_conflict : Error< + "target of using declaration conflicts with declaration already in scope">; +def err_using_decl_conflict_reverse : Error< + "declaration conflicts with target of using declaration already in scope">; +def note_using_decl : Note<"%select{|previous }0using declaration">; + +def warn_access_decl_deprecated : Warning< + "access declarations are deprecated; use using declarations instead">; def err_invalid_thread : Error< "'__thread' is only allowed on variable declarations">; @@ -186,7 +199,6 @@ def warn_pragma_pack_invalid_alignment : Warning< "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">; // Follow the MSVC implementation. def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">; -// FIXME: Dehardcode. def warn_pragma_pack_pop_identifer_and_alignment : Warning< "specifying both a name and alignment to 'pop' is undefined">; def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">; @@ -441,7 +453,8 @@ def err_implicit_object_parameter_init : Error< "of type %1">; def note_field_decl : Note<"member is declared here">; -def note_previous_class_decl : Note< +def note_bitfield_decl : Note<"bit-field is declared here">; +def note_previous_decl : Note< "%0 declared here">; def note_member_synthesized_at : Note< "implicit default %select{constructor|copy constructor|" @@ -521,14 +534,35 @@ def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lval def err_not_reference_to_const_init : Error< "non-const lvalue reference to type %0 cannot be initialized " "with a %1 of type %2">; +def err_lvalue_reference_bind_to_temporary : Error< + "non-const lvalue reference to type %0 cannot bind to a temporary of type " + "%1">; +def err_lvalue_reference_bind_to_unrelated : Error< + "non-const lvalue reference to type %0 cannot bind to a value of unrelated " + "type %1">; +def err_reference_bind_drops_quals : Error< + "binding of reference to type %0 to a value of type %1 drops qualifiers">; +def err_reference_bind_failed : Error< + "reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type " + "%2">; +def err_reference_bind_init_list : Error< + "reference to type %0 cannot bind to an initializer list">; +def err_init_list_bad_dest_type : Error< + "%select{|non-aggregate }0type %1 cannot be initialized with an initializer " + "list">; + // FIXME: passing in an English string as %1! def err_reference_init_drops_quals : Error< "initialization of reference to type %0 with a %1 of type %2 drops " "qualifiers">; +def err_reference_bind_to_bitfield : Error< + "%select{non-const|volatile}0 reference cannot bind to bit-field %1">; def err_reference_var_requires_init : Error< "declaration of reference variable %0 requires an initializer">; def err_const_var_requires_init : Error< "declaration of const variable '%0' requires an initializer">; +def err_reference_has_multiple_inits : Error< + "reference cannot be initialized with multiple values">; def err_init_non_aggr_init_list : Error< "initialization of non-aggregate type %0 with an initializer list">; def err_init_reference_member_uninitialized : Error< @@ -934,6 +968,11 @@ def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; def err_template_tag_noparams : Error< "extraneous 'template<>' in declaration of %0 %1">; +def err_template_decl_ref : Error< + "cannot refer to class template %0 without a template argument list">; + +def err_typedef_in_def_scope : Error< + "cannot use typedef %0 in scope specifier for out-of-line declaration">; // C++ Template Argument Lists def err_template_arg_list_different_arity : Error< @@ -1261,7 +1300,10 @@ def warn_missing_prototype : Warning< "no previous prototype for function %0">, InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore; def err_redefinition : Error<"redefinition of %0">; - +def err_definition_of_implicitly_declared_member : Error< + "definition of implicitly declared %select{constructor|copy constructor|" + "copy assignment operator|destructor}1">; + def warn_redefinition_of_typedef : Warning< "redefinition of typedef %0 is invalid in C">, InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError; @@ -1515,6 +1557,8 @@ def err_typecheck_member_reference_ivar : Error< "%0 does not have a member named %1">; def err_typecheck_member_reference_arrow : Error< "member reference type %0 is not a pointer">; +def err_typecheck_member_reference_suggestion : Error< + "member reference type %0 is %select{a|not a}1 pointer; maybe you meant to use '%select{->|.}1'?">; def err_typecheck_member_reference_type : Error< "cannot refer to type member %0 with '%select{.|->}1'">; def err_typecheck_member_reference_unknown : Error< @@ -1564,6 +1608,9 @@ def warn_tentative_incomplete_array : Warning< def err_typecheck_incomplete_array_needs_initializer : Error< "definition of variable with array type needs an explicit size " "or an initializer">; +def err_array_init_not_init_list : Error< + "array initializater must be an initializer " + "list%select{| or string literal}0">; def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">; def err_typecheck_sclass_fscope : Error< @@ -1649,6 +1696,7 @@ def warn_printf_nonliteral : Warning< def err_unexpected_interface : Error< "unexpected interface name %0: expected expression">; +def err_ref_non_value : Error<"%0 does not refer to a value">; def err_property_not_found : Error< "property %0 not found on object of type %1">; def ext_gnu_void_ptr : Extension< @@ -1849,7 +1897,10 @@ def err_typecheck_bool_condition : Error< def err_typecheck_ambiguous_condition : Error< "conversion from %0 to %1 is ambiguous">; def err_typecheck_nonviable_condition : Error< - "no viable conversion from %0 to %1 is possible">; + "no viable conversion from %0 to %1">; +def err_typecheck_deleted_function : Error< + "conversion function from %0 to %1 invokes a deleted function">; + def err_expected_class_or_namespace : Error<"expected a class or namespace">; def err_invalid_declarator_scope : Error< "definition or redeclaration of %0 not in a namespace enclosing %1">; @@ -1963,7 +2014,8 @@ def err_cannot_pass_objc_interface_to_vararg : Error< def warn_cannot_pass_non_pod_arg_to_vararg : Warning< "cannot pass object of non-POD type %0 through variadic " - "%select{function|block|method|constructor}1; call will abort at runtime">; + "%select{function|block|method|constructor}1; call will abort at runtime">, + InGroup<DiagGroup<"non-pod-varargs">>, DefaultError; def err_typecheck_call_invalid_ordered_compare : Error< "ordered compare requires two args of floating point type (%0 and %1)">; @@ -2047,12 +2099,6 @@ def err_overload_expr_requires_non_zero_constant : Error< def err_overload_incorrect_fntype : Error< "argument is not a function, or has wrong number of parameters">; -// FIXME: PASSING TYPES AS STRING. -def err_overload_no_match : Error< - "no matching overload found for arguments of type '%0'">; -def err_overload_multiple_match : Error< - "more than one matching function found in __builtin_overload">; - // C++ member initializers. def err_only_constructors_take_base_inits : Error< "only constructors take base initializers">; @@ -2176,10 +2222,6 @@ def err_operator_overload_needs_class_or_enum : Error< def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">; def err_operator_overload_static : Error< "overloaded %0 cannot be a static member function">; -def err_operator_new_param_type : Error< - "%0 takes type size_t (%1) as first parameter">; -def err_operator_new_result_type : Error< - "%0 must return type %1">; def err_operator_overload_default_arg : Error< "parameter of overloaded %0 cannot have a default argument">; def err_operator_overload_must_be : Error< @@ -2192,6 +2234,31 @@ def err_operator_overload_post_incdec_must_be_int : Error< "parameter of overloaded post-%select{increment|decrement}1 operator must " "have type 'int' (not %0)">; +// C++ allocation and deallocation functions. +def err_operator_new_delete_declared_in_namespace : Error< + "%0 cannot be declared inside a namespace">; +def err_operator_new_delete_declared_static : Error< + "%0 cannot be declared static in global scope">; +def err_operator_new_delete_invalid_result_type : Error< + "%0 must return type %1">; +def err_operator_new_delete_dependent_result_type : Error< + "%0 cannot have a dependent return type; use %1 instead">; +def err_operator_new_delete_too_few_parameters : Error< + "%0 must have at least one parameter.">; +def err_operator_new_delete_template_too_few_parameters : Error< + "%0 template must have at least two parameters.">; + +def err_operator_new_dependent_param_type : Error< + "%0 cannot take a dependent type as first parameter; " + "use size_t (%1) instead">; +def err_operator_new_param_type : Error< + "%0 takes type size_t (%1) as first parameter">; +def err_operator_new_default_arg: Error< + "parameter of %0 cannot have a default argument">; +def err_operator_delete_dependent_param_type : Error< + "%0 cannot take a dependent type as first parameter; use %1 instead">; +def err_operator_delete_param_type : Error< + "%0 takes type %1 as first parameter">; // C++ conversion functions def err_conv_function_not_member : Error< @@ -2371,7 +2438,9 @@ def err_altivec_empty_initializer : Error<"expected initializer">; def err_stack_const_level : Error< "level argument for a stack address builtin must be constant">; -def err_prefetch_invalid_argument : Error< +def err_prefetch_invalid_arg_type : Error< + "argument to __builtin_prefetch must be of integer type">; +def err_prefetch_invalid_arg_ice : Error< "argument to __builtin_prefetch must be a constant integer">; def err_argument_invalid_range : Error< "argument should be a value from %0 to %1">; diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 5e7ac4f3c859..d0e0118d99d6 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_FILEMANAGER_H #define LLVM_CLANG_FILEMANAGER_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/OwningPtr.h" @@ -151,6 +152,9 @@ class FileManager { /// unsigned NextFileUID; + /// \brief The virtual files that we have allocated. + llvm::SmallVector<FileEntry *, 4> VirtualFileEntries; + // Statistics. unsigned NumDirLookups, NumFileLookups; unsigned NumDirCacheMisses, NumFileCacheMisses; @@ -199,6 +203,11 @@ public: const FileEntry *getFile(const char *FilenameStart, const char *FilenameEnd); + /// \brief Retrieve a file entry for a "virtual" file that acts as + /// if there were a file with the given name on disk. The file + /// itself is not accessed. + const FileEntry *getVirtualFile(const llvm::StringRef &Filename, + off_t Size, time_t ModificationTime); void PrintStats() const; }; diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 53939500e72a..75a7b8192c5a 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -532,9 +532,11 @@ struct DenseMapInfo<clang::Selector> { static bool isEqual(clang::Selector LHS, clang::Selector RHS) { return LHS == RHS; } - - static bool isPod() { return true; } }; + +template <> +struct isPodLike<clang::Selector> { static const bool value = true; }; + // Provide PointerLikeTypeTraits for IdentifierInfo pointers, which // are not guaranteed to be 8-byte aligned. diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index a16a27103b67..e17279e2664a 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -46,7 +46,7 @@ public: unsigned LaxVectorConversions : 1; unsigned AltiVec : 1; // Support AltiVec-style vector initializers. unsigned Exceptions : 1; // Support exception handling. - unsigned Rtti : 1; // Support rtti information. + unsigned RTTI : 1; // Support RTTI information. unsigned NeXTRuntime : 1; // Use NeXT runtime. unsigned Freestanding : 1; // Freestanding implementation @@ -92,6 +92,7 @@ public: unsigned ElideConstructors : 1; // Whether C++ copy constructors should be // elided if possible. + unsigned CatchUndefined :1; // Generate code to check for undefined ops. private: unsigned GC : 2; // Objective-C Garbage Collection modes. We // declare this enum as unsigned because MSVC @@ -125,7 +126,7 @@ public: CXXOperatorNames = PascalStrings = WritableStrings = 0; Exceptions = Freestanding = NoBuiltin = 0; NeXTRuntime = 1; - Rtti = 1; + RTTI = 1; LaxVectorConversions = 1; HeinousExtensions = 0; AltiVec = OpenCL = StackProtector = 0; @@ -160,6 +161,7 @@ public: CharIsSigned = 1; ShortWChar = 0; + CatchUndefined = 0; } GCMode getGCMode() const { return (GCMode) GC; } diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index 9960d5beb5c1..ae11a755cce4 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -51,11 +51,11 @@ class PartialDiagnostic { /// This is used when the argument is not an std::string. The specific value /// is mangled into an intptr_t and the intepretation depends on exactly /// what sort of argument kind it is. - mutable intptr_t DiagArgumentsVal[MaxArguments]; + intptr_t DiagArgumentsVal[MaxArguments]; /// DiagRanges - The list of ranges added to this diagnostic. It currently /// only support 10 ranges, could easily be extended if needed. - mutable const SourceRange *DiagRanges[10]; + SourceRange DiagRanges[10]; }; /// DiagID - The diagnostic ID. @@ -81,25 +81,40 @@ class PartialDiagnostic { assert(DiagStorage->NumDiagRanges < llvm::array_lengthof(DiagStorage->DiagRanges) && "Too many arguments to diagnostic!"); - DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = &R; + DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R; } - void operator=(const PartialDiagnostic &); // DO NOT IMPLEMENT - public: PartialDiagnostic(unsigned DiagID) : DiagID(DiagID), DiagStorage(0) { } PartialDiagnostic(const PartialDiagnostic &Other) - : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage) { - Other.DiagID = 0; - Other.DiagStorage = 0; + : DiagID(Other.DiagID), DiagStorage(0) + { + if (Other.DiagStorage) + DiagStorage = new Storage(*Other.DiagStorage); + } + + PartialDiagnostic &operator=(const PartialDiagnostic &Other) { + DiagID = Other.DiagID; + if (Other.DiagStorage) { + if (DiagStorage) + *DiagStorage = *Other.DiagStorage; + else + DiagStorage = new Storage(*Other.DiagStorage); + } else { + delete DiagStorage; + DiagStorage = 0; + } + + return *this; } ~PartialDiagnostic() { delete DiagStorage; } + unsigned getDiagID() const { return DiagID; } void Emit(const DiagnosticBuilder &DB) const { @@ -114,7 +129,7 @@ public: // Add all ranges. for (unsigned i = 0, e = DiagStorage->NumDiagRanges; i != e; ++i) - DB.AddSourceRange(*DiagStorage->DiagRanges[i]); + DB.AddSourceRange(DiagStorage->DiagRanges[i]); } friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index 28cf2db9bc25..36baf5feecce 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -21,6 +21,7 @@ namespace llvm { class MemoryBuffer; class raw_ostream; template <typename T> struct DenseMapInfo; + template <typename T> struct isPodLike; } namespace clang { @@ -296,9 +297,12 @@ namespace llvm { static bool isEqual(clang::FileID LHS, clang::FileID RHS) { return LHS == RHS; } - - static bool isPod() { return true; } }; + + template <> + struct isPodLike<clang::SourceLocation> { static const bool value = true; }; + template <> + struct isPodLike<clang::FileID> { static const bool value = true; }; } // end namespace llvm diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 7e9ac531017e..b4cf959dc551 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -54,9 +54,6 @@ namespace SrcMgr { /// file. This is owned by the ContentCache object. mutable const llvm::MemoryBuffer *Buffer; - /// The line and column at which we should truncate the file. - unsigned TruncateAtLine, TruncateAtColumn; - public: /// Reference to the file entry. This reference does not own /// the FileEntry object. It is possible for this to be NULL if @@ -72,13 +69,10 @@ namespace SrcMgr { /// if SourceLineCache is non-null. unsigned NumLines; - /// FirstFID - First FileID that was created for this ContentCache. - /// Represents the first source inclusion of the file associated with this - /// ContentCache. - mutable FileID FirstFID; - - /// getBuffer - Returns the memory buffer for the associated content. - const llvm::MemoryBuffer *getBuffer() const; + /// getBuffer - Returns the memory buffer for the associated content. If + /// there is an error opening this buffer the first time, this manufactures + /// a temporary buffer and returns a non-empty error string. + const llvm::MemoryBuffer *getBuffer(std::string *ErrorStr = 0) const; /// getSize - Returns the size of the content encapsulated by this /// ContentCache. This can be the size of the source file or the size of an @@ -96,28 +90,19 @@ namespace SrcMgr { Buffer = B; } - /// \brief Truncate this file at the given line and column. - /// - /// \param Line the line on which to truncate the current file (1-based). - /// \param Column the column at which to truncate the current file. - /// (1-based). - void truncateAt(unsigned Line, unsigned Column); - - /// \brief Determines whether the file was artificially truncated with - /// truncateAt(). - bool isTruncated() const { return TruncateAtLine && TruncateAtColumn; } - + /// \brief Replace the existing buffer (which will be deleted) + /// with the given buffer. + void replaceBuffer(const llvm::MemoryBuffer *B); + ContentCache(const FileEntry *Ent = 0) - : Buffer(0), TruncateAtLine(0), TruncateAtColumn(0), Entry(Ent), - SourceLineCache(0), NumLines(0) {} + : Buffer(0), Entry(Ent), SourceLineCache(0), NumLines(0) {} ~ContentCache(); /// The copy ctor does not allow copies where source object has either /// a non-NULL Buffer or SourceLineCache. Ownership of allocated memory /// is not transfered, so this is a logical error. - ContentCache(const ContentCache &RHS) - : Buffer(0), TruncateAtLine(0), TruncateAtColumn(0), SourceLineCache(0) { + ContentCache(const ContentCache &RHS) : Buffer(0), SourceLineCache(0) { Entry = RHS.Entry; assert (RHS.Buffer == 0 && RHS.SourceLineCache == 0 @@ -347,19 +332,13 @@ class SourceManager { mutable FileID LastRFIDForBeforeTUCheck; mutable bool LastResForBeforeTUCheck; - // Keep track of the file/line/column that we should truncate. - const FileEntry *TruncateFile; - unsigned TruncateAtLine; - unsigned TruncateAtColumn; - // SourceManager doesn't support copy construction. explicit SourceManager(const SourceManager&); void operator=(const SourceManager&); public: SourceManager() - : ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), - NumBinaryProbes(0), TruncateFile(0), TruncateAtLine(0), - TruncateAtColumn(0) { + : ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), + NumBinaryProbes(0) { clearIDTables(); } ~SourceManager(); @@ -428,14 +407,30 @@ public: unsigned PreallocatedID = 0, unsigned Offset = 0); + /// \brief Retrieve the memory buffer associated with the given file. + const llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File); + + /// \brief Override the contents of the given source file by providing an + /// already-allocated buffer. + /// + /// \param SourceFile the source file whose contents will be override. + /// + /// \param Buffer the memory buffer whose contents will be used as the + /// data in the given source file. + /// + /// \returns true if an error occurred, false otherwise. + bool overrideFileContents(const FileEntry *SourceFile, + const llvm::MemoryBuffer *Buffer); + //===--------------------------------------------------------------------===// // FileID manipulation methods. //===--------------------------------------------------------------------===// - /// getBuffer - Return the buffer for the specified FileID. - /// - const llvm::MemoryBuffer *getBuffer(FileID FID) const { - return getSLocEntry(FID).getFile().getContentCache()->getBuffer(); + /// getBuffer - Return the buffer for the specified FileID. If there is an + /// error opening this buffer the first time, this manufactures a temporary + /// buffer and returns a non-empty error string. + const llvm::MemoryBuffer *getBuffer(FileID FID, std::string *Error = 0) const{ + return getSLocEntry(FID).getFile().getContentCache()->getBuffer(Error); } /// getFileEntryForID - Returns the FileEntry record for the provided FileID. @@ -669,12 +664,6 @@ public: /// \returns true if LHS source location comes before RHS, false otherwise. bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const; - /// \brief Truncate the given file at the specified line/column. - void truncateFileAt(const FileEntry *Entry, unsigned Line, unsigned Column); - - /// \brief Determine whether this file was truncated. - bool isTruncatedFile(FileID FID) const; - // Iterators over FileInfos. typedef llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> ::const_iterator fileinfo_iterator; diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 99422332a788..bb022f11759d 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -324,6 +324,8 @@ KEYWORD(__is_enum , KEYCXX) KEYWORD(__is_pod , KEYCXX) KEYWORD(__is_polymorphic , KEYCXX) KEYWORD(__is_union , KEYCXX) +// Tentative name - there's no implementation of std::is_literal_type yet. +KEYWORD(__is_literal , KEYCXX) // FIXME: Add MS's traits, too. // Apple Extension. diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 2a2eacc4caac..36b830069f86 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -32,7 +32,8 @@ namespace clang { UTT_IsEnum, UTT_IsPOD, UTT_IsPolymorphic, - UTT_IsUnion + UTT_IsUnion, + UTT_IsLiteral }; } diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index b34fe0340a55..a9566f3f9d47 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -55,7 +55,7 @@ def analysis_CheckerCFRef : Flag<"-checker-cfref">, def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">, HelpText<"Warn about unintended use of sizeof() on pointer expressions">; def analysis_InlineCall : Flag<"-inline-call">, - HelpText<"Experimental transfer function inling callees when its definition is available.">; + HelpText<"Experimental transfer function inlining callees when its definition is available.">; def analyzer_store : Separate<"-analyzer-store">, HelpText<"Source Code Analysis - Abstract Memory Store Models">; @@ -73,6 +73,8 @@ def analyzer_output_EQ : Joined<"-analyzer-output=">, def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">, HelpText<"Force the static analyzer to analyze functions defined in header files">; +def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-blocks">, + HelpText<"Analyze the definitions of blocks in addition to functions">; def analyzer_display_progress : Flag<"-analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">; def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">, @@ -103,6 +105,8 @@ def disable_llvm_optzns : Flag<"-disable-llvm-optzns">, def disable_red_zone : Flag<"-disable-red-zone">, HelpText<"Do not emit code that uses the red zone.">; def g : Flag<"-g">, HelpText<"Generate source level debug information">; +def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, + HelpText<"Generate runtime checks for undefined behavior.">; def fno_common : Flag<"-fno-common">, HelpText<"Compile common globals like normal definitions">; def no_implicit_float : Flag<"-no-implicit-float">, @@ -117,13 +121,13 @@ def mdebug_pass : Separate<"-mdebug-pass">, HelpText<"Enable additional debug output">; def mdisable_fp_elim : Flag<"-mdisable-fp-elim">, HelpText<"Disable frame pointer elimination optimization">; -def mfloat_abi : Flag<"-mfloat-abi">, +def mfloat_abi : Separate<"-mfloat-abi">, HelpText<"The float ABI to use">; def mlimit_float_precision : Separate<"-mlimit-float-precision">, HelpText<"Limit float precision to the given value">; def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">, HelpText<"Do not put zero initialized data in the BSS">; -def msoft_float : Separate<"-msoft-float">, +def msoft_float : Flag<"-msoft-float">, HelpText<"Use software floating point">; def mrelocation_model : Separate<"-mrelocation-model">, HelpText<"The relocation model to use">; @@ -149,7 +153,7 @@ def MP : Flag<"-MP">, //===----------------------------------------------------------------------===// def dump_build_information : Separate<"-dump-build-information">, - MetaVarName<"filename">, + MetaVarName<"<filename>">, HelpText<"output a dump of some build information to a file">; def fno_show_column : Flag<"-fno-show-column">, HelpText<"Do not include column number on diagnostics">; @@ -172,7 +176,7 @@ def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-rang HelpText<"Print source range spans in numeric form">; def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">, HelpText<"Print diagnostic name with mappable diagnostics">; -def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"N">, +def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, HelpText<"Use colors in diagnostics">; @@ -185,28 +189,45 @@ def verify : Flag<"-verify">, // Frontend Options //===----------------------------------------------------------------------===// +// This isn't normally used, it is just here so we can parse a +// CompilerInvocation out of a driver-derived argument vector. +def cc1 : Flag<"-cc1">; + def code_completion_at : Separate<"-code-completion-at">, - MetaVarName<"file:line:column">, + MetaVarName<"<file>:<line>:<column>">, HelpText<"Dump code-completion information at a location">; +def remap_file : Separate<"-remap-file">, + MetaVarName<"<from>;<to>">, + HelpText<"Replace the contents of the <from> file with the contents of the <to> file">; def code_completion_at_EQ : Joined<"-code-completion-at=">, Alias<code_completion_at>; def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer">, - HelpText<"Don't the \"debug\" code-completion print">; + HelpText<"Don't use the \"debug\" code-completion print">; def code_completion_macros : Flag<"-code-completion-macros">, HelpText<"Include macros in code-completion results">; def disable_free : Flag<"-disable-free">, HelpText<"Disable freeing of memory on exit">; def empty_input_only : Flag<"-empty-input-only">, HelpText<"Force running on an empty input file">; +def help : Flag<"-help">, + HelpText<"Print this help text">; +def _help : Flag<"--help">, Alias<help>; def x : Separate<"-x">, HelpText<"Input language type">; def cxx_inheritance_view : Separate<"-cxx-inheritance-view">, - MetaVarName<"class name">, + MetaVarName<"<class name>">, HelpText<"View C++ inheritance for a specified class">; -def fixit_at : Separate<"-fixit-at">, MetaVarName<"source-location">, +def fixit_at : Separate<"-fixit-at">, MetaVarName<"<source location>">, HelpText<"Perform Fix-It modifications at the given source location">; -def o : Separate<"-o">, MetaVarName<"path">, HelpText<"Specify output file">; +def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">; +def load : Separate<"-load">, MetaVarName<"<dsopath>">, + HelpText<"Load the named plugin (dynamic shared object)">; def plugin : Separate<"-plugin">, HelpText<"Use the named plugin action (use \"help\" to list available options)">; +def resource_dir : Separate<"-resource-dir">, + HelpText<"The directory which holds the compiler resource files">; +def version : Flag<"-version">, + HelpText<"Print the compiler version">; +def _version : Flag<"--version">, Alias<version>; def Action_Group : OptionGroup<"<action group>">; let Group = Action_Group in { @@ -313,7 +334,7 @@ def fno_signed_char : Flag<"-fno-signed-char">, def fno_operator_names : Flag<"-fno-operator-names">, HelpText<"Do not treat C++ operator name keywords as synonyms for operators">; def fconstant_string_class : Separate<"-fconstant-string-class">, - MetaVarName<"class name">, + MetaVarName<"<class name>">, HelpText<"Specify the class to use for constant Objective-C string objects.">; def fobjc_gc : Flag<"-fobjc-gc">, HelpText<"Enable Objective-C garbage collection">; @@ -326,7 +347,7 @@ def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">, def ftrapv : Flag<"-ftrapv">, HelpText<"Trap on integer overflow">; def pic_level : Separate<"-pic-level">, - HelpText<"-Value for __PIC__">; + HelpText<"Value for __PIC__">; def pthread : Flag<"-pthread">, HelpText<"Support POSIX threads in generated code">; def fpascal_strings : Flag<"-fpascal-strings">, @@ -356,23 +377,24 @@ def nostdinc : Flag<"-nostdinc">, HelpText<"Disable standard #include directories">; def nobuiltininc : Flag<"-nobuiltininc">, HelpText<"Disable builtin #include directories">; -def F : JoinedOrSeparate<"-F">, MetaVarName<"directory">, +def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">, HelpText<"Add directory to framework include search path">; -def I : JoinedOrSeparate<"-I">, MetaVarName<"directory">, +def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">, HelpText<"Add directory to include search path">; -def idirafter : Separate<"-idirafter">, MetaVarName<"directory">, +def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">, HelpText<"Add directory to AFTER include search path">; -def iquote : Separate<"-iquote">, MetaVarName<"directory">, +def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">, HelpText<"Add directory to QUOTE include search path">; -def isystem : Separate<"-isystem">, MetaVarName<"directory">, +def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to SYSTEM include search path">; -def iprefix : Separate<"-iprefix">, MetaVarName<"prefix">, +def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">, HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">; -def iwithprefix : Separate<"-iwithprefix">, MetaVarName<"dir">, +def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">, HelpText<"Set directory to SYSTEM include search path with prefix">; -def iwithprefixbefore : Separate<"-iwithprefixbefore">, MetaVarName<"dir">, +def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, + MetaVarName<"<dir>">, HelpText<"Set directory to include search path with prefix">; -def isysroot : Separate<"-isysroot">, MetaVarName<"dir">, +def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">, HelpText<"Set the system root directory (usually /)">; def v : Flag<"-v">, HelpText<"Enable verbose output">; @@ -380,21 +402,21 @@ def v : Flag<"-v">, HelpText<"Enable verbose output">; // Preprocessor Options //===----------------------------------------------------------------------===// -def D : JoinedOrSeparate<"-D">, MetaVarName<"macro">, +def D : JoinedOrSeparate<"-D">, MetaVarName<"<macro>">, HelpText<"Predefine the specified macro">; -def include_ : Separate<"-include">, MetaVarName<"file">, EnumName<"include">, +def include_ : JoinedOrSeparate<"-include">, MetaVarName<"<file>">, EnumName<"include">, HelpText<"Include file before parsing">; -def imacros : Separate<"-imacros">, MetaVarName<"file">, +def imacros : JoinedOrSeparate<"-imacros">, MetaVarName<"<file>">, HelpText<"Include macros from file before parsing">; -def include_pch : Separate<"-include-pch">, MetaVarName<"file">, +def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">, HelpText<"Include precompiled header file">; -def include_pth : Separate<"-include-pth">, MetaVarName<"file">, +def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">, HelpText<"Include file before parsing">; -def token_cache : Separate<"-token-cache">, MetaVarName<"path">, +def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">, HelpText<"Use specified token cache file">; -def U : JoinedOrSeparate<"-U">, MetaVarName<"macro">, +def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">, HelpText<"Undefine the specified macro">; -def undef : Flag<"-undef">, MetaVarName<"macro">, +def undef : Flag<"-undef">, MetaVarName<"<macro>">, HelpText<"undef all system defines">; //===----------------------------------------------------------------------===// diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index d3ab1153371a..8933619b2c25 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -15,6 +15,7 @@ #include "clang/Driver/Phases.h" #include "clang/Driver/Util.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/System/Path.h" // FIXME: Kill when CompilationInfo // lands. @@ -112,9 +113,9 @@ private: std::list<std::string> ResultFiles; public: - Driver(const char *_Name, const char *_Dir, - const char *_DefaultHostTriple, - const char *_DefaultImageName, + Driver(llvm::StringRef _Name, llvm::StringRef _Dir, + llvm::StringRef _DefaultHostTriple, + llvm::StringRef _DefaultImageName, bool IsProduction, Diagnostic &_Diags); ~Driver(); diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index 906d73128b7d..74ca083417a6 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -22,7 +22,8 @@ using llvm::dyn_cast_or_null; namespace clang { namespace driver { - class Command; +class Command; +class Tool; class Job { public: @@ -55,6 +56,9 @@ class Command : public Job { /// Source - The action which caused the creation of this job. const Action &Source; + /// Tool - The tool which caused the creation of this job. + const Tool &Creator; + /// The executable to run. const char *Executable; @@ -63,12 +67,15 @@ class Command : public Job { ArgStringList Arguments; public: - Command(const Action &_Source, const char *_Executable, + Command(const Action &_Source, const Tool &_Creator, const char *_Executable, const ArgStringList &_Arguments); /// getSource - Return the Action which caused the creation of this job. const Action &getSource() const { return Source; } + /// getCreator - Return the Tool which caused the creation of this job. + const Tool &getCreator() const { return Creator; } + const char *getExecutable() const { return Executable; } const ArgStringList &getArguments() const { return Arguments; } diff --git a/include/clang/Driver/OptParser.td b/include/clang/Driver/OptParser.td index f5b6980d8f6a..a9f4289fc86e 100644 --- a/include/clang/Driver/OptParser.td +++ b/include/clang/Driver/OptParser.td @@ -77,11 +77,17 @@ def RenderSeparate : OptionFlag; // lines that use it. def Unsupported : OptionFlag; +// HelpHidden - The option should not be displayed in --help, even if it has +// help text. Clients *can* use this in conjuction with the OptTable::PrintHelp +// arguments to implement hidden help groups. +def HelpHidden : OptionFlag; + // Define the option group class. class OptionGroup<string name> { string EnumName = ?; // Uses the def name if undefined. string Name = name; + string HelpText = ?; OptionGroup Group = ?; } diff --git a/include/clang/Driver/OptTable.h b/include/clang/Driver/OptTable.h index faaeba69e2e6..edae75c9f057 100644 --- a/include/clang/Driver/OptTable.h +++ b/include/clang/Driver/OptTable.h @@ -13,17 +13,22 @@ #include "clang/Driver/OptSpecifier.h" #include <cassert> +namespace llvm { + class raw_ostream; +} + namespace clang { namespace driver { namespace options { enum DriverFlag { DriverOption = (1 << 0), - LinkerInput = (1 << 1), - NoArgumentUnused = (1 << 2), - RenderAsInput = (1 << 3), - RenderJoined = (1 << 4), - RenderSeparate = (1 << 5), - Unsupported = (1 << 6) + HelpHidden = (1 << 1), + LinkerInput = (1 << 2), + NoArgumentUnused = (1 << 3), + RenderAsInput = (1 << 4), + RenderJoined = (1 << 5), + RenderSeparate = (1 << 6), + Unsupported = (1 << 7) }; } @@ -113,6 +118,17 @@ namespace options { return getInfo(id).Kind; } + /// getOptionGroupID - Get the group id for the given option. + unsigned getOptionGroupID(OptSpecifier id) const { + return getInfo(id).GroupID; + } + + /// isOptionHelpHidden - Should the help for the given option be hidden by + /// default. + bool isOptionHelpHidden(OptSpecifier id) const { + return getInfo(id).Flags & options::HelpHidden; + } + /// getOptionHelpText - Get the help text to use to describe this option. const char *getOptionHelpText(OptSpecifier id) const { return getInfo(id).HelpText; @@ -156,6 +172,15 @@ namespace options { const char **ArgEnd, unsigned &MissingArgIndex, unsigned &MissingArgCount) const; + + /// PrintHelp - Render the help text for an option table. + /// + /// \param OS - The stream to write the help text to. + /// \param Name - The name to use in the usage line. + /// \param Title - The title to use in the usage line. + /// \param ShowHidden - Whether help-hidden arguments should be shown. + void PrintHelp(llvm::raw_ostream &OS, const char *Name, + const char *Title, bool ShowHidden = false) const; }; } } diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index ace1a3c16add..3592fc946846 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -61,6 +61,55 @@ def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">, // = => _EQ // C++ => CXX +// Developer Driver Options + +def ccc_Group : OptionGroup<"<clang internal options>">; +def ccc_driver_Group : OptionGroup<"<clang driver internal options>">, + Group<ccc_Group>, HelpText<"DRIVER OPTIONS">; +def ccc_debug_Group : OptionGroup<"<clang debug/development internal options>">, + Group<ccc_Group>, HelpText<"DEBUG/DEVELOPMENT OPTIONS">; + +class CCCDriverOpt : Group<ccc_driver_Group>, Flags<[DriverOption, HelpHidden]>; +def ccc_cxx : Flag<"-ccc-cxx">, CCCDriverOpt, + HelpText<"Act as a C++ driver">; +def ccc_echo : Flag<"-ccc-echo">, CCCDriverOpt, + HelpText<"Echo commands before running them">; +def ccc_gcc_name : Separate<"-ccc-gcc-name">, CCCDriverOpt, + HelpText<"Name for native GCC compiler">, + MetaVarName<"<gcc-path>">; +def ccc_clang_cxx : Flag<"-ccc-clang-cxx">, CCCDriverOpt, + HelpText<"Enable the clang compiler for C++">; +def ccc_no_clang_cxx : Flag<"-ccc-no-clang-cxx">, CCCDriverOpt, + HelpText<"Disable the clang compiler for C++">; +def ccc_no_clang : Flag<"-ccc-no-clang">, CCCDriverOpt, + HelpText<"Disable the clang compiler">; +def ccc_no_clang_cpp : Flag<"-ccc-no-clang-cpp">, CCCDriverOpt, + HelpText<"Disable the clang preprocessor">; +def ccc_clang_archs : Separate<"-ccc-clang-archs">, CCCDriverOpt, + HelpText<"Comma separate list of architectures to use the clang compiler for">, + MetaVarName<"<arch-list>">; +def ccc_pch_is_pch : Flag<"-ccc-pch-is-pch">, CCCDriverOpt, + HelpText<"Use lazy PCH for precompiled headers">; +def ccc_pch_is_pth : Flag<"-ccc-pch-is-pth">, CCCDriverOpt, + HelpText<"Use pretokenized headers for precompiled headers">; + +class CCCDebugOpt : Group<ccc_debug_Group>, Flags<[DriverOption, HelpHidden]>; +def ccc_host_triple : Separate<"-ccc-host-triple">, CCCDebugOpt, + HelpText<"Simulate running on the given target">; +def ccc_install_dir : Separate<"-ccc-install-dir">, CCCDebugOpt, + HelpText<"Simulate installation in the given directory">; +def ccc_print_options : Flag<"-ccc-print-options">, CCCDebugOpt, + HelpText<"Dump parsed command line arguments">; +def ccc_print_phases : Flag<"-ccc-print-phases">, CCCDebugOpt, + HelpText<"Dump list of actions to perform">; +def ccc_print_bindings : Flag<"-ccc-print-bindings">, CCCDebugOpt, + HelpText<"Show bindings of tools to actions">; + +// Make sure all other -ccc- options are rejected. +def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>; + +// Standard Options + def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>, HelpText<"Print the commands to run for this compilation">; def A : JoinedOrSeparate<"-A">; @@ -187,6 +236,8 @@ def fbootclasspath_EQ : Joined<"-fbootclasspath=">, Group<f_Group>; def fbuiltin_strcat : Flag<"-fbuiltin-strcat">, Group<f_Group>; def fbuiltin_strcpy : Flag<"-fbuiltin-strcpy">, Group<f_Group>; def fbuiltin : Flag<"-fbuiltin">, Group<f_Group>; +def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">, + Group<f_Group>, HelpText<"Generate runtime checks for undefined behavior.">; def fclasspath_EQ : Joined<"-fclasspath=">, Group<f_Group>; def fcolor_diagnostics : Flag<"-fcolor-diagnostics">, Group<f_Group>; def fcommon : Flag<"-fcommon">, Group<f_Group>; @@ -277,6 +328,9 @@ def fprofile_arcs : Flag<"-fprofile-arcs">, Group<f_Group>; def fprofile_generate : Flag<"-fprofile-generate">, Group<f_Group>; def framework : Separate<"-framework">, Flags<[LinkerInput]>; def frtti : Flag<"-frtti">, Group<f_Group>; +def fsched_interblock : Flag<"-fsched-interblock">, Group<clang_ignored_f_Group>; +def fshort_enums : Flag<"-fshort-enums">, Group<clang_ignored_f_Group>; +def freorder_blocks : Flag<"-freorder-blocks">, Group<clang_ignored_f_Group>; def fshort_wchar : Flag<"-fshort-wchar">, Group<f_Group>; def fshow_source_location : Flag<"-fshow-source-location">, Group<f_Group>; def fsigned_bitfields : Flag<"-fsigned-bitfields">, Group<f_Group>; @@ -315,7 +369,7 @@ def init : Separate<"-init">; def install__name : Separate<"-install_name">; def iprefix : JoinedOrSeparate<"-iprefix">, Group<clang_i_Group>; def iquote : JoinedOrSeparate<"-iquote">, Group<clang_i_Group>; -def isysroot : JoinedOrSeparate<"-isysroot">, Group<i_Group>; +def isysroot : JoinedOrSeparate<"-isysroot">, Group<clang_i_Group>; def isystem : JoinedOrSeparate<"-isystem">, Group<clang_i_Group>; def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">, Group<clang_i_Group>; def iwithprefix : JoinedOrSeparate<"-iwithprefix">, Group<clang_i_Group>; @@ -373,6 +427,8 @@ def multiply__defined : Separate<"-multiply_defined">; def mwarn_nonportable_cfstrings : Flag<"-mwarn-nonportable-cfstrings">, Group<m_Group>; def m_Separate : Separate<"-m">, Group<m_Group>; def m_Joined : Joined<"-m">, Group<m_Group>; +def no_canonical_prefixes : Flag<"-no-canonical-prefixes">, Flags<[DriverOption, HelpHidden]>, + HelpText<"Use relative instead of canonical paths">; def no_cpp_precomp : Flag<"-no-cpp-precomp">; def no_integrated_cpp : Flag<"-no-integrated-cpp">, Flags<[DriverOption]>; def no__dead__strip__inits__and__terms : Flag<"-no_dead_strip_inits_and_terms">; diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 26efa9745600..20bf83ee0456 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -94,9 +94,9 @@ ASTConsumer *CreateHTMLPrinter(llvm::raw_ostream *OS, Preprocessor &PP, bool SyntaxHighlight = true, bool HighlightMacros = true); -// PCH generator: generates a precompiled header file; this file can be -// used later with the PCHReader (clang-cc option -include-pch) -// to speed up compile times. +// PCH generator: generates a precompiled header file; this file can be used +// later with the PCHReader (clang -cc1 option -include-pch) to speed up compile +// times. ASTConsumer *CreatePCHGenerator(const Preprocessor &PP, llvm::raw_ostream *OS, const char *isysroot = 0); diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 04dc5ed8cc56..f18972ab3445 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -16,10 +16,11 @@ #include "clang/Basic/SourceManager.h" #include "llvm/ADT/OwningPtr.h" -#include "clang/Frontend/TextDiagnosticBuffer.h" #include "clang/Basic/FileManager.h" #include "clang/Index/ASTLocation.h" #include <string> +#include <vector> +#include <cassert> namespace clang { class ASTContext; @@ -32,14 +33,12 @@ class HeaderSearch; class Preprocessor; class SourceManager; class TargetInfo; -class TextDiagnosticBuffer; using namespace idx; /// \brief Utility class for loading a ASTContext from a PCH file. /// class ASTUnit { - Diagnostic Diags; FileManager FileMgr; SourceManager SourceMgr; @@ -48,22 +47,39 @@ class ASTUnit { llvm::OwningPtr<Preprocessor> PP; llvm::OwningPtr<ASTContext> Ctx; bool tempFile; - + // OnlyLocalDecls - when true, walking this AST should only visit declarations // that come from the AST itself, not from included precompiled headers. // FIXME: This is temporary; eventually, CIndex will always do this. bool OnlyLocalDecls; - + + /// Track whether the main file was loaded from an AST or not. + bool MainFileIsAST; + + /// Track the top-level decls which appeared in an ASTUnit which was loaded + /// from a source file. + // + // FIXME: This is just an optimization hack to avoid deserializing large parts + // of a PCH file when using the Index library on an ASTUnit loaded from + // source. In the long term we should make the Index library use efficient and + // more scalable search mechanisms. + std::vector<Decl*> TopLevelDecls; + + /// The name of the original source file used to generate this ASTUnit. + std::string OriginalSourceFile; + // Critical optimization when using clang_getCursor(). ASTLocation LastLoc; - + ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT public: - ASTUnit(DiagnosticClient *diagClient = NULL); + ASTUnit(bool MainFileIsAST); ~ASTUnit(); + bool isMainFileAST() const { return MainFileIsAST; } + const SourceManager &getSourceManager() const { return SourceMgr; } SourceManager &getSourceManager() { return SourceMgr; } @@ -73,37 +89,38 @@ public: const ASTContext &getASTContext() const { return *Ctx.get(); } ASTContext &getASTContext() { return *Ctx.get(); } - const Diagnostic &getDiagnostic() const { return Diags; } - Diagnostic &getDiagnostic() { return Diags; } - const FileManager &getFileManager() const { return FileMgr; } FileManager &getFileManager() { return FileMgr; } - + const std::string &getOriginalSourceFileName(); const std::string &getPCHFileName(); void unlinkTemporaryFile() { tempFile = true; } - + bool getOnlyLocalDecls() const { return OnlyLocalDecls; } - + void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; } ASTLocation getLastASTLocation() const { return LastLoc; } - + + std::vector<Decl*> &getTopLevelDecls() { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + return TopLevelDecls; + } + const std::vector<Decl*> &getTopLevelDecls() const { + assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); + return TopLevelDecls; + } + /// \brief Create a ASTUnit from a PCH file. /// /// \param Filename - The PCH file to load. /// - /// \param DiagClient - The diagnostics client to use. Specify NULL - /// to use a default client that emits warnings/errors to standard error. - /// The ASTUnit objects takes ownership of this object. - /// - /// \param ErrMsg - Error message to report if the PCH file could not be - /// loaded. + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. /// /// \returns - The initialized ASTUnit or null if the PCH failed to load. static ASTUnit *LoadFromPCHFile(const std::string &Filename, - std::string *ErrMsg = 0, - DiagnosticClient *DiagClient = NULL, + Diagnostic &Diags, bool OnlyLocalDecls = false, bool UseBumpAllocator = false); @@ -113,15 +130,35 @@ public: /// \param CI - The compiler invocation to use; it must have exactly one input /// source file. /// - /// \param Diags - The diagnostics engine to use for reporting errors. + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. // // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCompilerInvocation(const CompilerInvocation &CI, Diagnostic &Diags, - bool OnlyLocalDecls = false, - bool UseBumpAllocator = false); + bool OnlyLocalDecls = false); + /// LoadFromCommandLine - Create an ASTUnit from a vector of command line + /// arguments, which must specify exactly one source file. + /// + /// \param ArgBegin - The beginning of the argument vector. + /// + /// \param ArgEnd - The end of the argument vector. + /// + /// \param Diags - The diagnostics engine to use for reporting errors; its + /// lifetime is expected to extend past that of the returned ASTUnit. + /// + /// \param ResourceFilesPath - The path to the compiler resource files. + // + // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we + // shouldn't need to specify them at construction time. + static ASTUnit *LoadFromCommandLine(const char **ArgBegin, + const char **ArgEnd, + Diagnostic &Diags, + llvm::StringRef ResourceFilesPath, + bool OnlyLocalDecls = false, + bool UseBumpAllocator = false); }; } // namespace clang diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h index 24fed6e76ac1..f55e5dc04055 100644 --- a/include/clang/Frontend/AnalysisConsumer.h +++ b/include/clang/Frontend/AnalysisConsumer.h @@ -62,6 +62,7 @@ public: std::string AnalyzeSpecificFunction; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; + unsigned AnalyzeNestedBlocks : 1; unsigned EagerlyAssume : 1; unsigned PurgeDead : 1; unsigned TrimGraph : 1; @@ -76,6 +77,7 @@ public: AnalysisDiagOpt = PD_HTML; AnalyzeAll = 0; AnalyzerDisplayProgress = 0; + AnalyzeNestedBlocks = 0; EagerlyAssume = 0; PurgeDead = 1; TrimGraph = 0; diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index d7e7d991f379..18ec429db7e8 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -222,7 +222,7 @@ public: void setDiagnostics(Diagnostic *Value); DiagnosticClient &getDiagnosticClient() const { - assert(Target && "Compiler instance has no diagnostic client!"); + assert(DiagClient && "Compiler instance has no diagnostic client!"); return *DiagClient; } @@ -419,9 +419,13 @@ public: /// logging information. /// /// Note that this creates an unowned DiagnosticClient, if using directly the - /// caller is responsible for releaseing the returned Diagnostic's client + /// caller is responsible for releasing the returned Diagnostic's client /// eventually. /// + /// \param Opts - The diagnostic options; note that the created text + /// diagnostic object contains a reference to these options and its lifetime + /// must extend past that of the diagnostic engine. + /// /// \return The new object on success, or null on failure. static Diagnostic *createDiagnostics(const DiagnosticOptions &Opts, int Argc, char **Argv); @@ -482,12 +486,16 @@ public: /// Create the default output file (from the invocation's options) and add it /// to the list of tracked output files. + /// + /// \return - Null on error. llvm::raw_fd_ostream * createDefaultOutputFile(bool Binary = true, llvm::StringRef BaseInput = "", llvm::StringRef Extension = ""); /// Create a new output file and add it to the list of tracked output files, /// optionally deriving the output path name. + /// + /// \return - Null on error. llvm::raw_fd_ostream * createOutputFile(llvm::StringRef OutputPath, bool Binary = true, llvm::StringRef BaseInput = "", diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index e7c51aabba59..f5a9053ceb64 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -82,15 +82,19 @@ public: /// \param Res [out] - The resulting invocation. /// \param ArgBegin - The first element in the argument vector. /// \param ArgEnd - The last element in the argument vector. + /// \param Diags - The diagnostic engine to use for errors. + static void CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin, + const char **ArgEnd, Diagnostic &Diags); + + /// GetBuiltinIncludePath - Get the directory where the compiler headers + /// reside, relative to the compiler binary (found by the passed in + /// arguments). + /// /// \param Argv0 - The program path (from argv[0]), for finding the builtin /// compiler path. /// \param MainAddr - The address of main (or some other function in the main /// executable), for finding the builtin compiler path. - /// \param Diags - The diagnostic engine to use for errors. - static void CreateFromArgs(CompilerInvocation &Res, const char **ArgBegin, - const char **ArgEnd, const char *Argv0, - void *MainAddr, - Diagnostic &Diags); + static std::string GetResourcesPath(const char *Argv0, void *MainAddr); /// toArgs - Convert the CompilerInvocation to a list of strings suitable for /// passing to CreateFromArgs. diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index c1ec8e70f1c6..36fea7f71337 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -77,12 +77,14 @@ public: unsigned RelocatablePCH : 1; ///< When generating PCH files, /// instruct the PCH writer to create /// relocatable PCH files. + unsigned ShowHelp : 1; ///< Show the -help text. unsigned ShowMacrosInCodeCompletion : 1; ///< Show macros in code completion /// results. unsigned ShowStats : 1; ///< Show frontend performance /// metrics and statistics. unsigned ShowTimers : 1; ///< Show timers for individual /// actions. + unsigned ShowVersion : 1; ///< Show the -version text. /// The input files and their types. std::vector<std::pair<InputKind, std::string> > Inputs; @@ -105,6 +107,9 @@ public: /// The name of the action to run when using a plugin action. std::string ActionName; + /// The list of plugins to load. + std::vector<std::string> Plugins; + public: FrontendOptions() { DebugCodeCompletionPrinter = 1; @@ -113,9 +118,11 @@ public: ProgramAction = frontend::ParseSyntaxOnly; ActionName = ""; RelocatablePCH = 0; + ShowHelp = 0; ShowMacrosInCodeCompletion = 0; ShowStats = 0; ShowTimers = 0; + ShowVersion = 0; } /// getInputKindForExtension - Return the appropriate input kind for a file diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index 67129775ac8d..690408547c0d 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -61,9 +61,12 @@ public: std::string CXXEnvIncPath; std::string ObjCXXEnvIncPath; - /// If non-empty, the path to the compiler builtin include directory, which - /// will be searched following the user and environment includes. - std::string BuiltinIncludePath; + /// The directory which holds the compiler resource files (builtin includes, + /// etc.). + std::string ResourceDir; + + /// Include the compiler builtin includes. + unsigned UseBuiltinIncludes : 1; /// Include the system standard include search directories. unsigned UseStandardIncludes : 1; @@ -73,7 +76,8 @@ public: public: HeaderSearchOptions(llvm::StringRef _Sysroot = "/") - : Sysroot(_Sysroot), UseStandardIncludes(true), Verbose(false) {} + : Sysroot(_Sysroot), UseBuiltinIncludes(true), + UseStandardIncludes(true), Verbose(false) {} /// AddPath - Add the \arg Path path to the specified \arg Group list. void AddPath(llvm::StringRef Path, frontend::IncludeDirGroup Group, diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 98463c308e51..c8c49c83f940 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -404,7 +404,9 @@ namespace clang { /// \brief An ElaboratedType record. TYPE_ELABORATED = 24, /// \brief A SubstTemplateTypeParmType record. - TYPE_SUBST_TEMPLATE_TYPE_PARM = 25 + TYPE_SUBST_TEMPLATE_TYPE_PARM = 25, + /// \brief An UnresolvedUsingType record. + TYPE_UNRESOLVED_USING = 26 }; /// \brief The type IDs for special types constructed by semantic diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 85861fab4a22..7e2c65690fd6 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -530,7 +530,8 @@ public: /// \brief Retrieve the name of the original source file name /// directly from the PCH file, without actually loading the PCH /// file. - static std::string getOriginalSourceFile(const std::string &PCHFileName); + static std::string getOriginalSourceFile(const std::string &PCHFileName, + Diagnostic &Diags); /// \brief Returns the suggested contents of the predefines buffer, /// which contains a (typically-empty) subset of the predefines @@ -552,7 +553,7 @@ public: const RecordData &Record, unsigned &Idx); /// \brief Reads a declarator info from the given record. - virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record, + virtual TypeSourceInfo *GetTypeSourceInfo(const RecordData &Record, unsigned &Idx); /// \brief Resolve a type ID into a type, potentially building a new @@ -625,6 +626,9 @@ public: /// tree. virtual void InitializeSema(Sema &S); + /// \brief Inform the semantic consumer that Sema is no longer available. + virtual void ForgetSema() { SemaObj = 0; } + /// \brief Retrieve the IdentifierInfo for the named identifier. /// /// This routine builds a new IdentifierInfo for the given identifier. If any diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index b520f4be1d31..212130e2ea62 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -44,7 +44,6 @@ class TargetInfo; /// DenseMap. This uses the standard pointer hash function. struct UnsafeQualTypeDenseMapInfo { static inline bool isEqual(QualType A, QualType B) { return A == B; } - static inline bool isPod() { return true; } static inline QualType getEmptyKey() { return QualType::getFromOpaquePtr((void*) 1); } @@ -274,7 +273,7 @@ public: void AddTypeRef(QualType T, RecordData &Record); /// \brief Emits a reference to a declarator info. - void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record); + void AddTypeSourceInfo(TypeSourceInfo *TInfo, RecordData &Record); /// \brief Emits a template argument location. void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg, diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h index f0c1d3c2c38d..c43a1feb8c05 100644 --- a/include/clang/Frontend/PreprocessorOptions.h +++ b/include/clang/Frontend/PreprocessorOptions.h @@ -13,6 +13,7 @@ #include "llvm/ADT/StringRef.h" #include <cassert> #include <string> +#include <utility> #include <vector> namespace clang { @@ -41,6 +42,21 @@ public: /// If given, a PTH cache file to use for speeding up header parsing. std::string TokenCache; + /// \brief The set of file remappings, which take existing files on + /// the system (the first part of each pair) and gives them the + /// contents of other files on the system (the second part of each + /// pair). + std::vector<std::pair<std::string, std::string> > RemappedFiles; + + typedef std::vector<std::pair<std::string, std::string> >::const_iterator + remapped_file_iterator; + remapped_file_iterator remapped_file_begin() const { + return RemappedFiles.begin(); + } + remapped_file_iterator remapped_file_end() const { + return RemappedFiles.end(); + } + public: PreprocessorOptions() : UsePredefines(true) {} @@ -50,6 +66,9 @@ public: void addMacroUndef(llvm::StringRef Name) { Macros.push_back(std::make_pair(Name, true)); } + void addRemappedFile(llvm::StringRef From, llvm::StringRef To) { + RemappedFiles.push_back(std::make_pair(From, To)); + } }; } // end namespace clang diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Index/CallGraph.h index 5edfe6fea8db..5edfe6fea8db 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Index/CallGraph.h diff --git a/include/clang/Index/Entity.h b/include/clang/Index/Entity.h index 4533a1a0ac08..c2aab62e23f2 100644 --- a/include/clang/Index/Entity.h +++ b/include/clang/Index/Entity.h @@ -134,9 +134,10 @@ struct DenseMapInfo<clang::idx::Entity> { isEqual(clang::idx::Entity LHS, clang::idx::Entity RHS) { return LHS == RHS; } - - static inline bool isPod() { return true; } }; + +template <> +struct isPodLike<clang::idx::Entity> { static const bool value = true; }; } // end namespace llvm diff --git a/include/clang/Index/GlobalSelector.h b/include/clang/Index/GlobalSelector.h index 51f98267f356..9cd83a8595b9 100644 --- a/include/clang/Index/GlobalSelector.h +++ b/include/clang/Index/GlobalSelector.h @@ -90,9 +90,10 @@ struct DenseMapInfo<clang::idx::GlobalSelector> { isEqual(clang::idx::GlobalSelector LHS, clang::idx::GlobalSelector RHS) { return LHS == RHS; } - - static inline bool isPod() { return true; } }; + +template <> +struct isPodLike<clang::idx::GlobalSelector> { static const bool value = true;}; } // end namespace llvm diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index 52bf194883df..fc65b1fc5449 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -38,8 +38,8 @@ class Lexer : public PreprocessorLexer { const char *BufferEnd; // End of the buffer. SourceLocation FileLoc; // Location for start of file. LangOptions Features; // Features enabled by this language (cache). - bool Is_PragmaLexer; // True if lexer for _Pragma handling. - bool IsEofCodeCompletion; // True if EOF is treated as a code-completion. + bool Is_PragmaLexer : 1; // True if lexer for _Pragma handling. + bool IsInConflictMarker : 1; // True if in a VCS conflict marker '<<<<<<<' //===--------------------------------------------------------------------===// // Context-specific lexing flags set by the preprocessor. @@ -180,15 +180,6 @@ public: ExtendedTokenMode = Mode ? 1 : 0; } - /// \brief Specify that end-of-file is to be considered a code-completion - /// token. - /// - /// When in this mode, the end-of-file token will be immediately preceded - /// by a code-completion token. - void SetEofIsCodeCompletion(bool Val = true) { - IsEofCodeCompletion = Val; - } - const char *getBufferStart() const { return BufferStart; } /// ReadToEndOfLine - Read the rest of the current preprocessor line as an @@ -379,6 +370,9 @@ private: bool SkipBCPLComment (Token &Result, const char *CurPtr); bool SkipBlockComment (Token &Result, const char *CurPtr); bool SaveBCPLComment (Token &Result, const char *CurPtr); + + bool IsStartOfConflictMarker(const char *CurPtr); + bool HandleEndOfConflictMarker(const char *CurPtr); }; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index edd34b718969..7c838ff86243 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -91,12 +91,14 @@ class Preprocessor { bool KeepMacroComments : 1; // State that changes while the preprocessor runs: - bool DisableMacroExpansion : 1; // True if macro expansion is disabled. bool InMacroArgs : 1; // True if parsing fn macro invocation args. /// Whether the preprocessor owns the header search object. bool OwnsHeaderSearch : 1; + /// DisableMacroExpansion - True if macro expansion is disabled. + bool DisableMacroExpansion : 1; + /// Identifiers - This is mapping/lookup information for all identifiers in /// the program, including program keywords. mutable IdentifierTable Identifiers; @@ -121,6 +123,9 @@ class Preprocessor { /// with this preprocessor. std::vector<CommentHandler *> CommentHandlers; + /// \brief The file that we're performing code-completion for, if any. + const FileEntry *CodeCompletionFile; + /// 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. @@ -134,7 +139,7 @@ class Preprocessor { /// CurPPLexer - This is the current top of the stack what we're lexing from /// if not expanding a macro. This is an alias for either CurLexer or /// CurPTHLexer. - PreprocessorLexer* CurPPLexer; + PreprocessorLexer *CurPPLexer; /// CurLookup - The DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. This allows us to @@ -171,8 +176,14 @@ class Preprocessor { llvm::DenseMap<IdentifierInfo*, MacroInfo*> Macros; /// MICache - A "freelist" of MacroInfo objects that can be reused for quick - /// allocation. + /// allocation. + /// FIXME: why not use a singly linked list? std::vector<MacroInfo*> MICache; + + /// MacroArgCache - This is a "freelist" of MacroArg objects that can be + /// reused for quick allocation. + MacroArgs *MacroArgCache; + friend class MacroArgs; // Various statistics we track for performance analysis. unsigned NumDirectives, NumIncluded, NumDefined, NumUndefined, NumPragma; @@ -330,8 +341,9 @@ public: /// EnterSourceFile - Add a source file to the top of the include stack and /// start lexing tokens from it instead of the current buffer. Return true - /// on failure. - bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir); + /// and fill in ErrorStr with the error information on failure. + bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, + std::string &ErrorStr); /// EnterMacro - Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. Args specifies the @@ -484,6 +496,27 @@ public: CachedTokens[CachedLexPos-1] = Tok; } + /// \brief Specify the point at which code-completion will be performed. + /// + /// \param File the file in which code completion should occur. If + /// this file is included multiple times, code-completion will + /// perform completion the first time it is included. If NULL, this + /// function clears out the code-completion point. + /// + /// \param Line the line at which code completion should occur + /// (1-based). + /// + /// \param Column the column at which code completion should occur + /// (1-based). + /// + /// \returns true if an error occurred, false otherwise. + bool SetCodeCompletionPoint(const FileEntry *File, + unsigned Line, unsigned Column); + + /// \brief Determine if this source location refers into the file + /// for which we are performing code completion. + bool isCodeCompletionFile(SourceLocation FileLoc) const; + /// Diag - Forwarding function for diagnostics. This emits a diagnostic at /// the specified Token's location, translating the token's start /// position in the current buffer into a SourcePosition object for rendering. diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index fc56cc68476e..b7540f9993d0 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -334,6 +334,20 @@ public: bool EnteringContext) { return 0; } + + /// IsInvalidUnlessNestedName - This method is used for error recovery + /// purposes to determine whether the specified identifier is only valid as + /// a nested name specifier, for example a namespace name. It is + /// conservatively correct to always return false from this method. + /// + /// The arguments are the same as those passed to ActOnCXXNestedNameSpecifier. + virtual bool IsInvalidUnlessNestedName(Scope *S, + const CXXScopeSpec &SS, + IdentifierInfo &II, + TypeTy *ObjectType, + bool EnteringContext) { + return false; + } /// ActOnCXXNestedNameSpecifier - Called during parsing of a /// nested-name-specifier that involves a template-id, e.g., @@ -351,8 +365,19 @@ public: return 0; } + /// ShouldEnterDeclaratorScope - Called when a C++ scope specifier + /// is parsed as part of a declarator-id to determine whether a scope + /// should be entered. + /// + /// \param S the current scope + /// \param SS the scope being entered + /// \param isFriendDeclaration whether this is a friend declaration + virtual bool ShouldEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + return false; + } + /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global - /// scope or nested-name-specifier) is parsed, part of a declarator-id. + /// scope or nested-name-specifier) is parsed as part of a declarator-id. /// After this method is called, according to [C++ 3.4.3p3], names should be /// looked up in the declarator-id's scope, until the declarator is parsed and /// ActOnCXXExitDeclaratorScope is called. @@ -1250,6 +1275,10 @@ public: /// /// \param AS the currently-active access specifier. /// + /// \param HasUsingKeyword true if this was declared with an + /// explicit 'using' keyword (i.e. if this is technically a using + /// declaration, not an access declaration) + /// /// \param UsingLoc the location of the 'using' keyword. /// /// \param SS the nested-name-specifier that precedes the name. @@ -1267,6 +1296,7 @@ public: /// \returns a representation of the using declaration. virtual DeclPtrTy ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, + bool HasUsingKeyword, SourceLocation UsingLoc, const CXXScopeSpec &SS, UnqualifiedId &Name, @@ -2394,6 +2424,24 @@ public: /// \param S the scope in which the operator keyword occurs. virtual void CodeCompleteOperatorName(Scope *S) { } + /// \brief Code completion after the '@' at the top level. + /// + /// \param S the scope in which the '@' occurs. + /// + /// \param ObjCImpDecl the Objective-C implementation or category + /// implementation. + /// + /// \param InInterface whether we are in an Objective-C interface or + /// protocol. + virtual void CodeCompleteObjCAtDirective(Scope *S, DeclPtrTy ObjCImpDecl, + bool InInterface) { } + + /// \brief Code completion after the '@' in a statement. + virtual void CodeCompleteObjCAtStatement(Scope *S) { } + + /// \brief Code completion after the '@' in an expression. + virtual void CodeCompleteObjCAtExpression(Scope *S) { } + /// \brief Code completion for an ObjC property decl. /// /// This code completion action is invoked when the code-completion token is diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h index fe899b3fdb17..b766890b7023 100644 --- a/include/clang/Parse/DeclSpec.h +++ b/include/clang/Parse/DeclSpec.h @@ -27,6 +27,40 @@ namespace clang { class Declarator; struct TemplateIdAnnotation; +/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope +/// specifier. +class CXXScopeSpec { + SourceRange Range; + void *ScopeRep; + +public: + CXXScopeSpec() : Range(), ScopeRep() { } + + const SourceRange &getRange() const { return Range; } + void setRange(const SourceRange &R) { Range = R; } + void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } + void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); } + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + + ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; } + void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; } + + bool isEmpty() const { return !Range.isValid(); } + bool isNotEmpty() const { return !isEmpty(); } + + /// isInvalid - An error occured during parsing of the scope specifier. + bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; } + + /// isSet - A scope specifier was resolved to a valid C++ scope. + bool isSet() const { return ScopeRep != 0; } + + void clear() { + Range = SourceRange(); + ScopeRep = 0; + } +}; + /// DeclSpec - This class captures information about "declaration specifiers", /// which encompasses storage-class-specifiers, type-specifiers, /// type-qualifiers, and function-specifiers. @@ -143,6 +177,9 @@ private: // attributes. AttributeList *AttrList; + // Scope specifier for the type spec, if applicable. + CXXScopeSpec TypeScope; + // List of protocol qualifiers for objective-c classes. Used for // protocol-qualified interfaces "NString<foo>" and protocol-qualified id // "id<foo>". @@ -211,6 +248,8 @@ public: TST getTypeSpecType() const { return (TST)TypeSpecType; } bool isTypeSpecOwned() const { return TypeSpecOwned; } void *getTypeRep() const { return TypeRep; } + CXXScopeSpec &getTypeSpecScope() { return TypeScope; } + const CXXScopeSpec &getTypeSpecScope() const { return TypeScope; } const SourceRange &getSourceRange() const { return Range; } SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; } @@ -436,40 +475,6 @@ private: IdentifierInfo *SetterName; // setter name of NULL if no setter }; -/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope -/// specifier. -class CXXScopeSpec { - SourceRange Range; - void *ScopeRep; - -public: - CXXScopeSpec() : Range(), ScopeRep() { } - - const SourceRange &getRange() const { return Range; } - void setRange(const SourceRange &R) { Range = R; } - void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } - void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); } - SourceLocation getBeginLoc() const { return Range.getBegin(); } - SourceLocation getEndLoc() const { return Range.getEnd(); } - - ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; } - void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; } - - bool isEmpty() const { return !Range.isValid(); } - bool isNotEmpty() const { return !isEmpty(); } - - /// isInvalid - An error occured during parsing of the scope specifier. - bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; } - - /// isSet - A scope specifier was resolved to a valid C++ scope. - bool isSet() const { return ScopeRep != 0; } - - void clear() { - Range = SourceRange(); - ScopeRep = 0; - } -}; - /// \brief Represents a C++ unqualified-id that has been parsed. class UnqualifiedId { private: diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 81a80ebcbc61..e47de506fd1f 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -30,6 +30,7 @@ namespace clang { class DiagnosticBuilder; class Parser; class PragmaUnusedHandler; + class ColonProtectionRAIIObject; /// PrettyStackTraceParserEntry - If a crash happens while the parser is active, /// an entry is printed for it. @@ -47,6 +48,7 @@ public: /// class Parser { friend class PragmaUnusedHandler; + friend class ColonProtectionRAIIObject; PrettyStackTraceParserEntry CrashInfo; Preprocessor &PP; @@ -90,26 +92,16 @@ class Parser { /// template argument list, where the '>' closes the template /// argument list. bool GreaterThanIsOperator; + + /// ColonIsSacred - When this is false, we aggressively try to recover from + /// code like "foo : bar" as if it were a typo for "foo :: bar". This is not + /// safe in case statements and a few other things. This is managed by the + /// ColonProtectionRAIIObject RAII object. + bool ColonIsSacred; /// The "depth" of the template parameters currently being parsed. unsigned TemplateParameterDepth; - /// \brief RAII object that makes '>' behave either as an operator - /// or as the closing angle bracket for a template argument list. - struct GreaterThanIsOperatorScope { - bool &GreaterThanIsOperator; - bool OldGreaterThanIsOperator; - - GreaterThanIsOperatorScope(bool >IO, bool Val) - : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) { - GreaterThanIsOperator = Val; - } - - ~GreaterThanIsOperatorScope() { - GreaterThanIsOperator = OldGreaterThanIsOperator; - } - }; - public: Parser(Preprocessor &PP, Action &Actions); ~Parser(); @@ -759,7 +751,10 @@ private: bool isStartOfFunctionDefinition(); DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(AttributeList *Attr, AccessSpecifier AS = AS_none); - + DeclGroupPtrTy ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, + AttributeList *Attr, + AccessSpecifier AS = AS_none); + DeclPtrTy ParseFunctionDefinition(ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); void ParseKNRParamDeclarations(Declarator &D); @@ -1087,6 +1082,7 @@ private: private: virtual void _anchor(); }; + struct ObjCPropertyCallback; void ParseStructDeclaration(DeclSpec &DS, FieldCallback &Callback); @@ -1288,7 +1284,7 @@ private: tok::TokenKind *After = 0); DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd); - DeclPtrTy ParseLinkage(unsigned Context); + DeclPtrTy ParseLinkage(ParsingDeclSpec &DS, unsigned Context); DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context, SourceLocation &DeclEnd, CXX0XAttributeList Attrs); diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index 05c56451b218..d27e29281b5a 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -34,6 +34,9 @@ public: /// tree. virtual void InitializeSema(Sema &S) {} + /// \brief Inform the semantic consumer that Sema is no longer available. + virtual void ForgetSema() {} + /// \brief Load the contents of the global method pool for a given /// selector. /// diff --git a/include/clang/Sema/SemaConsumer.h b/include/clang/Sema/SemaConsumer.h index b213daf8a39e..3689a6e7a820 100644 --- a/include/clang/Sema/SemaConsumer.h +++ b/include/clang/Sema/SemaConsumer.h @@ -34,6 +34,9 @@ namespace clang { /// tree. virtual void InitializeSema(Sema &S) {} + /// \brief Inform the semantic consumer that Sema is no longer available. + virtual void ForgetSema() {} + // isa/cast/dyn_cast support static bool classof(const ASTConsumer *Consumer) { return Consumer->SemaConsumer; |