diff options
Diffstat (limited to 'include/clang')
58 files changed, 1165 insertions, 461 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index e77dcf86cca67..c41857ec02001 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -17,6 +17,7 @@  #include "clang/Basic/IdentifierTable.h"  #include "clang/Basic/LangOptions.h"  #include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PartialDiagnostic.h"  #include "clang/AST/Attr.h"  #include "clang/AST/Decl.h"  #include "clang/AST/NestedNameSpecifier.h" @@ -57,6 +58,7 @@ namespace clang {    class ObjCIvarRefExpr;    class ObjCPropertyDecl;    class RecordDecl; +  class StoredDeclsMap;    class TagDecl;    class TemplateTypeParmDecl;    class TranslationUnitDecl; @@ -115,7 +117,7 @@ class ASTContext {    llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes;    llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;    llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes; -  llvm::FoldingSet<TypenameType> TypenameTypes; +  llvm::FoldingSet<DependentNameType> DependentNameTypes;    llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;    llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes;    llvm::FoldingSet<ElaboratedType> ElaboratedTypes; @@ -264,6 +266,9 @@ class ASTContext {    llvm::MallocAllocator MallocAlloc;    llvm::BumpPtrAllocator BumpAlloc; +  /// \brief Allocator for partial diagnostics. +  PartialDiagnostic::StorageAllocator DiagAllocator; +    public:    const TargetInfo &Target;    IdentifierTable &Idents; @@ -289,6 +294,11 @@ public:      if (FreeMemory)        MallocAlloc.Deallocate(Ptr);    } +   +  PartialDiagnostic::StorageAllocator &getDiagAllocator() { +    return DiagAllocator; +  } +    const LangOptions& getLangOptions() const { return LangOpts; }    FullSourceLoc getFullLoc(SourceLocation Loc) const { @@ -437,6 +447,11 @@ public:    /// allowable type.    QualType getCallConvType(QualType T, CallingConv CallConv); +  /// getRegParmType - Sets the specified regparm attribute to +  /// the given type, which must be a FunctionType or a pointer to an +  /// allowable type. +  QualType getRegParmType(QualType T, unsigned RegParm); +    /// getComplexType - Return the uniqued reference to the type for a complex    /// number with the specified element type.    QualType getComplexType(QualType T); @@ -554,8 +569,12 @@ public:    /// getFunctionNoProtoType - Return a K&R style C function type like 'int()'.    /// -  QualType getFunctionNoProtoType(QualType ResultTy, bool NoReturn = false, -                                  CallingConv CallConv = CC_Default); +  QualType getFunctionNoProtoType(QualType ResultTy, +                                  const FunctionType::ExtInfo &Info); + +  QualType getFunctionNoProtoType(QualType ResultTy) { +    return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo()); +  }    /// getFunctionType - Return a normal function type with a typed argument    /// list.  isVariadic indicates whether the argument list includes '...'. @@ -564,8 +583,7 @@ public:                             unsigned TypeQuals, bool hasExceptionSpec,                             bool hasAnyExceptionSpec,                             unsigned NumExs, const QualType *ExArray, -                           bool NoReturn, -                           CallingConv CallConv); +                           const FunctionType::ExtInfo &Info);    /// getTypeDeclType - Return the unique reference to the type for    /// the specified type declaration. @@ -612,12 +630,14 @@ public:    QualType getQualifiedNameType(NestedNameSpecifier *NNS,                                  QualType NamedType); -  QualType getTypenameType(NestedNameSpecifier *NNS, -                           const IdentifierInfo *Name, -                           QualType Canon = QualType()); -  QualType getTypenameType(NestedNameSpecifier *NNS, -                           const TemplateSpecializationType *TemplateId, -                           QualType Canon = QualType()); +  QualType getDependentNameType(ElaboratedTypeKeyword Keyword, +                                NestedNameSpecifier *NNS, +                                const IdentifierInfo *Name, +                                QualType Canon = QualType()); +  QualType getDependentNameType(ElaboratedTypeKeyword Keyword, +                                NestedNameSpecifier *NNS, +                                const TemplateSpecializationType *TemplateId, +                                QualType Canon = QualType());    QualType getElaboratedType(QualType UnderlyingType,                               ElaboratedType::TagKind Tag); @@ -937,8 +957,7 @@ public:                                 llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars);    void CollectNonClassIvars(const ObjCInterfaceDecl *OI,                                 llvm::SmallVectorImpl<ObjCIvarDecl*> &Ivars); -  unsigned CountSynthesizedIvars(const ObjCInterfaceDecl *OI); -  unsigned CountProtocolSynthesizedIvars(const ObjCProtocolDecl *PD); +  unsigned CountNonClassIvars(const ObjCInterfaceDecl *OI);    void CollectInheritedProtocols(const Decl *CDecl,                            llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); @@ -1273,9 +1292,8 @@ private:    // FIXME: This currently contains the set of StoredDeclMaps used    // by DeclContext objects.  This probably should not be in ASTContext,    // but we include it here so that ASTContext can quickly deallocate them. -  std::vector<void*> SDMs;  +  llvm::PointerIntPair<StoredDeclsMap*,1> LastSDM;    friend class DeclContext; -  void *CreateStoredDeclsMap();    void ReleaseDeclContextMaps();  }; diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index c89e5e4b167ae..edd633e8e1408 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -19,6 +19,7 @@  #include "clang/AST/DeclCXX.h"  #include "clang/AST/Type.h"  #include "clang/AST/TypeOrdering.h" +#include "llvm/ADT/DenseMap.h"  #include "llvm/ADT/SmallVector.h"  #include <list>  #include <map> @@ -227,6 +228,137 @@ public:    /// object.    void swap(CXXBasePaths &Other);  }; + +/// \brief Uniquely identifies a virtual method within a class +/// hierarchy by the method itself and a class subobject number. +struct UniqueVirtualMethod { +  UniqueVirtualMethod() : Method(0), Subobject(0), InVirtualSubobject(0) { } + +  UniqueVirtualMethod(CXXMethodDecl *Method, unsigned Subobject, +                      const CXXRecordDecl *InVirtualSubobject) +    : Method(Method), Subobject(Subobject),  +      InVirtualSubobject(InVirtualSubobject) { } + +  /// \brief The overriding virtual method. +  CXXMethodDecl *Method; + +  /// \brief The subobject in which the overriding virtual method +  /// resides. +  unsigned Subobject; + +  /// \brief The virtual base class subobject of which this overridden +  /// virtual method is a part. Note that this records the closest +  /// derived virtual base class subobject. +  const CXXRecordDecl *InVirtualSubobject; + +  friend bool operator==(const UniqueVirtualMethod &X, +                         const UniqueVirtualMethod &Y) { +    return X.Method == Y.Method && X.Subobject == Y.Subobject && +      X.InVirtualSubobject == Y.InVirtualSubobject; +  } + +  friend bool operator!=(const UniqueVirtualMethod &X, +                         const UniqueVirtualMethod &Y) { +    return !(X == Y); +  } +}; + +/// \brief The set of methods that override a given virtual method in +/// each subobject where it occurs. +/// +/// The first part of the pair is the subobject in which the +/// overridden virtual function occurs, while the second part of the +/// pair is the virtual method that overrides it (including the +/// subobject in which that virtual function occurs). +class OverridingMethods { +  llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> >  +    Overrides; + +public: +  // Iterate over the set of subobjects that have overriding methods. +  typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> > +            ::iterator iterator; +  typedef llvm::DenseMap<unsigned, llvm::SmallVector<UniqueVirtualMethod, 4> > +            ::const_iterator const_iterator; +  iterator begin() { return Overrides.begin(); } +  const_iterator begin() const { return Overrides.begin(); } +  iterator end() { return Overrides.end(); } +  const_iterator end() const { return Overrides.end(); } +  unsigned size() const { return Overrides.size(); } + +  // Iterate over the set of overriding virtual methods in a given +  // subobject. +  typedef llvm::SmallVector<UniqueVirtualMethod, 4>::iterator  +    overriding_iterator; +  typedef llvm::SmallVector<UniqueVirtualMethod, 4>::const_iterator +    overriding_const_iterator; + +  // Add a new overriding method for a particular subobject. +  void add(unsigned OverriddenSubobject, UniqueVirtualMethod Overriding); + +  // Add all of the overriding methods from "other" into overrides for +  // this method. Used when merging the overrides from multiple base +  // class subobjects. +  void add(const OverridingMethods &Other); + +  // Replace all overriding virtual methods in all subobjects with the +  // given virtual method. +  void replaceAll(UniqueVirtualMethod Overriding); +}; + +/// \brief A mapping from each virtual member function to its set of +/// final overriders. +/// +/// Within a class hierarchy for a given derived class, each virtual +/// member function in that hierarchy has one or more "final +/// overriders" (C++ [class.virtual]p2). A final overrider for a +/// virtual function "f" is the virtual function that will actually be +/// invoked when dispatching a call to "f" through the +/// vtable. Well-formed classes have a single final overrider for each +/// virtual function; in abstract classes, the final overrider for at +/// least one virtual function is a pure virtual function. Due to +/// multiple, virtual inheritance, it is possible for a class to have +/// more than one final overrider. Athough this is an error (per C++ +/// [class.virtual]p2), it is not considered an error here: the final +/// overrider map can represent multiple final overriders for a +/// method, and it is up to the client to determine whether they are +/// problem. For example, the following class \c D has two final +/// overriders for the virtual function \c A::f(), one in \c C and one +/// in \c D: +/// +/// \code +///   struct A { virtual void f(); }; +///   struct B : virtual A { virtual void f(); }; +///   struct C : virtual A { virtual void f(); }; +///   struct D : B, C { }; +/// \endcode +/// +/// This data structure contaings a mapping from every virtual +/// function *that does not override an existing virtual function* and +/// in every subobject where that virtual function occurs to the set +/// of virtual functions that override it. Thus, the same virtual +/// function \c A::f can actually occur in multiple subobjects of type +/// \c A due to multiple inheritance, and may be overriden by +/// different virtual functions in each, as in the following example: +/// +/// \code +///   struct A { virtual void f(); }; +///   struct B : A { virtual void f(); }; +///   struct C : A { virtual void f(); }; +///   struct D : B, C { }; +/// \endcode +/// +/// Unlike in the previous example, where the virtual functions \c +/// B::f and \c C::f both overrode \c A::f in the same subobject of +/// type \c A, in this example the two virtual functions both override +/// \c A::f but in *different* subobjects of type A. This is +/// represented by numbering the subobjects in which the overridden +/// and the overriding virtual member functions are located. Subobject +/// 0 represents the virtua base class subobject of that type, while +/// subobject numbers greater than 0 refer to non-virtual base class +/// subobjects of that type. +class CXXFinalOverriderMap  +  : public llvm::DenseMap<const CXXMethodDecl *, OverridingMethods> { };  } // end namespace clang diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 1f459b08ca78c..b2a87f617063c 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -165,6 +165,8 @@ public:    // (dynamic) type.    static CanQual<T> CreateUnsafe(QualType Other); +  void dump() const { Stored.dump(); } +    void Profile(llvm::FoldingSetNodeID &ID) const {      ID.AddPointer(getAsOpaquePtr());    } @@ -562,24 +564,21 @@ struct CanProxyAdaptor<ExtVectorType> : public CanProxyBase<ExtVectorType> {  template<>  struct CanProxyAdaptor<FunctionType> : public CanProxyBase<FunctionType> {    LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) +  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)  };  template<>  struct CanProxyAdaptor<FunctionNoProtoType>    : public CanProxyBase<FunctionNoProtoType> {    LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) +  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)  };  template<>  struct CanProxyAdaptor<FunctionProtoType>    : public CanProxyBase<FunctionProtoType> {    LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getResultType) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, getNoReturnAttr) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CallingConv, getCallConv) +  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo)    LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumArgs)    CanQualType getArgType(unsigned i) const {      return CanQualType::CreateUnsafe(this->getTypePtr()->getArgType(i)); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index e23811d8f9c0f..2cdb98351394e 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -224,18 +224,26 @@ class NamespaceDecl : public NamedDecl, public DeclContext {    // NextNamespace points to the next extended declaration.    // OrigNamespace points to the original namespace declaration.    // OrigNamespace of the first namespace decl points to itself. -  NamespaceDecl *OrigNamespace, *NextNamespace; +  NamespaceDecl *NextNamespace; -  // The (most recently entered) anonymous namespace inside this -  // namespace. -  NamespaceDecl *AnonymousNamespace; +  /// \brief A pointer to either the original namespace definition for +  /// this namespace (if the boolean value is false) or the anonymous +  /// namespace that lives just inside this namespace (if the boolean +  /// value is true). +  /// +  /// We can combine these two notions because the anonymous namespace +  /// must only be stored in one of the namespace declarations (so all +  /// of the namespace declarations can find it). We therefore choose +  /// the original namespace declaration, since all of the namespace +  /// declarations have a link directly to it; the original namespace +  /// declaration itself only needs to know that it is the original +  /// namespace declaration (which the boolean indicates). +  llvm::PointerIntPair<NamespaceDecl *, 1, bool> OrigOrAnonNamespace;    NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) -    : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) { -    OrigNamespace = this; -    NextNamespace = 0; -    AnonymousNamespace = 0; -  } +    : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace), +      NextNamespace(0), OrigOrAnonNamespace(0, true) { } +  public:    static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,                                 SourceLocation L, IdentifierInfo *Id); @@ -258,22 +266,33 @@ public:    void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; }    NamespaceDecl *getOriginalNamespace() const { -    return OrigNamespace; +    if (OrigOrAnonNamespace.getInt()) +      return const_cast<NamespaceDecl *>(this); + +    return OrigOrAnonNamespace.getPointer(); +  } + +  void setOriginalNamespace(NamespaceDecl *ND) {  +    if (ND != this) { +      OrigOrAnonNamespace.setPointer(ND); +      OrigOrAnonNamespace.setInt(false); +    }    } -  void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; }    NamespaceDecl *getAnonymousNamespace() const { -    return AnonymousNamespace; +    return getOriginalNamespace()->OrigOrAnonNamespace.getPointer();    }    void setAnonymousNamespace(NamespaceDecl *D) {      assert(!D || D->isAnonymousNamespace());      assert(!D || D->getParent() == this); -    AnonymousNamespace = D; +    getOriginalNamespace()->OrigOrAnonNamespace.setPointer(D);    } -  virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; } -  const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; } +  virtual NamespaceDecl *getCanonicalDecl() { return getOriginalNamespace(); } +  const NamespaceDecl *getCanonicalDecl() const {  +    return getOriginalNamespace();  +  }    virtual SourceRange getSourceRange() const {      return SourceRange(getLocation(), RBracLoc); @@ -1819,12 +1838,12 @@ class RecordDecl : public TagDecl {    /// If so, this cannot be contained in arrays or other structs as a member.    bool HasFlexibleArrayMember : 1; -  /// AnonymousStructOrUnion - Whether this is the type of an -  /// anonymous struct or union. +  /// AnonymousStructOrUnion - Whether this is the type of an anonymous struct +  /// or union.    bool AnonymousStructOrUnion : 1; -  /// HasObjectMember - This is true if this struct has at least one -  /// member containing an object +  /// HasObjectMember - This is true if this struct has at least one member +  /// containing an object.    bool HasObjectMember : 1;  protected: diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 6f8284458f2be..d5913e236c2c4 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -41,6 +41,8 @@ class LinkageSpecDecl;  class BlockDecl;  class DeclarationName;  class CompoundStmt; +class StoredDeclsMap; +class DependentDiagnostic;  }  namespace llvm { @@ -450,15 +452,23 @@ public:    /// same entity may not (and probably don't) share this property.    void setObjectOfFriendDecl(bool PreviouslyDeclared) {      unsigned OldNS = IdentifierNamespace; -    assert((OldNS == IDNS_Tag || OldNS == IDNS_Ordinary || -            OldNS == (IDNS_Tag | IDNS_Ordinary)) -           && "unsupported namespace for undeclared friend"); -    if (!PreviouslyDeclared) IdentifierNamespace = 0; - -    if (OldNS == IDNS_Tag) +    assert((OldNS & (IDNS_Tag | IDNS_Ordinary | +                     IDNS_TagFriend | IDNS_OrdinaryFriend)) && +           "namespace includes neither ordinary nor tag"); +    assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | +                       IDNS_TagFriend | IDNS_OrdinaryFriend)) && +           "namespace includes other than ordinary or tag"); + +    IdentifierNamespace = 0; +    if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {        IdentifierNamespace |= IDNS_TagFriend; -    else +      if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag; +    } + +    if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {        IdentifierNamespace |= IDNS_OrdinaryFriend; +      if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary; +    }    }    enum FriendObjectKind { @@ -545,9 +555,9 @@ class DeclContext {    mutable bool ExternalVisibleStorage : 1;    /// \brief Pointer to the data structure used to lookup declarations -  /// within this context, which is a DenseMap<DeclarationName, -  /// StoredDeclsList>. -  mutable void* LookupPtr; +  /// within this context (or a DependentStoredDeclsMap if this is a +  /// dependent context). +  mutable StoredDeclsMap *LookupPtr;    /// FirstDecl - The first declaration stored within this declaration    /// context. @@ -674,6 +684,9 @@ public:    /// "primary" DeclContext structure, which will contain the    /// information needed to perform name lookup into this context.    DeclContext *getPrimaryContext(); +  const DeclContext *getPrimaryContext() const { +    return const_cast<DeclContext*>(this)->getPrimaryContext(); +  }    /// getLookupContext - Retrieve the innermost non-transparent    /// context of this context, which corresponds to the innermost @@ -976,10 +989,15 @@ public:      return getUsingDirectives().second;    } +  // These are all defined in DependentDiagnostic.h. +  class ddiag_iterator; +  inline ddiag_iterator ddiag_begin() const; +  inline ddiag_iterator ddiag_end() const; +    // Low-level accessors    /// \brief Retrieve the internal representation of the lookup structure. -  void* getLookupPtr() const { return LookupPtr; } +  StoredDeclsMap* getLookupPtr() const { return LookupPtr; }    /// \brief Whether this DeclContext has external storage containing    /// additional declarations that are lexically in this context. @@ -1013,6 +1031,9 @@ private:    void LoadLexicalDeclsFromExternalStorage() const;    void LoadVisibleDeclsFromExternalStorage() const; +  friend class DependentDiagnostic; +  StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; +    void buildLookup(DeclContext *DCtx);    void makeDeclVisibleInContextImpl(NamedDecl *D);  }; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 6b04ed54109ad..23769af46b367 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -33,6 +33,7 @@ class CXXDestructorDecl;  class CXXMethodDecl;  class CXXRecordDecl;  class CXXMemberLookupCriteria; +class CXXFinalOverriderMap;  class FriendDecl;  /// \brief Represents any kind of function declaration, whether it is a @@ -328,6 +329,10 @@ class CXXRecordDecl : public RecordDecl {    /// instantiated or specialized.    llvm::PointerUnion<ClassTemplateDecl*, MemberSpecializationInfo*>      TemplateOrInstantiation; + +#ifndef NDEBUG +  void CheckConversionFunction(NamedDecl *D); +#endif  protected:    CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, @@ -549,17 +554,26 @@ public:      return getConversionFunctions()->replace(Old, New);    } +  /// Removes a conversion function from this class.  The conversion +  /// function must currently be a member of this class.  Furthermore, +  /// this class must currently be in the process of being defined. +  void removeConversion(const NamedDecl *Old); +    /// getVisibleConversionFunctions - get all conversion functions visible    /// in current class; including conversion function templates.    const UnresolvedSetImpl *getVisibleConversionFunctions(); -  /// addConversionFunction - Add a new conversion function to the -  /// list of conversion functions. -  void addConversionFunction(CXXConversionDecl *ConvDecl); +  /// addConversionFunction - Registers a conversion function which +  /// this class declares directly. +  void addConversionFunction(NamedDecl *Decl) { +#ifndef NDEBUG +    CheckConversionFunction(Decl); +#endif -  /// \brief Add a new conversion function template to the list of conversion -  /// functions. -  void addConversionFunction(FunctionTemplateDecl *ConvDecl); +    // We intentionally don't use the decl's access here because it +    // hasn't been set yet.  That's really just a misdesign in Sema. +    data().Conversions.addDecl(Decl); +  }    /// isAggregate - Whether this class is an aggregate (C++    /// [dcl.init.aggr]), which is a class with no user-declared @@ -879,7 +893,12 @@ public:    static bool FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier,                                              CXXBasePath &Path,                                              void *UserData); -   + +  /// \brief Retrieve the final overriders for each virtual member +  /// function in the class hierarchy where this class is the +  /// most-derived class in the class hierarchy. +  void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const; +    /// viewInheritance - Renders and displays an inheritance diagram    /// for this C++ class and all of its base classes (transitively) using    /// GraphViz. @@ -935,7 +954,7 @@ public:      return (CD->begin_overridden_methods() != CD->end_overridden_methods());    } -   +    /// \brief Determine whether this is a usual deallocation function    /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded    /// delete or delete[] operator with a particular signature. diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 32405ee812604..16cb491344bc8 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -24,6 +24,8 @@  namespace clang { +class DependentDiagnostic; +  /// StoredDeclsList - This is an array of decls optimized a common case of only  /// containing one entry.  struct StoredDeclsList { @@ -258,8 +260,28 @@ public:    }  }; -typedef llvm::DenseMap<DeclarationName, StoredDeclsList> StoredDeclsMap; +class StoredDeclsMap +  : public llvm::DenseMap<DeclarationName, StoredDeclsList> { + +public: +  static void DestroyAll(StoredDeclsMap *Map, bool Dependent); + +private: +  friend class ASTContext; // walks the chain deleting these +  friend class DeclContext; +  llvm::PointerIntPair<StoredDeclsMap*, 1> Previous; +}; +class DependentStoredDeclsMap : public StoredDeclsMap { +public: +  DependentStoredDeclsMap() : FirstDiagnostic(0) {} + +private: +  friend class DependentDiagnostic; +  friend class DeclContext; // iterates over diagnostics + +  DependentDiagnostic *FirstDiagnostic; +};  } // end namespace clang diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 5022ad018f4f9..99ef738980cc8 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -36,7 +36,7 @@ namespace clang {  /// The semantic context of a friend decl is its declaring class.  class FriendDecl : public Decl {  public: -  typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion; +  typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;  private:    // The declaration that's a friend of this class. @@ -73,8 +73,8 @@ public:    /// possibly dependent) type, return the type;  otherwise    /// return null.  This is used only for C++0x's unelaborated    /// friend type declarations. -  Type *getFriendType() const { -    return Friend.dyn_cast<Type*>(); +  TypeSourceInfo *getFriendType() const { +    return Friend.dyn_cast<TypeSourceInfo*>();    }    /// If this friend declaration doesn't name an unelaborated diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 560ce46ede7c3..8d1a4caccb232 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -1238,7 +1238,7 @@ public:  ///   template <typename U> friend class Foo<T>::Nested; // friend template  class FriendTemplateDecl : public Decl {  public: -  typedef llvm::PointerUnion<NamedDecl*,Type*> FriendUnion; +  typedef llvm::PointerUnion<NamedDecl*,TypeSourceInfo*> FriendUnion;  private:    // The number of template parameters;  always non-zero. @@ -1277,8 +1277,8 @@ public:    /// If this friend declaration names a templated type (or    /// a dependent member type of a templated type), return that    /// type;  otherwise return null. -  Type *getFriendType() const { -    return Friend.dyn_cast<Type*>(); +  TypeSourceInfo *getFriendType() const { +    return Friend.dyn_cast<TypeSourceInfo*>();    }    /// If this friend declaration names a templated function (or diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 2254724410d0b..6225069c602fe 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -378,7 +378,7 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,                    Diagnostic::ak_declarationname);    return PD;  } -   +  }  // end namespace clang  namespace llvm { diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h new file mode 100644 index 0000000000000..1954a282e8020 --- /dev/null +++ b/include/clang/AST/DependentDiagnostic.h @@ -0,0 +1,183 @@ +//===-- DependentDiagnostic.h - Dependently-generated diagnostics -*- C++ -*-=// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//  This file defines interfaces for diagnostics which may or may +//  fire based on how a template is instantiated. +// +//  At the moment, the only consumer of this interface is access +//  control. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H +#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H + +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclContextInternals.h" + +namespace clang { + +class ASTContext; +class CXXRecordDecl; +class NamedDecl; + +/// A dependently-generated diagnostic. +class DependentDiagnostic { +public: +  enum AccessNonce { Access = 0 }; + +  static DependentDiagnostic *Create(ASTContext &Context, +                                     DeclContext *Parent, +                                     AccessNonce _, +                                     SourceLocation Loc, +                                     bool IsMemberAccess, +                                     AccessSpecifier AS, +                                     NamedDecl *TargetDecl, +                                     CXXRecordDecl *NamingClass, +                                     const PartialDiagnostic &PDiag) { +    DependentDiagnostic *DD = Create(Context, Parent, PDiag); +    DD->AccessData.Loc = Loc.getRawEncoding(); +    DD->AccessData.IsMember = IsMemberAccess; +    DD->AccessData.Access = AS; +    DD->AccessData.TargetDecl = TargetDecl; +    DD->AccessData.NamingClass = NamingClass; +    return DD; +  } + +  unsigned getKind() const { +    return Access; +  } + +  bool isAccessToMember() const { +    assert(getKind() == Access); +    return AccessData.IsMember; +  } + +  AccessSpecifier getAccess() const { +    assert(getKind() == Access); +    return AccessSpecifier(AccessData.Access); +  } + +  SourceLocation getAccessLoc() const { +    assert(getKind() == Access); +    return SourceLocation::getFromRawEncoding(AccessData.Loc); +  } + +  NamedDecl *getAccessTarget() const { +    assert(getKind() == Access); +    return AccessData.TargetDecl; +  } + +  NamedDecl *getAccessNamingClass() const { +    assert(getKind() == Access); +    return AccessData.NamingClass; +  } + +  const PartialDiagnostic &getDiagnostic() const { +    return Diag; +  } + +private: +  DependentDiagnostic(const PartialDiagnostic &PDiag, +                      PartialDiagnostic::Storage *Storage)  +    : Diag(PDiag, Storage) {} +   +  static DependentDiagnostic *Create(ASTContext &Context, +                                     DeclContext *Parent, +                                     const PartialDiagnostic &PDiag); + +  friend class DependentStoredDeclsMap; +  friend class DeclContext::ddiag_iterator; +  DependentDiagnostic *NextDiagnostic; + +  PartialDiagnostic Diag; + +  union { +    struct { +      unsigned Loc; +      unsigned Access : 2; +      unsigned IsMember : 1; +      NamedDecl *TargetDecl; +      CXXRecordDecl *NamingClass; +    } AccessData; +  }; +}; + +///  + +/// An iterator over the dependent diagnostics in a dependent context. +class DeclContext::ddiag_iterator { +public: +  ddiag_iterator() : Ptr(0) {} +  explicit ddiag_iterator(DependentDiagnostic *Ptr) : Ptr(Ptr) {} + +  typedef DependentDiagnostic *value_type; +  typedef DependentDiagnostic *reference; +  typedef DependentDiagnostic *pointer; +  typedef int difference_type; +  typedef std::forward_iterator_tag iterator_category; + +  reference operator*() const { return Ptr; } + +  ddiag_iterator &operator++() { +    assert(Ptr && "attempt to increment past end of diag list"); +    Ptr = Ptr->NextDiagnostic; +    return *this; +  } + +  ddiag_iterator operator++(int) { +    ddiag_iterator tmp = *this; +    ++*this; +    return tmp; +  } + +  bool operator==(ddiag_iterator Other) const { +    return Ptr == Other.Ptr; +  } + +  bool operator!=(ddiag_iterator Other) const { +    return Ptr != Other.Ptr; +  } + +  ddiag_iterator &operator+=(difference_type N) { +    assert(N >= 0 && "cannot rewind a DeclContext::ddiag_iterator"); +    while (N--) +      ++*this; +    return *this; +  } + +  ddiag_iterator operator+(difference_type N) const { +    ddiag_iterator tmp = *this; +    tmp += N; +    return tmp; +  } + +private: +  DependentDiagnostic *Ptr; +}; + +inline DeclContext::ddiag_iterator DeclContext::ddiag_begin() const { +  assert(isDependentContext() +         && "cannot iterate dependent diagnostics of non-dependent context"); +  const DependentStoredDeclsMap *Map +    = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->LookupPtr); + +  if (!Map) return ddiag_iterator(); +  return ddiag_iterator(Map->FirstDiagnostic); +} + +inline DeclContext::ddiag_iterator DeclContext::ddiag_end() const { +  return ddiag_iterator(); +} + +} + +#endif diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6b14e47cbef50..507a61c6d7a63 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1263,6 +1263,11 @@ public:  /// MemberExpr - [C99 6.5.2.3] Structure and Union Members.  X->F and X.F.  ///  class MemberExpr : public Expr { +  /// Extra data stored in some member expressions. +  struct MemberNameQualifier : public NameQualifier { +    NamedDecl *FoundDecl; +  }; +    /// Base - the expression for the base pointer or structure references.  In    /// X.F, this is "X".    Stmt *Base; @@ -1278,27 +1283,26 @@ class MemberExpr : public Expr {    bool IsArrow : 1;    /// \brief True if this member expression used a nested-name-specifier to -  /// refer to the member, e.g., "x->Base::f". When true, a NameQualifier +  /// refer to the member, e.g., "x->Base::f", or found its member via a using +  /// declaration.  When true, a MemberNameQualifier    /// structure is allocated immediately after the MemberExpr. -  bool HasQualifier : 1; +  bool HasQualifierOrFoundDecl : 1;    /// \brief True if this member expression specified a template argument list    /// explicitly, e.g., x->f<int>. When true, an ExplicitTemplateArgumentList    /// structure (and its TemplateArguments) are allocated immediately after    /// the MemberExpr or, if the member expression also has a qualifier, after -  /// the NameQualifier structure. +  /// the MemberNameQualifier structure.    bool HasExplicitTemplateArgumentList : 1;    /// \brief Retrieve the qualifier that preceded the member name, if any. -  NameQualifier *getMemberQualifier() { -    if (!HasQualifier) -      return 0; - -    return reinterpret_cast<NameQualifier *> (this + 1); +  MemberNameQualifier *getMemberQualifier() { +    assert(HasQualifierOrFoundDecl); +    return reinterpret_cast<MemberNameQualifier *> (this + 1);    }    /// \brief Retrieve the qualifier that preceded the member name, if any. -  const NameQualifier *getMemberQualifier() const { +  const MemberNameQualifier *getMemberQualifier() const {      return const_cast<MemberExpr *>(this)->getMemberQualifier();    } @@ -1308,7 +1312,7 @@ class MemberExpr : public Expr {      if (!HasExplicitTemplateArgumentList)        return 0; -    if (!HasQualifier) +    if (!HasQualifierOrFoundDecl)        return reinterpret_cast<ExplicitTemplateArgumentList *>(this + 1);      return reinterpret_cast<ExplicitTemplateArgumentList *>( @@ -1321,26 +1325,22 @@ class MemberExpr : public Expr {      return const_cast<MemberExpr *>(this)->getExplicitTemplateArgumentList();    } -  MemberExpr(Expr *base, bool isarrow, NestedNameSpecifier *qual, -             SourceRange qualrange, ValueDecl *memberdecl, SourceLocation l, -             const TemplateArgumentListInfo *targs, QualType ty); -  public:    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), -      HasQualifier(false), HasExplicitTemplateArgumentList(false) {} +      HasQualifierOrFoundDecl(false), HasExplicitTemplateArgumentList(false) {}    /// \brief Build an empty member reference expression.    explicit MemberExpr(EmptyShell Empty) -    : Expr(MemberExprClass, Empty), HasQualifier(false), +    : Expr(MemberExprClass, Empty), HasQualifierOrFoundDecl(false),        HasExplicitTemplateArgumentList(false) { }    static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow,                              NestedNameSpecifier *qual, SourceRange qualrange, -                            ValueDecl *memberdecl, +                            ValueDecl *memberdecl, NamedDecl *founddecl,                              SourceLocation l,                              const TemplateArgumentListInfo *targs,                              QualType ty); @@ -1355,16 +1355,23 @@ public:    ValueDecl *getMemberDecl() const { return MemberDecl; }    void setMemberDecl(ValueDecl *D) { MemberDecl = D; } +  /// \brief Retrieves the declaration found by lookup. +  NamedDecl *getFoundDecl() const { +    if (!HasQualifierOrFoundDecl) +      return getMemberDecl(); +    return getMemberQualifier()->FoundDecl; +  } +    /// \brief Determines whether this member expression actually had    /// a C++ nested-name-specifier prior to the name of the member, e.g.,    /// x->Base::foo. -  bool hasQualifier() const { return HasQualifier; } +  bool hasQualifier() const { return getQualifier() != 0; }    /// \brief If the member name was qualified, retrieves the source range of    /// the nested-name-specifier that precedes the member name. Otherwise,    /// returns an empty source range.    SourceRange getQualifierRange() const { -    if (!HasQualifier) +    if (!HasQualifierOrFoundDecl)        return SourceRange();      return getMemberQualifier()->Range; @@ -1374,7 +1381,7 @@ public:    /// nested-name-specifier that precedes the member name. Otherwise, returns    /// NULL.    NestedNameSpecifier *getQualifier() const { -    if (!HasQualifier) +    if (!HasQualifierOrFoundDecl)        return 0;      return getMemberQualifier()->NNS; @@ -1545,6 +1552,10 @@ public:      /// CK_DerivedToBase - Derived to base class casts.      CK_DerivedToBase, +    /// CK_UncheckedDerivedToBase - Derived to base class casts that +    /// assume that the derived pointer is not null. +    CK_UncheckedDerivedToBase, +      /// CK_Dynamic - Dynamic cast.      CK_Dynamic, diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index d1351b8b14471..6e2e832e3542d 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -1095,8 +1095,8 @@ public:      : Expr(CXXPseudoDestructorExprClass,             Context.getPointerType(Context.getFunctionType(Context.VoidTy, 0, 0,                                                            false, 0, false,  -                                                          false, 0, 0, false, -                                                          CC_Default)), +                                                          false, 0, 0, +                                                      FunctionType::ExtInfo())),             /*isTypeDependent=*/(Base->isTypeDependent() ||              (DestroyedType.getTypeSourceInfo() &&                DestroyedType.getTypeSourceInfo()->getType()->isDependentType())), diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 111be5562199f..72793651c4be9 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -17,6 +17,7 @@  #include "clang/Basic/Diagnostic.h"  #include "clang/Basic/IdentifierTable.h"  #include "clang/Basic/Linkage.h" +#include "clang/Basic/PartialDiagnostic.h"  #include "clang/AST/NestedNameSpecifier.h"  #include "clang/AST/TemplateName.h"  #include "llvm/Support/Casting.h" @@ -678,14 +679,6 @@ public:      return getObjCGCAttr() == Qualifiers::Strong;    } -  /// getNoReturnAttr - Returns true if the type has the noreturn attribute, -  /// false otherwise. -  bool getNoReturnAttr() const; - -  /// getCallConv - Returns the calling convention of the type if the type -  /// is a function type, CC_Default otherwise. -  CallingConv getCallConv() const; -  private:    // These methods are implemented in a separate translation unit;    // "static"-ize them to avoid creating temporary QualTypes in the @@ -902,6 +895,9 @@ public:    bool isDependentType() const { return Dependent; }    bool isOverloadableType() const; +  /// \brief Determine wither this type is a C++ elaborated-type-specifier. +  bool isElaboratedTypeSpecifier() const; +      /// hasPointerRepresentation - Whether this type is represented    /// natively as a pointer; this includes pointers, references, block    /// pointers, and Objective-C interface, qualified id, and qualified @@ -1747,25 +1743,101 @@ class FunctionType : public Type {    /// NoReturn - Indicates if the function type is attribute noreturn.    unsigned NoReturn : 1; +  /// RegParm - How many arguments to pass inreg. +  unsigned RegParm : 3; +    /// CallConv - The calling convention used by the function.    unsigned CallConv : 2;    // The type returned by the function.    QualType ResultType; + + public: +  // This class is used for passing arround the information needed to +  // construct a call. It is not actually used for storage, just for +  // factoring together common arguments. +  // If you add a field (say Foo), other than the obvious places (both, constructors, +  // compile failures), what you need to update is +  // * Operetor== +  // * getFoo +  // * withFoo +  // * functionType. Add Foo, getFoo. +  // * ASTContext::getFooType +  // * ASTContext::mergeFunctionTypes +  // * FunctionNoProtoType::Profile +  // * FunctionProtoType::Profile +  // * TypePrinter::PrintFunctionProto +  // * PCH read and write +  // * Codegen + +  class ExtInfo { +   public: +    // Constructor with no defaults. Use this when you know that you +    // have all the elements (when reading a PCH file for example). +    ExtInfo(bool noReturn, unsigned regParm, CallingConv cc) : +        NoReturn(noReturn), RegParm(regParm), CC(cc) {} + +    // Constructor with all defaults. Use when for example creating a +    // function know to use defaults. +    ExtInfo() : NoReturn(false), RegParm(0), CC(CC_Default) {} + +    bool getNoReturn() const { return NoReturn; } +    unsigned getRegParm() const { return RegParm; } +    CallingConv getCC() const { return CC; } + +    bool operator==(const ExtInfo &Other) const { +      return getNoReturn() == Other.getNoReturn() && +          getRegParm() == Other.getRegParm() && +          getCC() == Other.getCC(); +    } +    bool operator!=(const ExtInfo &Other) const { +      return !(*this == Other); +    } + +    // Note that we don't have setters. That is by design, use +    // the following with methods instead of mutating these objects. + +    ExtInfo withNoReturn(bool noReturn) const { +      return ExtInfo(noReturn, getRegParm(), getCC()); +    } + +    ExtInfo withRegParm(unsigned RegParm) const { +      return ExtInfo(getNoReturn(), RegParm, getCC()); +    } + +    ExtInfo withCallingConv(CallingConv cc) const { +      return ExtInfo(getNoReturn(), getRegParm(), cc); +    } + +   private: +    // True if we have __attribute__((noreturn)) +    bool NoReturn; +    // The value passed to __attribute__((regparm(x))) +    unsigned RegParm; +    // The calling convention as specified via +    // __attribute__((cdecl|stdcall||fastcall)) +    CallingConv CC; +  }; +  protected:    FunctionType(TypeClass tc, QualType res, bool SubclassInfo,                 unsigned typeQuals, QualType Canonical, bool Dependent, -               bool noReturn = false, CallingConv callConv = CC_Default) +               const ExtInfo &Info)      : Type(tc, Canonical, Dependent), -      SubClassData(SubclassInfo), TypeQuals(typeQuals), NoReturn(noReturn), -      CallConv(callConv), ResultType(res) {} +      SubClassData(SubclassInfo), TypeQuals(typeQuals), +      NoReturn(Info.getNoReturn()), +      RegParm(Info.getRegParm()), CallConv(Info.getCC()), ResultType(res) {}    bool getSubClassData() const { return SubClassData; }    unsigned getTypeQuals() const { return TypeQuals; }  public:    QualType getResultType() const { return ResultType; } +  unsigned getRegParmType() const { return RegParm; }    bool getNoReturnAttr() const { return NoReturn; }    CallingConv getCallConv() const { return (CallingConv)CallConv; } +  ExtInfo getExtInfo() const { +    return ExtInfo(NoReturn, RegParm, (CallingConv)CallConv); +  }    static llvm::StringRef getNameForCallConv(CallingConv CC); @@ -1780,9 +1852,9 @@ public:  /// no information available about its arguments.  class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {    FunctionNoProtoType(QualType Result, QualType Canonical, -                      bool NoReturn = false, CallingConv CallConv = CC_Default) +                      const ExtInfo &Info)      : FunctionType(FunctionNoProto, Result, false, 0, Canonical, -                   /*Dependent=*/false, NoReturn, CallConv) {} +                   /*Dependent=*/false, Info) {}    friend class ASTContext;  // ASTContext creates these.  public:    // No additional state past what FunctionType provides. @@ -1791,12 +1863,13 @@ public:    QualType desugar() const { return QualType(this, 0); }    void Profile(llvm::FoldingSetNodeID &ID) { -    Profile(ID, getResultType(), getNoReturnAttr(), getCallConv()); +    Profile(ID, getResultType(), getExtInfo());    }    static void Profile(llvm::FoldingSetNodeID &ID, QualType ResultType, -                      bool NoReturn, CallingConv CallConv) { -    ID.AddInteger(CallConv); -    ID.AddInteger(NoReturn); +                      const ExtInfo &Info) { +    ID.AddInteger(Info.getCC()); +    ID.AddInteger(Info.getRegParm()); +    ID.AddInteger(Info.getNoReturn());      ID.AddPointer(ResultType.getAsOpaquePtr());    } @@ -1827,12 +1900,12 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {    FunctionProtoType(QualType Result, const QualType *ArgArray, unsigned numArgs,                      bool isVariadic, unsigned typeQuals, bool hasExs,                      bool hasAnyExs, const QualType *ExArray, -                    unsigned numExs, QualType Canonical, bool NoReturn, -                    CallingConv CallConv) +                    unsigned numExs, QualType Canonical, +                    const ExtInfo &Info)      : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical,                     (Result->isDependentType() || -                    hasAnyDependentType(ArgArray, numArgs)), NoReturn, -                   CallConv), +                    hasAnyDependentType(ArgArray, numArgs)), +                   Info),        NumArgs(numArgs), NumExceptions(numExs), HasExceptionSpec(hasExs),        AnyExceptionSpec(hasAnyExs) {      // Fill in the trailing argument array. @@ -1918,7 +1991,7 @@ public:                        bool isVariadic, unsigned TypeQuals,                        bool hasExceptionSpec, bool anyExceptionSpec,                        unsigned NumExceptions, exception_iterator Exs, -                      bool NoReturn, CallingConv CallConv); +                      const ExtInfo &ExtInfo);  }; @@ -2481,6 +2554,24 @@ public:    static bool classof(const InjectedClassNameType *T) { return true; }  }; +/// \brief The elaboration keyword that precedes a qualified type name or +/// introduces an elaborated-type-specifier. +enum ElaboratedTypeKeyword { +  /// \brief No keyword precedes the qualified type name. +  ETK_None, +  /// \brief The "typename" keyword precedes the qualified type name, e.g., +  /// \c typename T::type. +  ETK_Typename, +  /// \brief The "class" keyword introduces the elaborated-type-specifier. +  ETK_Class, +  /// \brief The "struct" keyword introduces the elaborated-type-specifier. +  ETK_Struct, +  /// \brief The "union" keyword introduces the elaborated-type-specifier. +  ETK_Union, +  /// \brief The "enum" keyword introduces the elaborated-type-specifier. +  ETK_Enum +}; +    /// \brief Represents a type that was referred to via a qualified  /// name, e.g., N::M::type.  /// @@ -2531,19 +2622,19 @@ public:    static bool classof(const QualifiedNameType *T) { return true; }  }; -/// \brief Represents a 'typename' specifier that names a type within -/// a dependent type, e.g., "typename T::type". +/// \brief Represents a qualified type name for which the type name is +/// dependent.   /// -/// TypenameType has a very similar structure to QualifiedNameType, -/// which also involves a nested-name-specifier following by a type, -/// and (FIXME!) both can even be prefixed by the 'typename' -/// keyword. However, the two types serve very different roles: -/// QualifiedNameType is a non-semantic type that serves only as sugar -/// to show how a particular type was written in the source -/// code. TypenameType, on the other hand, only occurs when the -/// nested-name-specifier is dependent, such that we cannot resolve -/// the actual type until after instantiation. -class TypenameType : public Type, public llvm::FoldingSetNode { +/// DependentNameType represents a class of dependent types that involve a  +/// dependent nested-name-specifier (e.g., "T::") followed by a (dependent)  +/// name of a type. The DependentNameType may start with a "typename" (for a +/// typename-specifier), "class", "struct", "union", or "enum" (for a  +/// dependent elaborated-type-specifier), or nothing (in contexts where we +/// know that we must be referring to a type, e.g., in a base class specifier). +class DependentNameType : public Type, public llvm::FoldingSetNode { +  /// \brief The keyword used to elaborate this type. +  ElaboratedTypeKeyword Keyword; +      /// \brief The nested name specifier containing the qualifier.    NestedNameSpecifier *NNS; @@ -2553,23 +2644,28 @@ class TypenameType : public Type, public llvm::FoldingSetNode {    /// \brief The type that this typename specifier refers to.    NameType Name; -  TypenameType(NestedNameSpecifier *NNS, const IdentifierInfo *Name, -               QualType CanonType) -    : Type(Typename, CanonType, true), NNS(NNS), Name(Name) { +  DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS,  +                    const IdentifierInfo *Name, QualType CanonType) +    : Type(DependentName, CanonType, true),  +      Keyword(Keyword), NNS(NNS), Name(Name) {      assert(NNS->isDependent() && -           "TypenameType requires a dependent nested-name-specifier"); +           "DependentNameType requires a dependent nested-name-specifier");    } -  TypenameType(NestedNameSpecifier *NNS, const TemplateSpecializationType *Ty, -               QualType CanonType) -    : Type(Typename, CanonType, true), NNS(NNS), Name(Ty) { +  DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, +                    const TemplateSpecializationType *Ty, QualType CanonType) +    : Type(DependentName, CanonType, true),  +      Keyword(Keyword), NNS(NNS), Name(Ty) {      assert(NNS->isDependent() && -           "TypenameType requires a dependent nested-name-specifier"); +           "DependentNameType requires a dependent nested-name-specifier");    }    friend class ASTContext;  // ASTContext creates these  public: +  /// \brief Retrieve the keyword used to elaborate this type. +  ElaboratedTypeKeyword getKeyword() const { return Keyword; } +      /// \brief Retrieve the qualification on this type.    NestedNameSpecifier *getQualifier() const { return NNS; } @@ -2593,19 +2689,20 @@ public:    QualType desugar() const { return QualType(this, 0); }    void Profile(llvm::FoldingSetNodeID &ID) { -    Profile(ID, NNS, Name); +    Profile(ID, Keyword, NNS, Name);    } -  static void Profile(llvm::FoldingSetNodeID &ID, NestedNameSpecifier *NNS, -                      NameType Name) { +  static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, +                      NestedNameSpecifier *NNS, NameType Name) { +    ID.AddInteger(Keyword);      ID.AddPointer(NNS);      ID.AddPointer(Name.getOpaqueValue());    }    static bool classof(const Type *T) { -    return T->getTypeClass() == Typename; +    return T->getTypeClass() == DependentName;    } -  static bool classof(const TypenameType *T) { return true; } +  static bool classof(const DependentNameType *T) { return true; }  };  /// ObjCInterfaceType - Interfaces are the core concept in Objective-C for @@ -2936,37 +3033,18 @@ inline Qualifiers::GC QualType::getObjCGCAttr() const {    return Qualifiers::GCNone;  } -  /// getNoReturnAttr - Returns true if the type has the noreturn attribute, -  /// false otherwise. -inline bool QualType::getNoReturnAttr() const { -  QualType CT = getTypePtr()->getCanonicalTypeInternal(); -  if (const PointerType *PT = getTypePtr()->getAs<PointerType>()) { +inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { +  if (const PointerType *PT = t.getAs<PointerType>()) {      if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>()) -      return FT->getNoReturnAttr(); -  } else if (const FunctionType *FT = getTypePtr()->getAs<FunctionType>()) -    return FT->getNoReturnAttr(); +      return FT->getExtInfo(); +  } else if (const FunctionType *FT = t.getAs<FunctionType>()) +    return FT->getExtInfo(); -  return false; +  return FunctionType::ExtInfo();  } -/// getCallConv - Returns the calling convention of the type if the type -/// is a function type, CC_Default otherwise. -inline CallingConv QualType::getCallConv() const { -  if (const PointerType *PT = getTypePtr()->getAs<PointerType>()) -    return PT->getPointeeType().getCallConv(); -  else if (const ReferenceType *RT = getTypePtr()->getAs<ReferenceType>()) -    return RT->getPointeeType().getCallConv(); -  else if (const MemberPointerType *MPT = -           getTypePtr()->getAs<MemberPointerType>()) -    return MPT->getPointeeType().getCallConv(); -  else if (const BlockPointerType *BPT = -           getTypePtr()->getAs<BlockPointerType>()) { -    if (const FunctionType *FT = BPT->getPointeeType()->getAs<FunctionType>()) -      return FT->getCallConv(); -  } else if (const FunctionType *FT = getTypePtr()->getAs<FunctionType>()) -    return FT->getCallConv(); - -  return CC_Default; +inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { +  return getFunctionExtInfo(*t);  }  /// isMoreQualifiedThan - Determine whether this type is more @@ -3152,6 +3230,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,    return DB;  } +/// Insertion operator for partial diagnostics.  This allows sending QualType's +/// into a diagnostic with <<. +inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, +                                           QualType T) { +  PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), +                  Diagnostic::ak_qualtype); +  return PD; +} +  // Helper class template that is used by Type::getAs to ensure that one does  // not try to look through a qualified type to get to an array type.  template<typename T, diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 27659bd02f979..a51da7474d376 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1242,9 +1242,9 @@ class QualifiedNameTypeLoc :  };  // FIXME: locations for the typename keyword and nested name specifier. -class TypenameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, -                                                         TypenameTypeLoc, -                                                         TypenameType> { +class DependentNameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, +                                                         DependentNameTypeLoc, +                                                         DependentNameType> {  };  } diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index e75202e50abf8..7e8b73c7a5f97 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -92,7 +92,7 @@ NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)  NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type)  NON_CANONICAL_TYPE(QualifiedName, Type)  NON_CANONICAL_TYPE(InjectedClassName, Type) -DEPENDENT_TYPE(Typename, Type) +DEPENDENT_TYPE(DependentName, Type)  TYPE(ObjCInterface, Type)  TYPE(ObjCObjectPointer, Type) diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index bde4417412277..9ebd93b75b382 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -33,7 +33,7 @@ class ParentMap;  class ImplicitParamDecl;  class LocationContextManager;  class StackFrameContext; -   +  /// AnalysisContext contains the context data for the function or method under  /// analysis.  class AnalysisContext { @@ -41,6 +41,7 @@ class AnalysisContext {    // AnalysisContext owns the following data.    CFG *cfg; +  bool builtCFG;    LiveVariables *liveness;    ParentMap *PM;    llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; @@ -48,8 +49,8 @@ class AnalysisContext {    bool AddEHEdges;  public:    AnalysisContext(const Decl *d, bool addehedges = false) -    : D(d), cfg(0), liveness(0), PM(0), ReferencedBlockVars(0), -      AddEHEdges(addehedges) {} +    : D(d), cfg(0), builtCFG(false), liveness(0), PM(0), +      ReferencedBlockVars(0), AddEHEdges(addehedges) {}    ~AnalysisContext(); @@ -69,7 +70,7 @@ public:    std::pair<referenced_decls_iterator, referenced_decls_iterator>      getReferencedBlockVars(const BlockDecl *BD); -   +    /// Return the ImplicitParamDecl* associated with 'self' if this    /// AnalysisContext wraps an ObjCMethodDecl.  Returns NULL otherwise.    const ImplicitParamDecl *getSelfDecl() const; @@ -82,7 +83,7 @@ public:    ~AnalysisContextManager();    AnalysisContext *getContext(const Decl *D); -   +    // Discard all previously created AnalysisContexts.    void clear();  }; @@ -103,7 +104,7 @@ protected:  public:    virtual ~LocationContext(); -   +    ContextKind getKind() const { return Kind; }    AnalysisContext *getAnalysisContext() const { return Ctx; } @@ -120,14 +121,14 @@ public:      return getAnalysisContext()->getLiveVariables();    } -  ParentMap &getParentMap() const {  +  ParentMap &getParentMap() const {      return getAnalysisContext()->getParentMap();    }    const ImplicitParamDecl *getSelfDecl() const {      return Ctx->getSelfDecl();    } -   +    const StackFrameContext *getCurrentStackFrame() const;    const StackFrameContext *      getStackFrameForDeclContext(const DeclContext *DC) const; @@ -157,7 +158,7 @@ class StackFrameContext : public LocationContext {    friend class LocationContextManager;    StackFrameContext(AnalysisContext *ctx, const LocationContext *parent,                      const Stmt *s, const CFGBlock *blk, unsigned idx) -    : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),  +    : LocationContext(StackFrame, ctx, parent), CallSite(s), Block(blk),        Index(idx) {}  public: @@ -170,9 +171,9 @@ public:    unsigned getIndex() const { return Index; }    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,                        const CFGBlock *blk, unsigned idx) {      ProfileCommon(ID, StackFrame, ctx, parent, s);      ID.AddPointer(blk); @@ -186,7 +187,7 @@ public:  class ScopeContext : public LocationContext {    const Stmt *Enter; -   +    friend class LocationContextManager;    ScopeContext(AnalysisContext *ctx, const LocationContext *parent,                 const Stmt *s) @@ -229,7 +230,7 @@ public:                        const LocationContext *parent, const BlockDecl *bd) {      ProfileCommon(ID, Block, ctx, parent, bd);    } -   +    static bool classof(const LocationContext* Ctx) {      return Ctx->getKind() == Block;    } @@ -239,7 +240,7 @@ class LocationContextManager {    llvm::FoldingSet<LocationContext> Contexts;  public:    ~LocationContextManager(); -   +    const StackFrameContext *getStackFrame(AnalysisContext *ctx,                                           const LocationContext *parent,                                           const Stmt *s, const CFGBlock *blk, @@ -248,7 +249,7 @@ public:    const ScopeContext *getScope(AnalysisContext *ctx,                                 const LocationContext *parent,                                 const Stmt *s); -   +    /// Discard all previously created LocationContext objects.    void clear();  private: diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index cbf7010bfdb53..3c762011a6575 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -17,7 +17,8 @@  #include "clang/Analysis/CFG.h"  #include "clang/Analysis/ProgramPoint.h"  #include "clang/Analysis/FlowSensitive/DataflowValues.h" -#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h"  #include "functional" // STL  namespace clang { @@ -28,23 +29,30 @@ namespace clang {  //===----------------------------------------------------------------------===//  class DataflowWorkListTy { -  typedef llvm::SmallPtrSet<const CFGBlock*,20> BlockSet; -  BlockSet wlist; +  llvm::DenseMap<const CFGBlock*, unsigned char> BlockSet; +  llvm::SmallVector<const CFGBlock *, 10> BlockQueue;  public:    /// enqueue - Add a block to the worklist.  Blocks already on the    ///  worklist are not added a second time. -  void enqueue(const CFGBlock* B) { wlist.insert(B); } +  void enqueue(const CFGBlock* B) { +    unsigned char &x = BlockSet[B]; +    if (x == 1) +      return; +    x = 1; +    BlockQueue.push_back(B); +  }    /// dequeue - Remove a block from the worklist.    const CFGBlock* dequeue() { -    assert (!wlist.empty()); -    const CFGBlock* B = *wlist.begin(); -    wlist.erase(B); +    assert(!BlockQueue.empty()); +    const CFGBlock *B = BlockQueue.back(); +    BlockQueue.pop_back(); +    BlockSet[B] = 0;      return B;    }    /// isEmpty - Return true if the worklist is empty. -  bool isEmpty() const { return wlist.empty(); } +  bool isEmpty() const { return BlockQueue.empty(); }  };  //===----------------------------------------------------------------------===// @@ -188,10 +196,7 @@ private:    /// SolveDataflowEquations - Perform the actual worklist algorithm    ///  to compute dataflow values.    void SolveDataflowEquations(CFG& cfg, bool recordStmtValues) { -    // Enqueue all blocks to ensure the dataflow values are computed -    // for every block.  Not all blocks are guaranteed to reach the exit block. -    for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I) -      WorkList.enqueue(&**I); +    EnqueueBlocksOnWorklist(cfg, AnalysisDirTag());      while (!WorkList.isEmpty()) {        const CFGBlock* B = WorkList.dequeue(); @@ -201,6 +206,22 @@ private:      }    } +  void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::forward_analysis_tag) { +    // Enqueue all blocks to ensure the dataflow values are computed +    // for every block.  Not all blocks are guaranteed to reach the exit block. +    for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I) +      WorkList.enqueue(&**I); +  } + +  void EnqueueBlocksOnWorklist(CFG &cfg, dataflow::backward_analysis_tag) { +    // Enqueue all blocks to ensure the dataflow values are computed +    // for every block.  Not all blocks are guaranteed to reach the exit block. +    // Enqueue in reverse order since that will more likely match with +    // the order they should ideally processed by the dataflow algorithm. +    for (CFG::reverse_iterator I=cfg.rbegin(), E=cfg.rend(); I!=E; ++I) +      WorkList.enqueue(&**I); +  } +    void ProcessMerge(CFG& cfg, const CFGBlock* B) {      ValTy& V = TF.getVal();      TF.SetTopValue(V); diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 3afdaf5b0eb12..453f660c360a3 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -397,13 +397,6 @@ BUILTIN(__sync_fetch_and_xor_4, "ii*i.", "n")  BUILTIN(__sync_fetch_and_xor_8, "LLiLLi*LLi.", "n")  BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLi*LLLi.", "n") -BUILTIN(__sync_fetch_and_nand, "v.", "") -BUILTIN(__sync_fetch_and_nand_1, "cc*c.", "n") -BUILTIN(__sync_fetch_and_nand_2, "ss*s.", "n") -BUILTIN(__sync_fetch_and_nand_4, "ii*i.", "n") -BUILTIN(__sync_fetch_and_nand_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLi*LLLi.", "n") -  BUILTIN(__sync_add_and_fetch, "v.", "")  BUILTIN(__sync_add_and_fetch_1, "cc*c.", "n") @@ -440,14 +433,6 @@ BUILTIN(__sync_xor_and_fetch_4, "ii*i.", "n")  BUILTIN(__sync_xor_and_fetch_8, "LLiLLi*LLi.", "n")  BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLi*LLLi.", "n") -BUILTIN(__sync_nand_and_fetch, "v.", "") -BUILTIN(__sync_nand_and_fetch_1, "cc*c.", "n") -BUILTIN(__sync_nand_and_fetch_2, "ss*s.", "n") -BUILTIN(__sync_nand_and_fetch_4, "ii*i.", "n") -BUILTIN(__sync_nand_and_fetch_8, "LLiLLi*LLi.", "n") -BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLi*LLLi.", "n") - -  BUILTIN(__sync_bool_compare_and_swap, "v.", "")  BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "n")  BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "n") diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 00b076aa1004a..5c75d3799bcbb 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -317,4 +317,12 @@ BUILTIN(__builtin_ia32_crc32qi, "iic", "")  BUILTIN(__builtin_ia32_crc32hi, "iis", "")  BUILTIN(__builtin_ia32_crc32si, "iii", "")  BUILTIN(__builtin_ia32_crc32di, "LLiLLiLLi", "") + +// AES +BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "") +BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLii", "")  #undef BUILTIN diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index 9e643bb3c2c16..c2a4e1364a9eb 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -1,8 +1,8 @@  macro(clang_diag_gen component) -  tablegen(Diagnostic${component}Kinds.inc  -	   -gen-clang-diags-defs -clang-component=${component}) +  tablegen(Diagnostic${component}Kinds.inc +        -gen-clang-diags-defs -clang-component=${component})    add_custom_target(ClangDiagnostic${component} -    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Diagnostic${component}Kinds.inc) +    DEPENDS Diagnostic${component}Kinds.inc)  endmacro(clang_diag_gen)  set(LLVM_TARGET_DEFINITIONS Diagnostic.td) @@ -17,4 +17,4 @@ clang_diag_gen(Sema)  tablegen(DiagnosticGroups.inc           -gen-clang-diag-groups)  add_custom_target(ClangDiagnosticGroups -  DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/DiagnosticGroups.inc) +  DEPENDS DiagnosticGroups.inc) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index d6c8797fc901f..643868506d8f4 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -95,7 +95,7 @@ namespace clang {  /// should also provide full recovery from such errors, such that  /// suppressing the diagnostic output can still result in successful  /// compilation. -class CodeModificationHint { +class FixItHint {  public:    /// \brief Tokens that should be removed to correct the error.    SourceRange RemoveRange; @@ -110,7 +110,7 @@ public:    /// \brief Empty code modification hint, indicating that no code    /// modification is known. -  CodeModificationHint() : RemoveRange(), InsertionLoc() { } +  FixItHint() : RemoveRange(), InsertionLoc() { }    bool isNull() const {      return !RemoveRange.isValid() && !InsertionLoc.isValid(); @@ -118,9 +118,9 @@ public:    /// \brief Create a code modification hint that inserts the given    /// code string at a specific location. -  static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc, -                                              llvm::StringRef Code) { -    CodeModificationHint Hint; +  static FixItHint CreateInsertion(SourceLocation InsertionLoc, +                                   llvm::StringRef Code) { +    FixItHint Hint;      Hint.InsertionLoc = InsertionLoc;      Hint.CodeToInsert = Code;      return Hint; @@ -128,17 +128,17 @@ public:    /// \brief Create a code modification hint that removes the given    /// source range. -  static CodeModificationHint CreateRemoval(SourceRange RemoveRange) { -    CodeModificationHint Hint; +  static FixItHint CreateRemoval(SourceRange RemoveRange) { +    FixItHint Hint;      Hint.RemoveRange = RemoveRange;      return Hint;    }    /// \brief Create a code modification hint that replaces the given    /// source range with the given code string. -  static CodeModificationHint CreateReplacement(SourceRange RemoveRange, -                                                llvm::StringRef Code) { -    CodeModificationHint Hint; +  static FixItHint CreateReplacement(SourceRange RemoveRange, +                                     llvm::StringRef Code) { +    FixItHint Hint;      Hint.RemoveRange = RemoveRange;      Hint.InsertionLoc = RemoveRange.getBegin();      Hint.CodeToInsert = Code; @@ -234,6 +234,18 @@ private:                                    void *Cookie);    void *ArgToStringCookie;    ArgToStringFnTy ArgToStringFn; + +  /// \brief ID of the "delayed" diagnostic, which is a (typically +  /// fatal) diagnostic that had to be delayed because it was found +  /// while emitting another diagnostic. +  unsigned DelayedDiagID; + +  /// \brief First string argument for the delayed diagnostic. +  std::string DelayedDiagArg1; + +  /// \brief Second string argument for the delayed diagnostic. +  std::string DelayedDiagArg2; +  public:    explicit Diagnostic(DiagnosticClient *client = 0);    ~Diagnostic(); @@ -377,6 +389,28 @@ public:    /// the diagnostic, this returns null.    static const char *getWarningOptionForDiag(unsigned DiagID); +  /// \brief Enumeration describing how the the emission of a diagnostic should +  /// be treated when it occurs during C++ template argument deduction. +  enum SFINAEResponse { +    /// \brief The diagnostic should not be reported, but it should cause +    /// template argument deduction to fail. +    /// +    /// The vast majority of errors that occur during template argument  +    /// deduction fall into this category. +    SFINAE_SubstitutionFailure, +     +    /// \brief The diagnostic should be suppressed entirely. +    /// +    /// Warnings generally fall into this category. +    SFINAE_Suppress, +     +    /// \brief The diagnostic should be reported. +    /// +    /// The diagnostic should be reported. Various fatal errors (e.g.,  +    /// template instantiation depth exceeded) fall into this category. +    SFINAE_Report +  }; +      /// \brief Determines whether the given built-in diagnostic ID is    /// for an error that is suppressed if it occurs during C++ template    /// argument deduction. @@ -385,7 +419,7 @@ public:    /// deduction fails but no diagnostic is emitted. Certain classes of    /// errors, such as those errors that involve C++ access control,    /// are not SFINAE errors. -  static bool isBuiltinSFINAEDiag(unsigned DiagID); +  static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID);    /// getDiagnosticLevel - Based on the way the client configured the Diagnostic    /// object, classify the specified diagnostic ID into a Level, consumable by @@ -400,10 +434,41 @@ public:    inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);    inline DiagnosticBuilder Report(unsigned DiagID); +  /// \brief Determine whethere there is already a diagnostic in flight. +  bool isDiagnosticInFlight() const { return CurDiagID != ~0U; } + +  /// \brief Set the "delayed" diagnostic that will be emitted once +  /// the current diagnostic completes. +  /// +  ///  If a diagnostic is already in-flight but the front end must +  ///  report a problem (e.g., with an inconsistent file system +  ///  state), this routine sets a "delayed" diagnostic that will be +  ///  emitted after the current diagnostic completes. This should +  ///  only be used for fatal errors detected at inconvenient +  ///  times. If emitting a delayed diagnostic causes a second delayed +  ///  diagnostic to be introduced, that second delayed diagnostic +  ///  will be ignored. +  /// +  /// \param DiagID The ID of the diagnostic being delayed. +  /// +  /// \param Arg1 A string argument that will be provided to the +  /// diagnostic. A copy of this string will be stored in the +  /// Diagnostic object itself. +  /// +  /// \param Arg2 A string argument that will be provided to the +  /// diagnostic. A copy of this string will be stored in the +  /// Diagnostic object itself. +  void SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1 = "", +                            llvm::StringRef Arg2 = ""); +      /// \brief Clear out the current diagnostic.    void Clear() { CurDiagID = ~0U; }  private: +  /// \brief Report the delayed diagnostic. +  void ReportDelayed(); + +    /// getDiagnosticMappingInfo - Return the mapping info currently set for the    /// specified builtin diagnostic.  This returns the high bit encoding, or zero    /// if the field is completely uninitialized. @@ -454,8 +519,8 @@ private:    /// NumRanges - This is the number of ranges in the DiagRanges array.    unsigned char NumDiagRanges;    /// \brief The number of code modifications hints in the -  /// CodeModificationHints array. -  unsigned char NumCodeModificationHints; +  /// FixItHints array. +  unsigned char NumFixItHints;    /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum    /// values, with one for each argument.  This specifies whether the argument @@ -477,11 +542,11 @@ private:    /// only support 10 ranges, could easily be extended if needed.    SourceRange DiagRanges[10]; -  enum { MaxCodeModificationHints = 3 }; +  enum { MaxFixItHints = 3 }; -  /// CodeModificationHints - If valid, provides a hint with some code +  /// FixItHints - If valid, provides a hint with some code    /// to insert, remove, or modify at a particular position. -  CodeModificationHint CodeModificationHints[MaxCodeModificationHints]; +  FixItHint FixItHints[MaxFixItHints];    /// ProcessDiag - This is the method used to report a diagnostic that is    /// finally fully formed. @@ -508,13 +573,12 @@ private:  /// for example.  class DiagnosticBuilder {    mutable Diagnostic *DiagObj; -  mutable unsigned NumArgs, NumRanges, NumCodeModificationHints; +  mutable unsigned NumArgs, NumRanges, NumFixItHints;    void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT    friend class Diagnostic;    explicit DiagnosticBuilder(Diagnostic *diagObj) -    : DiagObj(diagObj), NumArgs(0), NumRanges(0), -      NumCodeModificationHints(0) {} +    : DiagObj(diagObj), NumArgs(0), NumRanges(0), NumFixItHints(0) {}  public:    /// Copy constructor.  When copied, this "takes" the diagnostic info from the @@ -524,7 +588,7 @@ public:      D.DiagObj = 0;      NumArgs = D.NumArgs;      NumRanges = D.NumRanges; -    NumCodeModificationHints = D.NumCodeModificationHints; +    NumFixItHints = D.NumFixItHints;    }    /// \brief Simple enumeration value used to give a name to the @@ -534,7 +598,7 @@ public:    /// \brief Create an empty DiagnosticBuilder object that represents    /// no actual diagnostic.    explicit DiagnosticBuilder(SuppressKind) -    : DiagObj(0), NumArgs(0), NumRanges(0), NumCodeModificationHints(0) { } +    : DiagObj(0), NumArgs(0), NumRanges(0), NumFixItHints(0) { }    /// \brief Force the diagnostic builder to emit the diagnostic now.    /// @@ -543,29 +607,7 @@ public:    ///    /// \returns true if a diagnostic was emitted, false if the    /// diagnostic was suppressed. -  bool Emit() { -    // If DiagObj is null, then its soul was stolen by the copy ctor -    // or the user called Emit(). -    if (DiagObj == 0) return false; - -    // When emitting diagnostics, we set the final argument count into -    // the Diagnostic object. -    DiagObj->NumDiagArgs = NumArgs; -    DiagObj->NumDiagRanges = NumRanges; -    DiagObj->NumCodeModificationHints = NumCodeModificationHints; - -    // Process the diagnostic, sending the accumulated information to the -    // DiagnosticClient. -    bool Emitted = DiagObj->ProcessDiag(); - -    // Clear out the current diagnostic object. -    DiagObj->Clear(); - -    // This diagnostic is dead. -    DiagObj = 0; - -    return Emitted; -  } +  bool Emit();    /// Destructor - The dtor emits the diagnostic if it hasn't already    /// been emitted. @@ -605,14 +647,14 @@ public:        DiagObj->DiagRanges[NumRanges++] = R;    } -  void AddCodeModificationHint(const CodeModificationHint &Hint) const { +  void AddFixItHint(const FixItHint &Hint) const {      if (Hint.isNull())        return; -    assert(NumCodeModificationHints < Diagnostic::MaxCodeModificationHints && -           "Too many code modification hints!"); +    assert(NumFixItHints < Diagnostic::MaxFixItHints && +           "Too many fix-it hints!");      if (DiagObj) -      DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint; +      DiagObj->FixItHints[NumFixItHints++] = Hint;    }  }; @@ -673,8 +715,8 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,  }  inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, -                                           const CodeModificationHint &Hint) { -  DB.AddCodeModificationHint(Hint); +                                           const FixItHint &Hint) { +  DB.AddFixItHint(Hint);    return DB;  } @@ -770,17 +812,17 @@ public:      return DiagObj->DiagRanges[Idx];    } -  unsigned getNumCodeModificationHints() const { -    return DiagObj->NumCodeModificationHints; +  unsigned getNumFixItHints() const { +    return DiagObj->NumFixItHints;    } -  const CodeModificationHint &getCodeModificationHint(unsigned Idx) const { -    return DiagObj->CodeModificationHints[Idx]; +  const FixItHint &getFixItHint(unsigned Idx) const { +    return DiagObj->FixItHints[Idx];    } -  const CodeModificationHint *getCodeModificationHints() const { -    return DiagObj->NumCodeModificationHints? -             &DiagObj->CodeModificationHints[0] : 0; +  const FixItHint *getFixItHints() const { +    return DiagObj->NumFixItHints? +             &DiagObj->FixItHints[0] : 0;    }    /// FormatDiagnostic - Format this diagnostic into a string, substituting the @@ -803,7 +845,7 @@ class StoredDiagnostic {    FullSourceLoc Loc;    std::string Message;    std::vector<SourceRange> Ranges; -  std::vector<CodeModificationHint> FixIts; +  std::vector<FixItHint> FixIts;  public:    StoredDiagnostic(); @@ -823,7 +865,7 @@ public:    range_iterator range_end() const { return Ranges.end(); }    unsigned range_size() const { return Ranges.size(); } -  typedef std::vector<CodeModificationHint>::const_iterator fixit_iterator; +  typedef std::vector<FixItHint>::const_iterator fixit_iterator;    fixit_iterator fixit_begin() const { return FixIts.begin(); }    fixit_iterator fixit_end() const { return FixIts.end(); }    unsigned fixit_size() const { return FixIts.size(); } diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index 3a28282d55220..2e0b4bad6b5be 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -22,7 +22,7 @@ def err_fe_stdout_binary : Error<"unable to change standard output to binary">,  def err_fe_stderr_binary : Error<"unable to change standard error to binary">,    DefaultFatal;  def err_fe_dependency_file_requires_MT : Error< -    "-dependency-file requires at least one -MT option">; +    "-dependency-file requires at least one -MT or -MQ option">;  def err_fe_incompatible_options : Error<      "'%0' cannot be used with '%1'">, DefaultFatal;  def err_fe_no_fixit_and_codegen : Error< @@ -57,6 +57,9 @@ def err_fe_pch_malformed_block : Error<      "malformed block record in PCH file: '%0'">, DefaultFatal;  def err_fe_pch_error_at_end_block : Error<      "error at end of module block in PCH file: '%0'">, DefaultFatal; +def err_fe_pch_file_modified : Error< +    "file '%0' has been modified since the precompiled header was built">, +    DefaultFatal;  def err_fe_unable_to_open_output : Error<      "unable to open output file '%0': '%1'">;  def err_fe_unable_to_open_logfile : Error< diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 203ab1eed5473..b0c016bbfd28f 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -31,6 +31,7 @@ def : DiagGroup<"char-align">;  def Comment : DiagGroup<"comment">;  def : DiagGroup<"ctor-dtor-privacy">;  def : DiagGroup<"declaration-after-statement">; +def GNUDesignator : DiagGroup<"gnu-designator">;  def Deprecated : DiagGroup<"deprecated">;  def : DiagGroup<"disabled-optimization">;  def : DiagGroup<"discard-qual">; @@ -115,6 +116,7 @@ def UnusedVariable : DiagGroup<"unused-variable">;  def ReadOnlySetterAttrs : DiagGroup<"readonly-setter-attrs">;  def Reorder : DiagGroup<"reorder">;  def UndeclaredSelector : DiagGroup<"undeclared-selector">; +def Protocol : DiagGroup<"protocol">;  def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;  def : DiagGroup<"variadic-macros">;  def VariadicMacros : DiagGroup<"variadic-macros">; @@ -185,3 +187,6 @@ def : DiagGroup<"comments", [Comment]>;         // -Wcomments = -Wcomment  // but which aren't on by default in GCC.  def NonGCC : DiagGroup<"non-gcc",      [SignCompare, Conversion, LiteralRange]>; + +// A warning group for warnings about GCC extensions. +def GNU : DiagGroup<"gnu", [GNUDesignator]>; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 9d001d48cc2a2..facf15f52e85e 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -50,22 +50,26 @@ def ext_enumerator_list_comma : Extension<    "feature">;  def ext_gnu_indirect_goto : Extension< -  "use of GNU indirect-goto extension">; +  "use of GNU indirect-goto extension">, InGroup<GNU>;  def ext_gnu_address_of_label : Extension< -  "use of GNU address-of-label extension">; +  "use of GNU address-of-label extension">, InGroup<GNU>;  def ext_gnu_statement_expr : Extension< -  "use of GNU statement expression extension">; +  "use of GNU statement expression extension">, InGroup<GNU>;  def ext_gnu_conditional_expr : Extension< -  "use of GNU ?: expression extension, eliding middle term">; +  "use of GNU ?: expression extension, eliding middle term">, InGroup<GNU>;  def ext_gnu_empty_initializer : Extension< -  "use of GNU empty initializer extension">; -def ext_gnu_array_range : Extension<"use of GNU array range extension">; +  "use of GNU empty initializer extension">, InGroup<GNU>; +def ext_gnu_array_range : Extension<"use of GNU array range extension">,  +  InGroup<GNUDesignator>;  def ext_gnu_missing_equal_designator : ExtWarn< -  "use of GNU 'missing =' extension in designator">; +  "use of GNU 'missing =' extension in designator">,  +  InGroup<GNUDesignator>;  def err_expected_equal_designator : Error<"expected '=' or another designator">;  def ext_gnu_old_style_field_designator : ExtWarn< -  "use of GNU old-style field designator extension">; -def ext_gnu_case_range : Extension<"use of GNU case range extension">; +  "use of GNU old-style field designator extension">,  +  InGroup<GNUDesignator>; +def ext_gnu_case_range : Extension<"use of GNU case range extension">, +  InGroup<GNU>;  // Generic errors.  def err_parse_error : Error<"parse error">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 752be5df7a126..be00972dac5c1 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -68,7 +68,7 @@ def err_designator_into_flexible_array_member : Error<  def note_flexible_array_member : Note<    "initialized flexible array member %0 is here">;  def ext_flexible_array_init : Extension< -  "flexible array initialization is a GNU extension">; +  "flexible array initialization is a GNU extension">, InGroup<GNU>;  // Declarations.  def ext_vla : Extension< @@ -268,8 +268,6 @@ def err_duplicate_ivar_declaration : Error<    "instance variable is already declared">;  def warn_on_superclass_use : Warning<    "class implementation may not have super class">; -def err_non_private_ivar_declaration : Error< -  "only private ivars may be declared in implementation">;  def err_conflicting_ivar_bitwidth : Error<    "instance variable %0 has conflicting bit-field width">;  def err_conflicting_ivar_name : Error< @@ -277,7 +275,9 @@ def err_conflicting_ivar_name : Error<  def err_inconsistant_ivar_count : Error<    "inconsistent number of instance variables specified">;  def warn_incomplete_impl : Warning<"incomplete implementation">; -def warn_undef_method_impl : Warning<"method definition for %0 not found">; +def note_undef_method_impl : Note<"method definition for %0 not found">; +def note_required_for_protocol_at :  +  Note<"required for direct or indirect protocol %0">;  def warn_conflicting_ret_types : Warning<    "conflicting return type in implementation of %0: %1 vs %2">; @@ -350,7 +350,7 @@ def error_synthesized_ivar_yet_not_supported : Error<    " (need to declare %0 explicitly)">;  def error_property_ivar_type : Error< -  "type of property %0 does not match type of ivar %1">; +  "type of property %0 (%1) does not match type of ivar %2 (%3)">;  def error_ivar_in_superclass_use : Error<    "property %0 attempting to use ivar %1 declared in super class %2">;  def error_weak_property : Error< @@ -367,6 +367,8 @@ def warn_objc_property_attr_mutually_exclusive : Warning<    InGroup<ReadOnlySetterAttrs>, DefaultIgnore;  def warn_undeclared_selector : Warning<    "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore; +def warn_unimplemented_protocol_method : Warning< +  "method in protocol not implemented">, InGroup<Protocol>;  // C++ declarations  def err_static_assert_expression_is_not_constant : Error< @@ -393,7 +395,11 @@ def err_abstract_type_in_decl : Error<    "%select{return|parameter|variable|field}0 type %1 is an abstract class">;  def err_allocation_of_abstract_type : Error<    "allocation of an object of abstract type %0">; -   + +def err_multiple_final_overriders : Error< +  "virtual function %q0 has more than one final overrider in %1">;  +def note_final_overrider : Note<"final overrider of %q0 in %1">; +  def err_type_defined_in_type_specifier : Error<    "%0 can not be defined in a type specifier">;  def err_type_defined_in_result_type : Error< @@ -432,6 +438,8 @@ def err_incompatible_exception_specs : Error<    "target exception specification is not superset of source">;  def err_deep_exception_specs_differ : Error<    "exception specifications of %select{return|argument}0 types differ">; +def warn_missing_exception_specification : Warning< +  "%0 is missing exception specification '%1'">;  // C++ access checking  def err_class_redeclared_with_different_access : Error< @@ -532,6 +540,7 @@ def err_implicit_object_parameter_init : Error<    "of type %1">;  def note_field_decl : Note<"member is declared here">; +def note_ivar_decl : Note<"ivar is declared here">;  def note_bitfield_decl : Note<"bit-field is declared here">;  def note_previous_decl : Note<"%0 declared here">;  def note_member_synthesized_at : Note< @@ -776,8 +785,9 @@ def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<  def warn_attribute_ignored : Warning<"%0 attribute ignored">;  def warn_attribute_precede_definition : Warning<    "attribute declaration must precede definition">; -def warn_attribute_void_function : Warning< -  "attribute %0 cannot be applied to functions without return value">; +def warn_attribute_void_function_method : Warning< +  "attribute %0 cannot be applied to " +  "%select{functions|Objective-C method}1 without return value">;  def warn_attribute_weak_on_field : Warning<    "__weak attribute cannot be specified on a field declaration">;  def warn_attribute_weak_on_local : Warning< @@ -1199,26 +1209,40 @@ def err_template_arg_not_integral_or_enumeral : Error<  def err_template_arg_not_ice : Error<    "non-type template argument of type %0 is not an integral constant "    "expression">; +def err_deduced_non_type_template_arg_type_mismatch : Error< +  "deduced non-type template argument does not have the same type as the " +  "its corresponding template parameter (%0 vs %1)">;  def err_template_arg_not_convertible : Error<    "non-type template argument of type %0 cannot be converted to a value "    "of type %1">; -def err_template_arg_negative : Error< -  "non-type template argument provides negative value '%0' for unsigned " -  "template parameter of type %1">; -def err_template_arg_too_large : Error< -  "non-type template argument value '%0' is too large for template " -  "parameter of type %1">; +def warn_template_arg_negative : Warning< +  "non-type template argument with value '%0' converted to '%1' for unsigned " +  "template parameter of type %2">; +def warn_template_arg_too_large : Warning< +  "non-type template argument value '%0' truncated to '%1' for " +  "template parameter of type %2">;  def err_template_arg_no_ref_bind : Error<    "non-type template parameter of reference type %0 cannot bind to template "    "argument of type %1">;  def err_template_arg_ref_bind_ignores_quals : Error<    "reference binding of non-type template parameter of type %0 to template "    "argument of type %1 ignores qualifiers">; +def err_template_arg_unresolved_overloaded_function : Error< +  "overloaded function cannot be resolved to a non-type template parameter of " +  "type %0">;  def err_template_arg_not_decl_ref : Error<    "non-type template argument does not refer to any declaration">;  def err_template_arg_not_object_or_func_form : Error<    "non-type template argument does not directly refer to an object or "    "function">; +def err_template_arg_not_address_of : Error< +  "non-type template argument for template parameter of pointer type %0 must " +  "have its address taken">; +def err_template_arg_address_of_non_pointer : Error< +  "address taken in non-type template argument for template parameter of " +  "reference type %0">; +def err_template_arg_reference_var : Error< +  "non-type template argument of reference type %0 is not an object">;  def err_template_arg_field : Error<    "non-type template argument refers to non-static data member %0">;  def err_template_arg_method : Error< @@ -1251,6 +1275,8 @@ def err_template_spec_decl_function_scope : Error<    "explicit specialization of %0 in function scope">;  def err_template_spec_decl_class_scope : Error<    "explicit specialization of %0 in class scope">; +def err_template_spec_decl_friend : Error< +  "cannot declare an explicit specialization in a friend">;  def err_template_spec_decl_out_of_scope_global : Error<    "%select{class template|class template partial|function template|member "    "function|static data member|member class}0 specialization of %1 must " @@ -1372,13 +1398,13 @@ def note_default_function_arg_instantiation_here : Note<    "for '%0' required here">;  def note_explicit_template_arg_substitution_here : Note<    "while substituting explicitly-specified template arguments into function " -  "template %f, here">; +  "template %0 %1">;  def note_function_template_deduction_instantiation_here : Note< -  "while substituting deduced template arguments into function template %0, " -  "here">; +  "while substituting deduced template arguments into function template %0 " +  "%1">;  def note_partial_spec_deduct_instantiation_here : Note<    "during template argument deduction for class template partial " -  "specialization %0, here">; +  "specialization %0 %1">;  def note_prior_template_arg_substitution : Note<    "while substituting prior template arguments into %select{non-type|template}0"    " template parameter%1 %2">; @@ -1537,7 +1563,8 @@ def err_forward_ref_enum : Error<    "ISO C++ forbids forward references to 'enum' types">;  def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;  def err_duplicate_member : Error<"duplicate member %0">; -def err_misplaced_ivar : Error<"ivars may not be placed in categories">; +def err_misplaced_ivar : Error< +  "ivars may not be placed in %select{categories|class extension}0">;  def ext_enum_value_not_int : Extension<    "ISO C restricts enumerator values to range of 'int' (%0 is too "    "%select{small|large}1)">; @@ -1575,6 +1602,8 @@ def err_typecheck_invalid_restrict_invalid_pointee : Error<    "pointer to function type %0 may not be 'restrict' qualified">;  def ext_typecheck_zero_array_size : Extension<    "zero size arrays are an extension">; +def err_typecheck_zero_array_size : Error< +  "zero-length arrays are not permitted in C++">;  def err_at_least_one_initializer_needed_to_size_array : Error<    "at least one initializer value required to size array">;  def err_array_size_non_int : Error<"size of array has non-integer type %0">; @@ -1664,7 +1693,7 @@ def err_field_declared_as_function : Error<"field %0 declared as a function">;  def err_field_incomplete : Error<"field has incomplete type %0">;  def ext_variable_sized_type_in_struct : ExtWarn<    "field %0 with variable sized type %1 not at the end of a struct or class is" -  " a GNU extension">; +  " a GNU extension">, InGroup<GNU>;  def err_flexible_array_empty_struct : Error<    "flexible array %0 not allowed in otherwise empty struct">; @@ -2164,7 +2193,7 @@ def err_invalid_declarator_global_scope : Error<  def err_invalid_declarator_in_function : Error<    "definition or redeclaration of %0 not allowed inside a function">;  def err_not_tag_in_scope : Error< -  "%0 does not name a tag member in the specified scope">; +  "no %select{struct|union|class|enum}0 named %1 in %2">;  def err_cannot_form_pointer_to_member_of_reference_type : Error<    "cannot form a pointer-to-member to member %0 of reference type %1">; @@ -2322,7 +2351,8 @@ def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn<  def err_typecheck_choose_expr_requires_constant : Error<    "'__builtin_choose_expr' requires a constant expression">;  def ext_typecheck_expression_not_constant_but_accepted : Extension< -  "expression is not a constant, but is accepted as one by GNU extensions">; +  "expression is not a constant, but is accepted as one by GNU extensions">,  +  InGroup<GNU>;  def warn_unused_expr : Warning<"expression result unused">,    InGroup<UnusedValue>;  def warn_unused_property_expr : Warning< @@ -2334,6 +2364,7 @@ def warn_unused_call : Warning<  def err_incomplete_type_used_in_type_trait_expr : Error<    "incomplete type %0 used in type trait expression">; +def err_expected_ident_or_lparen : Error<"expected identifier or '('">;  // inline asm.  def err_asm_wide_character : Error<"wide string is invalid in 'asm'">; @@ -2413,9 +2444,9 @@ def err_in_class_initializer_non_constant : Error<  // C++ anonymous unions and GNU anonymous structs/unions  def ext_anonymous_union : Extension< -  "anonymous unions are a GNU extension in C">; +  "anonymous unions are a GNU extension in C">, InGroup<GNU>;  def ext_anonymous_struct : Extension< -  "anonymous structs are a GNU extension">; +  "anonymous structs are a GNU extension">, InGroup<GNU>;  def err_anonymous_union_not_static : Error<    "anonymous unions at namespace or global scope must be declared 'static'">;  def err_anonymous_union_with_storage_spec : Error< @@ -2584,6 +2615,9 @@ def warn_printf_missing_format_string : Warning<  def warn_printf_conversion_argument_type_mismatch : Warning<    "conversion specifies type %0 but the argument has type %1">,    InGroup<Format>; +def warn_printf_positional_arg_exceeds_data_args : Warning < +  "data argument position '%0' exceeds the number of data arguments (%1)">, +  InGroup<Format>;  def warn_printf_zero_positional_specifier : Warning<    "position arguments in format strings start counting at 1 (not 0)">,    InGroup<Format>; diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index fb861dcf934d2..89fae87ae8ef9 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -15,19 +15,18 @@  #ifndef LLVM_CLANG_PARTIALDIAGNOSTIC_H  #define LLVM_CLANG_PARTIALDIAGNOSTIC_H -#include "clang/AST/Type.h"  #include "clang/Basic/Diagnostic.h"  #include "clang/Basic/SourceLocation.h"  #include "llvm/ADT/STLExtras.h" +#include "llvm/System/DataTypes.h" +#include <cassert>  namespace clang { -class DeclarationName; -    class PartialDiagnostic { +public:    struct Storage { -    Storage() : NumDiagArgs(0), NumDiagRanges(0), NumCodeModificationHints(0) { -    } +    Storage() : NumDiagArgs(0), NumDiagRanges(0), NumFixItHints(0) { }      enum {          /// MaxArguments - The maximum number of arguments we can hold. We  @@ -44,8 +43,8 @@ class PartialDiagnostic {      unsigned char NumDiagRanges;      /// \brief The number of code modifications hints in the -    /// CodeModificationHints array. -    unsigned char NumCodeModificationHints; +    /// FixItHints array. +    unsigned char NumFixItHints;      /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum      /// values, with one for each argument.  This specifies whether the argument @@ -62,13 +61,49 @@ class PartialDiagnostic {      /// only support 10 ranges, could easily be extended if needed.      SourceRange DiagRanges[10]; -    enum { MaxCodeModificationHints = 3 }; +    enum { MaxFixItHints = 3 }; -    /// CodeModificationHints - If valid, provides a hint with some code +    /// FixItHints - If valid, provides a hint with some code      /// to insert, remove, or modify at a particular position. -    CodeModificationHint CodeModificationHints[MaxCodeModificationHints];     +    FixItHint FixItHints[MaxFixItHints];        }; +  /// \brief An allocator for Storage objects, which uses a small cache to  +  /// objects, used to reduce malloc()/free() traffic for partial diagnostics. +  class StorageAllocator { +    static const unsigned NumCached = 4; +    Storage Cached[NumCached]; +    Storage *FreeList[NumCached]; +    unsigned NumFreeListEntries; +     +  public: +    StorageAllocator(); +    ~StorageAllocator(); +     +    /// \brief Allocate new storage. +    Storage *Allocate() { +      if (NumFreeListEntries == 0) +        return new Storage; +       +      Storage *Result = FreeList[--NumFreeListEntries]; +      Result->NumDiagArgs = 0; +      Result->NumDiagRanges = 0; +      Result->NumFixItHints = 0; +      return Result; +    } +     +    /// \brief Free the given storage object. +    void Deallocate(Storage *S) { +      if (S >= Cached && S <= Cached + NumCached) { +        FreeList[NumFreeListEntries++] = S; +        return; +      } +       +      delete S; +    } +  }; +   +private:    // NOTE: Sema assumes that PartialDiagnostic is location-invariant    // in the sense that its bits can be safely memcpy'ed and destructed    // in the new location. @@ -76,22 +111,40 @@ class PartialDiagnostic {    /// DiagID - The diagnostic ID.    mutable unsigned DiagID; -  /// DiagStorare - Storge for args and ranges. +  /// DiagStorage - Storage for args and ranges.    mutable Storage *DiagStorage; -  void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const { -    if (!DiagStorage) +  /// \brief Allocator used to allocate storage for this diagnostic. +  StorageAllocator *Allocator; +   +  /// \brief Retrieve storage for this particular diagnostic. +  Storage *getStorage() const { +    if (DiagStorage) +      return DiagStorage; +     +    if (Allocator) +      DiagStorage = Allocator->Allocate(); +    else { +      assert(Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0)));        DiagStorage = new Storage; +    } +    return DiagStorage; +  } +   +  void freeStorage() {  +    if (!DiagStorage) +      return; -    assert(DiagStorage->NumDiagArgs < Storage::MaxArguments && -           "Too many arguments to diagnostic!"); -    DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind; -    DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; +    if (Allocator) +      Allocator->Deallocate(DiagStorage); +    else if (Allocator != reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) +      delete DiagStorage; +    DiagStorage = 0;    } - +      void AddSourceRange(const SourceRange &R) const {      if (!DiagStorage) -      DiagStorage = new Storage; +      DiagStorage = getStorage();      assert(DiagStorage->NumDiagRanges <              llvm::array_lengthof(DiagStorage->DiagRanges) && @@ -99,53 +152,70 @@ class PartialDiagnostic {      DiagStorage->DiagRanges[DiagStorage->NumDiagRanges++] = R;    }   -  void AddCodeModificationHint(const CodeModificationHint &Hint) const { +  void AddFixItHint(const FixItHint &Hint) const {      if (Hint.isNull())        return;      if (!DiagStorage) -      DiagStorage = new Storage; +      DiagStorage = getStorage(); -    assert(DiagStorage->NumCodeModificationHints <  -             Storage::MaxCodeModificationHints && +    assert(DiagStorage->NumFixItHints < Storage::MaxFixItHints &&             "Too many code modification hints!"); -    DiagStorage->CodeModificationHints[DiagStorage->NumCodeModificationHints++] +    DiagStorage->FixItHints[DiagStorage->NumFixItHints++]        = Hint;    }  public: -  PartialDiagnostic(unsigned DiagID) -    : DiagID(DiagID), DiagStorage(0) { } - +  PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) +    : DiagID(DiagID), DiagStorage(0), Allocator(&Allocator) { } +      PartialDiagnostic(const PartialDiagnostic &Other)  -    : DiagID(Other.DiagID), DiagStorage(0)  +    : DiagID(Other.DiagID), DiagStorage(0), Allocator(Other.Allocator)    { -    if (Other.DiagStorage) -      DiagStorage = new Storage(*Other.DiagStorage); +    if (Other.DiagStorage) { +      DiagStorage = getStorage(); +      *DiagStorage = *Other.DiagStorage; +    }    } +  PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage)  +    : DiagID(Other.DiagID), DiagStorage(DiagStorage),  +      Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) +  { +    if (Other.DiagStorage) +      *this->DiagStorage = *Other.DiagStorage; +  } +      PartialDiagnostic &operator=(const PartialDiagnostic &Other) {      DiagID = Other.DiagID;      if (Other.DiagStorage) { -      if (DiagStorage) -        *DiagStorage = *Other.DiagStorage; -      else -        DiagStorage = new Storage(*Other.DiagStorage); +      if (!DiagStorage) +        DiagStorage = getStorage(); +       +      *DiagStorage = *Other.DiagStorage;      } else { -      delete DiagStorage; -      DiagStorage = 0; +      freeStorage();      }      return *this;    }    ~PartialDiagnostic() { -    delete DiagStorage; +    freeStorage();    } -    unsigned getDiagID() const { return DiagID; } +  void AddTaggedVal(intptr_t V, Diagnostic::ArgumentKind Kind) const { +    if (!DiagStorage) +      DiagStorage = getStorage(); + +    assert(DiagStorage->NumDiagArgs < Storage::MaxArguments && +           "Too many arguments to diagnostic!"); +    DiagStorage->DiagArgumentsKind[DiagStorage->NumDiagArgs] = Kind; +    DiagStorage->DiagArgumentsVal[DiagStorage->NumDiagArgs++] = V; +  } +    void Emit(const DiagnosticBuilder &DB) const {      if (!DiagStorage)        return; @@ -161,17 +231,19 @@ public:        DB.AddSourceRange(DiagStorage->DiagRanges[i]);      // Add all code modification hints -    for (unsigned i = 0, e = DiagStorage->NumCodeModificationHints; i != e; ++i) -      DB.AddCodeModificationHint(DiagStorage->CodeModificationHints[i]); +    for (unsigned i = 0, e = DiagStorage->NumFixItHints; i != e; ++i) +      DB.AddFixItHint(DiagStorage->FixItHints[i]);    } -  friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, -                                             QualType T) { -    PD.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()), -                    Diagnostic::ak_qualtype); -    return PD; +  /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID +  /// and removing all of its arguments, ranges, and fix-it hints. +  void Reset(unsigned DiagID = 0) { +    this->DiagID = DiagID; +    freeStorage();    } - +   +  bool hasStorage() const { return DiagStorage != 0; } +      friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,                                               unsigned I) {      PD.AddTaggedVal(I, Diagnostic::ak_uint); @@ -197,20 +269,13 @@ public:    }    friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, -                                             DeclarationName N); -   -  friend const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, -                                             const CodeModificationHint &Hint) { -    PD.AddCodeModificationHint(Hint); +                                             const FixItHint &Hint) { +    PD.AddFixItHint(Hint);      return PD;    }  }; -inline PartialDiagnostic PDiag(unsigned DiagID = 0) { -  return PartialDiagnostic(DiagID); -} -  inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,                                             const PartialDiagnostic &PD) {    PD.Emit(DB); @@ -219,4 +284,4 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,  }  // end namespace clang -#endif  +#endif diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index f7ea331e1cc7a..555e6f5a919a1 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -28,7 +28,6 @@ namespace llvm {  namespace clang {  class SourceManager; -class FileEntry;  /// FileID - This is an opaque identifier used by SourceManager which refers to  /// a source file (MemoryBuffer) along with its #include path and #line data. diff --git a/include/clang/Checker/BugReporter/BugReporter.h b/include/clang/Checker/BugReporter/BugReporter.h index 2c15f2a405760..6170342926385 100644 --- a/include/clang/Checker/BugReporter/BugReporter.h +++ b/include/clang/Checker/BugReporter/BugReporter.h @@ -15,17 +15,12 @@  #ifndef LLVM_CLANG_ANALYSIS_BUGREPORTER  #define LLVM_CLANG_ANALYSIS_BUGREPORTER -#include "clang/Basic/Diagnostic.h"  #include "clang/Basic/SourceLocation.h" -#include "clang/Checker/BugReporter/BugType.h" -#include "clang/Checker/PathSensitive/ExplodedGraph.h"  #include "clang/Checker/PathSensitive/GRState.h"  #include "llvm/ADT/FoldingSet.h"  #include "llvm/ADT/ImmutableList.h"  #include "llvm/ADT/ImmutableSet.h" -#include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallString.h"  #include <list>  namespace clang { @@ -35,6 +30,8 @@ class PathDiagnosticPiece;  class PathDiagnosticClient;  class ASTContext;  class Diagnostic; +class ExplodedNode; +class ExplodedGraph;  class BugReporter;  class BugReporterContext;  class GRExprEngine; diff --git a/include/clang/Checker/BugReporter/BugType.h b/include/clang/Checker/BugReporter/BugType.h index 4f1523a5440d1..afc07c89e86f8 100644 --- a/include/clang/Checker/BugReporter/BugType.h +++ b/include/clang/Checker/BugReporter/BugType.h @@ -14,15 +14,12 @@  #ifndef LLVM_CLANG_ANALYSIS_BUGTYPE  #define LLVM_CLANG_ANALYSIS_BUGTYPE -#include <llvm/ADT/FoldingSet.h> +#include "clang/Checker/BugReporter/BugReporter.h" +#include "llvm/ADT/FoldingSet.h"  #include <string>  namespace clang { -class BugReportEquivClass; -class BugReporter; -class BuiltinBugReport; -class BugReporterContext;  class ExplodedNode;  class GRExprEngine; diff --git a/include/clang/Checker/BugReporter/PathDiagnostic.h b/include/clang/Checker/BugReporter/PathDiagnostic.h index d380c45480cb4..24c75ce7b228f 100644 --- a/include/clang/Checker/BugReporter/PathDiagnostic.h +++ b/include/clang/Checker/BugReporter/PathDiagnostic.h @@ -168,7 +168,7 @@ public:  private:    const std::string str; -  std::vector<CodeModificationHint> CodeModificationHints; +  std::vector<FixItHint> FixItHints;    const Kind kind;    const DisplayHint Hint;    std::vector<SourceRange> ranges; @@ -203,8 +203,8 @@ public:      ranges.push_back(SourceRange(B,E));    } -  void addCodeModificationHint(const CodeModificationHint& Hint) { -    CodeModificationHints.push_back(Hint); +  void addFixItHint(const FixItHint& Hint) { +    FixItHints.push_back(Hint);    }    typedef const SourceRange* range_iterator; @@ -217,15 +217,15 @@ public:      return ranges_begin() + ranges.size();    } -  typedef const CodeModificationHint *code_modifications_iterator; +  typedef const FixItHint *fixit_iterator; -  code_modifications_iterator code_modifications_begin() const { -    return CodeModificationHints.empty()? 0 : &CodeModificationHints[0]; +  fixit_iterator fixit_begin() const { +    return FixItHints.empty()? 0 : &FixItHints[0];    } -  code_modifications_iterator code_modifications_end() const { -    return CodeModificationHints.empty()? 0 -                   : &CodeModificationHints[0] + CodeModificationHints.size(); +  fixit_iterator fixit_end() const { +    return FixItHints.empty()? 0 +                   : &FixItHints[0] + FixItHints.size();    }    static inline bool classof(const PathDiagnosticPiece* P) { diff --git a/include/clang/Checker/DomainSpecific/CocoaConventions.h b/include/clang/Checker/DomainSpecific/CocoaConventions.h index ee3d648b86081..4bbdab0e7fe1b 100644 --- a/include/clang/Checker/DomainSpecific/CocoaConventions.h +++ b/include/clang/Checker/DomainSpecific/CocoaConventions.h @@ -14,7 +14,6 @@  #ifndef LLVM_CLANG_CHECKER_DS_COCOA  #define LLVM_CLANG_CHECKER_DS_COCOA -#include "clang/Basic/IdentifierTable.h"  #include "clang/AST/Type.h"  namespace clang { diff --git a/include/clang/Checker/PathSensitive/BasicValueFactory.h b/include/clang/Checker/PathSensitive/BasicValueFactory.h index 2f0b6c2a0348a..59dd9190d25e7 100644 --- a/include/clang/Checker/PathSensitive/BasicValueFactory.h +++ b/include/clang/Checker/PathSensitive/BasicValueFactory.h @@ -16,7 +16,6 @@  #ifndef LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H  #define LLVM_CLANG_ANALYSIS_BASICVALUEFACTORY_H -#include "clang/Checker/PathSensitive/SymbolManager.h"  #include "clang/Checker/PathSensitive/SVals.h"  #include "clang/AST/ASTContext.h"  #include "llvm/ADT/FoldingSet.h" diff --git a/include/clang/Checker/PathSensitive/Checker.h b/include/clang/Checker/PathSensitive/Checker.h index 2401a72741b2b..8cb9cc8337c6a 100644 --- a/include/clang/Checker/PathSensitive/Checker.h +++ b/include/clang/Checker/PathSensitive/Checker.h @@ -14,21 +14,15 @@  #ifndef LLVM_CLANG_ANALYSIS_CHECKER  #define LLVM_CLANG_ANALYSIS_CHECKER +  #include "clang/Analysis/Support/SaveAndRestore.h" -#include "clang/Checker/PathSensitive/GRCoreEngine.h" -#include "clang/Checker/PathSensitive/GRState.h"  #include "clang/Checker/PathSensitive/GRExprEngine.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/ExprObjC.h" -#include "clang/AST/StmtCXX.h" -#include "clang/AST/StmtObjC.h"  //===----------------------------------------------------------------------===//  // Checker interface.  //===----------------------------------------------------------------------===//  namespace clang { -  class GRExprEngine;  class CheckerContext {    ExplodedNodeSet &Dst; diff --git a/include/clang/Checker/PathSensitive/Environment.h b/include/clang/Checker/PathSensitive/Environment.h index 6051654f4855f..b9bbebc652f24 100644 --- a/include/clang/Checker/PathSensitive/Environment.h +++ b/include/clang/Checker/PathSensitive/Environment.h @@ -18,11 +18,8 @@  // typedefs.  #include "clang/Checker/PathSensitive/Store.h" -#include "llvm/ADT/ImmutableMap.h" -#include "llvm/ADT/SmallVector.h"  #include "clang/Checker/PathSensitive/SVals.h" -#include "llvm/Support/Allocator.h" -#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableMap.h"  namespace clang { diff --git a/include/clang/Checker/PathSensitive/ExplodedGraph.h b/include/clang/Checker/PathSensitive/ExplodedGraph.h index d6c4436c594c3..c09c89312e106 100644 --- a/include/clang/Checker/PathSensitive/ExplodedGraph.h +++ b/include/clang/Checker/PathSensitive/ExplodedGraph.h @@ -9,6 +9,10 @@  //  //  This file defines the template classes ExplodedNode and ExplodedGraph,  //  which represent a path-sensitive, intra-procedural "exploded graph." +//  See "Precise interprocedural dataflow analysis via graph reachability" +//  by Reps, Horwitz, and Sagiv +//  (http://portal.acm.org/citation.cfm?id=199462) for the definition of an +//  exploded graph.  //  //===----------------------------------------------------------------------===// diff --git a/include/clang/Checker/PathSensitive/GRBlockCounter.h b/include/clang/Checker/PathSensitive/GRBlockCounter.h index 67ed9532db02b..b7d0e8ae0c71d 100644 --- a/include/clang/Checker/PathSensitive/GRBlockCounter.h +++ b/include/clang/Checker/PathSensitive/GRBlockCounter.h @@ -22,6 +22,8 @@ namespace llvm {  namespace clang { +class StackFrameContext; +  class GRBlockCounter {    void* Data; @@ -30,7 +32,8 @@ class GRBlockCounter {  public:    GRBlockCounter() : Data(0) {} -  unsigned getNumVisited(unsigned BlockID) const; +  unsigned getNumVisited(const StackFrameContext *CallSite,  +                         unsigned BlockID) const;    class Factory {      void* F; @@ -39,7 +42,9 @@ public:      ~Factory();      GRBlockCounter GetEmptyCounter(); -    GRBlockCounter IncrementCount(GRBlockCounter BC, unsigned BlockID); +    GRBlockCounter IncrementCount(GRBlockCounter BC,  +                                  const StackFrameContext *CallSite, +                                  unsigned BlockID);    };    friend class Factory; diff --git a/include/clang/Checker/PathSensitive/GRCoreEngine.h b/include/clang/Checker/PathSensitive/GRCoreEngine.h index c5bf5138a63fc..a3ff0dbedc7bf 100644 --- a/include/clang/Checker/PathSensitive/GRCoreEngine.h +++ b/include/clang/Checker/PathSensitive/GRCoreEngine.h @@ -82,7 +82,7 @@ class GRCoreEngine {    void ProcessStmt(CFGElement E, GRStmtNodeBuilder& Builder); -  bool ProcessBlockEntrance(CFGBlock* Blk, const GRState* State, +  bool ProcessBlockEntrance(CFGBlock* Blk, const ExplodedNode *Pred,                              GRBlockCounter BC); @@ -174,7 +174,9 @@ public:    GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();}    unsigned getCurrentBlockCount() const { -    return getBlockCounter().getNumVisited(B.getBlockID()); +    return getBlockCounter().getNumVisited( +                            Pred->getLocationContext()->getCurrentStackFrame(), +                                           B.getBlockID());    }    ExplodedNode* generateNode(PostStmt PP,const GRState* St,ExplodedNode* Pred) { @@ -434,7 +436,9 @@ public:    }    unsigned getCurrentBlockCount() const { -    return getBlockCounter().getNumVisited(B.getBlockID()); +    return getBlockCounter().getNumVisited( +                            Pred->getLocationContext()->getCurrentStackFrame(), +                                           B.getBlockID());    }    ExplodedNode* generateNode(const GRState* State, const void *tag = 0, diff --git a/include/clang/Checker/PathSensitive/GRExprEngine.h b/include/clang/Checker/PathSensitive/GRExprEngine.h index 916511e8bd098..161cb28df0333 100644 --- a/include/clang/Checker/PathSensitive/GRExprEngine.h +++ b/include/clang/Checker/PathSensitive/GRExprEngine.h @@ -16,7 +16,6 @@  #ifndef LLVM_CLANG_ANALYSIS_GREXPRENGINE  #define LLVM_CLANG_ANALYSIS_GREXPRENGINE -#include "clang/Checker/PathSensitive/AnalysisManager.h"  #include "clang/Checker/PathSensitive/GRSubEngine.h"  #include "clang/Checker/PathSensitive/GRCoreEngine.h"  #include "clang/Checker/PathSensitive/GRState.h" @@ -28,11 +27,9 @@  #include "clang/AST/ExprCXX.h"  namespace clang { - -  class PathDiagnosticClient; -  class Diagnostic; -  class ObjCForCollectionStmt; -  class Checker; +class AnalysisManager; +class Checker; +class ObjCForCollectionStmt;  class GRExprEngine : public GRSubEngine {    AnalysisManager &AMgr; @@ -153,7 +150,7 @@ public:    /// ProcessBlockEntrance - Called by GRCoreEngine when start processing    ///  a CFGBlock.  This method returns true if the analysis should continue    ///  exploring the given path, and false otherwise. -  bool ProcessBlockEntrance(CFGBlock* B, const GRState* St, +  bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,                              GRBlockCounter BC);    /// ProcessBranch - Called by GRCoreEngine.  Used to generate successor @@ -216,7 +213,7 @@ public:                           const GRState* St,                           ProgramPoint::Kind K = ProgramPoint::PostStmtKind,                           const void *tag = 0); -protected: +    /// CheckerVisit - Dispatcher for performing checker-specific logic    ///  at specific statements.    void CheckerVisit(Stmt *S, ExplodedNodeSet &Dst, ExplodedNodeSet &Src,  @@ -351,10 +348,21 @@ protected:    void VisitCXXConstructExpr(const CXXConstructExpr *E, SVal Dest,                               ExplodedNode *Pred,                               ExplodedNodeSet &Dst); + +  void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE, ExplodedNode *Pred, +                              ExplodedNodeSet &Dst); + +  void VisitAggExpr(const Expr *E, SVal Dest, ExplodedNode *Pred, +                    ExplodedNodeSet &Dst); +    /// Create a C++ temporary object for an rvalue.    void CreateCXXTemporaryObject(Expr *Ex, ExplodedNode *Pred,                                   ExplodedNodeSet &Dst); +  /// Synthesize CXXThisRegion. +  const CXXThisRegion *getCXXThisRegion(const CXXMethodDecl *MD, +                                        const StackFrameContext *SFC); +    /// EvalEagerlyAssume - Given the nodes in 'Src', eagerly assume symbolic    ///  expressions of the form 'x != 0' and generate new nodes (stored in Dst)    ///  with those assumptions. diff --git a/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h index 383463b822cb9..6d85e5fe6a90e 100644 --- a/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h +++ b/include/clang/Checker/PathSensitive/GRSimpleAPICheck.h @@ -17,18 +17,9 @@  #define LLVM_CLANG_ANALYSIS_GRAPICHECKS  #include "clang/Checker/PathSensitive/GRAuditor.h" -#include "clang/Checker/PathSensitive/GRState.h"  namespace clang { -class Diagnostic; -class BugReporter; -class ASTContext; -class GRExprEngine; -class PathDiagnosticClient; -class ExplodedGraph; - -  class GRSimpleAPICheck : public GRAuditor {  public:    GRSimpleAPICheck() {} diff --git a/include/clang/Checker/PathSensitive/GRState.h b/include/clang/Checker/PathSensitive/GRState.h index 657266b7508dc..25ba1f85fdff5 100644 --- a/include/clang/Checker/PathSensitive/GRState.h +++ b/include/clang/Checker/PathSensitive/GRState.h @@ -14,30 +14,22 @@  #ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H  #define LLVM_CLANG_ANALYSIS_VALUESTATE_H -// FIXME: Reduce the number of includes. - -#include "clang/AST/ASTContext.h" -#include "clang/AST/Decl.h" -#include "clang/AST/Expr.h" -#include "clang/Analysis/Analyses/LiveVariables.h"  #include "clang/Checker/PathSensitive/ConstraintManager.h"  #include "clang/Checker/PathSensitive/Environment.h" -#include "clang/Checker/PathSensitive/GRCoreEngine.h"  #include "clang/Checker/PathSensitive/Store.h"  #include "clang/Checker/PathSensitive/ValueManager.h" -#include "llvm/ADT/APSInt.h" -#include "llvm/ADT/DenseSet.h"  #include "llvm/ADT/FoldingSet.h"  #include "llvm/ADT/ImmutableMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Allocator.h"  #include "llvm/Support/Casting.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/System/DataTypes.h" -#include <functional> -namespace clang { +namespace llvm { +class APSInt; +class BumpPtrAllocator; +class raw_ostream; +} +namespace clang { +class ASTContext;  class GRStateManager;  class Checker; @@ -302,6 +294,8 @@ public:    template<typename T>    const GRState *remove(typename GRStateTrait<T>::key_type K,                          typename GRStateTrait<T>::context_type C) const; +  template <typename T> +  const GRState *remove() const;    template<typename T>    const GRState *set(typename GRStateTrait<T>::data_type D) const; @@ -464,6 +458,7 @@ public:    // Methods that manipulate the GDM.    const GRState* addGDM(const GRState* St, void* Key, void* Data); +  const GRState *removeGDM(const GRState *state, void *Key);    // Methods that query & manipulate the Store. @@ -528,6 +523,10 @@ public:       GRStateTrait<T>::MakeVoidPtr(GRStateTrait<T>::Remove(st->get<T>(), K, C)));    } +  template <typename T> +  const GRState *remove(const GRState *st) { +    return removeGDM(st, GRStateTrait<T>::GDMIndex()); +  }    void* FindGDMContext(void* index,                         void* (*CreateContext)(llvm::BumpPtrAllocator&), @@ -702,6 +701,11 @@ const GRState *GRState::remove(typename GRStateTrait<T>::key_type K,    return getStateManager().remove<T>(this, K, C);  } +template <typename T> +const GRState *GRState::remove() const { +  return getStateManager().remove<T>(this); +} +  template<typename T>  const GRState *GRState::set(typename GRStateTrait<T>::data_type D) const {    return getStateManager().set<T>(this, D); diff --git a/include/clang/Checker/PathSensitive/GRSubEngine.h b/include/clang/Checker/PathSensitive/GRSubEngine.h index f2cd0486e326c..d2e7457ea93d7 100644 --- a/include/clang/Checker/PathSensitive/GRSubEngine.h +++ b/include/clang/Checker/PathSensitive/GRSubEngine.h @@ -20,6 +20,7 @@ namespace clang {  class Stmt;  class CFGBlock;  class CFGElement; +class ExplodedNode;  class GRState;  class GRStateManager;  class GRBlockCounter; @@ -47,7 +48,7 @@ public:    /// ProcessBlockEntrance - Called by GRCoreEngine when start processing    ///  a CFGBlock.  This method returns true if the analysis should continue    ///  exploring the given path, and false otherwise. -  virtual bool ProcessBlockEntrance(CFGBlock* B, const GRState* St, +  virtual bool ProcessBlockEntrance(CFGBlock* B, const ExplodedNode *Pred,                                      GRBlockCounter BC) = 0;    /// ProcessBranch - Called by GRCoreEngine.  Used to generate successor diff --git a/include/clang/Checker/PathSensitive/GRTransferFuncs.h b/include/clang/Checker/PathSensitive/GRTransferFuncs.h index 04634effd5878..13325edea778d 100644 --- a/include/clang/Checker/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Checker/PathSensitive/GRTransferFuncs.h @@ -15,16 +15,18 @@  #ifndef LLVM_CLANG_ANALYSIS_GRTF  #define LLVM_CLANG_ANALYSIS_GRTF -#include "clang/Checker/PathSensitive/SVals.h" -#include "clang/Checker/PathSensitive/GRCoreEngine.h"  #include "clang/Checker/PathSensitive/GRState.h" +#include "clang/Checker/PathSensitive/SVals.h"  #include <vector>  namespace clang { - +class ExplodedNode; +class ExplodedNodeSet; +class GREndPathNodeBuilder;  class GRExprEngine; -class ObjCMessageExpr; +class GRStmtNodeBuilder;  class GRStmtNodeBuilderRef; +class ObjCMessageExpr;  class GRTransferFuncs {  public: diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index be89d2a3eb888..57ea8a3f6d9de 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -18,17 +18,15 @@  #include "clang/AST/Decl.h"  #include "clang/AST/DeclObjC.h" -#include "clang/Checker/PathSensitive/SymbolManager.h"  #include "clang/Checker/PathSensitive/SVals.h" -#include "clang/AST/ASTContext.h"  #include "llvm/Support/Casting.h"  #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/ImmutableList.h" -#include "llvm/ADT/ImmutableMap.h" -#include "llvm/Support/Allocator.h"  #include <string> -namespace llvm { class raw_ostream; } +namespace llvm { +class BumpPtrAllocator; +class raw_ostream; +}  namespace clang { diff --git a/include/clang/Checker/PathSensitive/Store.h b/include/clang/Checker/PathSensitive/Store.h index edc338012ada2..72565f4d740db 100644 --- a/include/clang/Checker/PathSensitive/Store.h +++ b/include/clang/Checker/PathSensitive/Store.h @@ -18,9 +18,6 @@  #include "clang/Checker/PathSensitive/SVals.h"  #include "clang/Checker/PathSensitive/ValueManager.h"  #include "llvm/ADT/DenseSet.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h"  namespace clang { diff --git a/include/clang/Checker/PathSensitive/SymbolManager.h b/include/clang/Checker/PathSensitive/SymbolManager.h index b6630c3d97d2b..dea877c0657f9 100644 --- a/include/clang/Checker/PathSensitive/SymbolManager.h +++ b/include/clang/Checker/PathSensitive/SymbolManager.h @@ -17,14 +17,14 @@  #include "clang/AST/Decl.h"  #include "clang/AST/Expr.h" -#include "clang/Analysis/Analyses/LiveVariables.h" +#include "clang/Analysis/AnalysisContext.h"  #include "llvm/System/DataTypes.h" -#include "llvm/Support/Allocator.h"  #include "llvm/ADT/FoldingSet.h"  #include "llvm/ADT/DenseSet.h"  namespace llvm { -  class raw_ostream; +class BumpPtrAllocator; +class raw_ostream;  }  namespace clang { @@ -34,9 +34,6 @@ namespace clang {    class TypedRegion;    class VarRegion;    class StackFrameContext; -} - -namespace clang {  class SymExpr : public llvm::FoldingSetNode {  public: @@ -247,6 +244,7 @@ public:               QualType t)      : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} +  BinaryOperator::Opcode getOpcode() const { return Op; }    const SymExpr *getLHS() const { return LHS; }    const SymExpr *getRHS() const { return RHS; } diff --git a/include/clang/CodeGen/CodeGenOptions.h b/include/clang/CodeGen/CodeGenOptions.h index 85c6c3e3abcf1..638ed516ed0b8 100644 --- a/include/clang/CodeGen/CodeGenOptions.h +++ b/include/clang/CodeGen/CodeGenOptions.h @@ -15,7 +15,6 @@  #define LLVM_CLANG_CODEGEN_CODEGENOPTIONS_H  #include <string> -#include <vector>  namespace clang { diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index feebbc78864f7..124288a76305c 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -156,6 +156,7 @@ def dependency_file : Separate<"-dependency-file">,    HelpText<"Filename (or -) to write dependency output to">;  def sys_header_deps : Flag<"-sys-header-deps">,    HelpText<"Include system headers in dependency output">; +def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">;  def MT : Separate<"-MT">, HelpText<"Specify target for dependency">;  def MP : Flag<"-MP">,    HelpText<"Create phony target for each dependency (other than main file)">; @@ -407,6 +408,8 @@ def fwritable_strings : Flag<"-fwritable-strings">,  def nostdinc : Flag<"-nostdinc">,    HelpText<"Disable standard #include directories">; +def nostdincxx : Flag<"-nostdinc++">, +  HelpText<"Disable standard #include directories for the C++ standard library">;  def nobuiltininc : Flag<"-nobuiltininc">,    HelpText<"Disable builtin #include directories">;  def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">, diff --git a/include/clang/Driver/CMakeLists.txt b/include/clang/Driver/CMakeLists.txt index f720d15d8cccd..ed9825b59df54 100644 --- a/include/clang/Driver/CMakeLists.txt +++ b/include/clang/Driver/CMakeLists.txt @@ -2,10 +2,10 @@ set(LLVM_TARGET_DEFINITIONS Options.td)  tablegen(Options.inc           -gen-opt-parser-defs)  add_custom_target(ClangDriverOptions -  DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/Options.inc) +  DEPENDS Options.inc)  set(LLVM_TARGET_DEFINITIONS CC1Options.td)  tablegen(CC1Options.inc           -gen-opt-parser-defs)  add_custom_target(ClangCC1Options -  DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/CC1Options.inc) +  DEPENDS CC1Options.inc) diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index f49c3b97c1c42..90c3a0dcdc189 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -64,6 +64,12 @@ public:    /// The path to the compiler resource directory.    std::string ResourceDir; +  /// A prefix directory used to emulated a limited subset of GCC's '-Bprefix' +  /// functionality. +  /// FIXME: This type of customization should be removed in favor of the +  /// universal driver when it is ready. +  std::string PrefixDir; +    /// Default host triple.    std::string DefaultHostTriple; @@ -133,7 +139,8 @@ public:    Driver(llvm::StringRef _Name, llvm::StringRef _Dir,           llvm::StringRef _DefaultHostTriple,           llvm::StringRef _DefaultImageName, -         bool IsProduction, Diagnostic &_Diags); +         bool IsProduction, bool CXXIsProduction, +         Diagnostic &_Diags);    ~Driver();    /// @name Accessors diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 71258f9814be7..d088be04c03ee 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -118,7 +118,7 @@ def ccc_ : Joined<"-ccc-">, Group<ccc_Group>, Flags<[Unsupported]>;  def _HASH_HASH_HASH : Flag<"-###">, Flags<[DriverOption]>,      HelpText<"Print the commands to run for this compilation">;  def A : JoinedOrSeparate<"-A">; -def B : JoinedOrSeparate<"-B">, Flags<[Unsupported]>; +def B : JoinedOrSeparate<"-B">;  def CC : Flag<"-CC">;  def C : Flag<"-C">;  def D : JoinedOrSeparate<"-D">, Group<CompileOnly_Group>; @@ -470,6 +470,7 @@ def noprebind : Flag<"-noprebind">;  def noseglinkedit : Flag<"-noseglinkedit">;  def nostartfiles : Flag<"-nostartfiles">;  def nostdinc : Flag<"-nostdinc">; +def nostdincxx : Flag<"-nostdinc++">;  def nostdlib : Flag<"-nostdlib">;  def object : Flag<"-object">;  def o : JoinedOrSeparate<"-o">, Flags<[DriverOption, RenderAsInput]>, diff --git a/include/clang/Frontend/HeaderSearchOptions.h b/include/clang/Frontend/HeaderSearchOptions.h index 690408547c0dc..c6682451835af 100644 --- a/include/clang/Frontend/HeaderSearchOptions.h +++ b/include/clang/Frontend/HeaderSearchOptions.h @@ -71,13 +71,17 @@ public:    /// Include the system standard include search directories.    unsigned UseStandardIncludes : 1; +  /// Include the system standard C++ library include search directories. +  unsigned UseStandardCXXIncludes : 1; +    /// Whether header search information should be output as for -v.    unsigned Verbose : 1;  public:    HeaderSearchOptions(llvm::StringRef _Sysroot = "/")      : Sysroot(_Sysroot), UseBuiltinIncludes(true), -      UseStandardIncludes(true), Verbose(false) {} +      UseStandardIncludes(true), UseStandardCXXIncludes(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/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index d09e51fd01848..157876b59d347 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -69,7 +69,7 @@ public:    void EmitCaretDiagnostic(SourceLocation Loc,                             SourceRange *Ranges, unsigned NumRanges,                             SourceManager &SM, -                           const CodeModificationHint *Hints, +                           const FixItHint *Hints,                             unsigned NumHints,                             unsigned Columns); diff --git a/include/clang/Frontend/TypeXML.def b/include/clang/Frontend/TypeXML.def index dd5018af82aaa..3add99a941c4b 100644 --- a/include/clang/Frontend/TypeXML.def +++ b/include/clang/Frontend/TypeXML.def @@ -233,7 +233,7 @@ NODE_XML(QualifiedNameType, "QualifiedNameType")    TYPE_ATTRIBUTE_XML(getNamedType())  END_NODE_XML -NODE_XML(TypenameType, "TypenameType") +NODE_XML(DependentNameType, "DependentNameType")    ID_ATTRIBUTE_XML  END_NODE_XML diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index dd24fb7d7ba25..e891e94d4cbc5 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -44,6 +44,12 @@ public:                             SrcMgr::CharacteristicKind FileType) {    } + +  /// EndOfMainFile - This callback is invoked when the end of the main file is +  /// reach, no subsequent callbacks will be made. +  virtual void EndOfMainFile() { +  } +    /// Ident - This callback is invoked when a #ident or #sccs directive is read.    ///    virtual void Ident(SourceLocation Loc, const std::string &str) { @@ -90,6 +96,11 @@ public:      Second->FileChanged(Loc, Reason, FileType);    } +  virtual void EndOfMainFile() { +    First->EndOfMainFile(); +    Second->EndOfMainFile(); +  } +    virtual void Ident(SourceLocation Loc, const std::string &str) {      First->Ident(Loc, str);      Second->Ident(Loc, str); diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 23c118d1fc630..312a760e01d38 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -368,6 +368,10 @@ public:    /// which implicitly adds the builtin defines etc.    bool EnterMainSourceFile(); +  /// EndSourceFile - Inform the preprocessor callbacks that processing is +  /// complete. +  void EndSourceFile(); +    /// 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    /// and fill in ErrorStr with the error information on failure. diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index 85c44c5a0b808..477a2130cf0eb 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -21,6 +21,7 @@  namespace clang { +class FileEntry;  class Preprocessor;  class PreprocessorLexer { diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index b79e698d50c96..59cc0d218cec4 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1761,7 +1761,8 @@ public:    virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc,                                                   DeclPtrTy TagDecl,                                                   SourceLocation LBrac, -                                                 SourceLocation RBrac) { +                                                 SourceLocation RBrac, +                                                 AttributeList *AttrList) {    }    //===---------------------------C++ Templates----------------------------===//  | 
