diff options
206 files changed, 7730 insertions, 3527 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 3178017e45be..44cbe0efff81 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -99,18 +99,84 @@ typedef struct {  } CXCursor;    /* A unique token for looking up "visible" CXDecls from a CXTranslationUnit. */ -typedef void *CXEntity;      +typedef void *CXEntity; -CXIndex clang_createIndex(); +/**   + * \brief clang_createIndex() provides a shared context for creating + * translation units. It provides two options: + * + * - excludeDeclarationsFromPCH: When non-zero, allows enumeration of "local" + * declarations (when loading any new translation units). A "local" declaration + * is one that belongs in the translation unit itself and not in a precompiled  + * header that was used by the translation unit. If zero, all declarations + * will be enumerated. + * + * - displayDiagnostics: when non-zero, diagnostics will be output. If zero, + * diagnostics will be ignored. + * + * Here is an example: + * + *   // excludeDeclsFromPCH = 1, displayDiagnostics = 1 + *   Idx = clang_createIndex(1, 1); + * + *   // IndexTest.pch was produced with the following command: + *   // "clang -x c IndexTest.h -emit-ast -o IndexTest.pch" + *   TU = clang_createTranslationUnit(Idx, "IndexTest.pch"); + * + *   // This will load all the symbols from 'IndexTest.pch' + *   clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0); + *   clang_disposeTranslationUnit(TU); + * + *   // This will load all the symbols from 'IndexTest.c', excluding symbols + *   // from 'IndexTest.pch'. + *   char *args[] = { "-Xclang", "-include-pch=IndexTest.pch", 0 }; + *   TU = clang_createTranslationUnitFromSourceFile(Idx, "IndexTest.c", 2, args); + *   clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0); + *   clang_disposeTranslationUnit(TU); + * + * This process of creating the 'pch', loading it separately, and using it (via + * -include-pch) allows 'excludeDeclsFromPCH' to remove redundant callbacks + * (which gives the indexer the same performance benefit as the compiler). + */ +CXIndex clang_createIndex(int excludeDeclarationsFromPCH, +                          int displayDiagnostics);  void clang_disposeIndex(CXIndex);  const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit); +/*  + * \brief Create a translation unit from an AST file (-emit-ast). + */  CXTranslationUnit clang_createTranslationUnit(    CXIndex, const char *ast_filename  ); +/** + * \brief Destroy the specified CXTranslationUnit object. + */   void clang_disposeTranslationUnit(CXTranslationUnit); +/** + * \brief Return the CXTranslationUnit for a given source file and the provided + * command line arguments one would pass to the compiler. + * + * Note: The 'source_filename' argument is optional.  If the caller provides a NULL pointer, + *  the name of the source file is expected to reside in the specified command line arguments. + * + * Note: When encountered in 'clang_command_line_args', the following options are ignored: + * + *   '-c' + *   '-emit-ast' + *   '-fsyntax-only' + *   '-o <output file>'  (both '-o' and '<output file>' are ignored) + * + */ +CXTranslationUnit clang_createTranslationUnitFromSourceFile( +  CXIndex CIdx,  +  const char *source_filename /* specify NULL if the source file is in clang_command_line_args */, +  int num_clang_command_line_args,  +  const char **clang_command_line_args +); +  /*     Usage: clang_loadTranslationUnit(). Will load the toplevel declarations     within a translation unit, issuing a 'callback' for each one. @@ -182,9 +248,28 @@ const char *clang_getDeclSource(CXDecl);  /*   * CXCursor Operations.   */ +/** +   Usage: clang_getCursor() will translate a source/line/column position +   into an AST cursor (to derive semantic information from the source code). + */  CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,                            unsigned line, unsigned column); +/** +   Usage: clang_getCursorWithHint() provides the same functionality as +   clang_getCursor() except that it takes an option 'hint' argument. +   The 'hint' is a temporary CXLookupHint object (whose lifetime is managed by  +   the caller) that should be initialized with clang_initCXLookupHint(). + +   FIXME: Add a better comment once getCursorWithHint() has more functionality. + */                          +typedef CXCursor CXLookupHint; +CXCursor clang_getCursorWithHint(CXTranslationUnit, const char *source_name,  +                                 unsigned line, unsigned column,  +                                 CXLookupHint *hint); + +void clang_initCXLookupHint(CXLookupHint *hint); +  enum CXCursorKind clang_getCursorKind(CXCursor);  unsigned clang_isDeclaration(enum CXCursorKind);  unsigned clang_isReference(enum CXCursorKind); diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 106d568c9b24..30896c91a143 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -81,12 +81,12 @@ class ASTContext {    llvm::FoldingSet<DependentTypeOfExprType> DependentTypeOfExprTypes;    llvm::FoldingSet<DependentDecltypeType> DependentDecltypeTypes;    llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes; +  llvm::FoldingSet<SubstTemplateTypeParmType> SubstTemplateTypeParmTypes;    llvm::FoldingSet<TemplateSpecializationType> TemplateSpecializationTypes;    llvm::FoldingSet<QualifiedNameType> QualifiedNameTypes;    llvm::FoldingSet<TypenameType> TypenameTypes;    llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes;    llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; -  llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes;    llvm::FoldingSet<ElaboratedType> ElaboratedTypes;    llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; @@ -143,6 +143,12 @@ class ASTContext {    /// \brief The type for the C sigjmp_buf type.    TypeDecl *sigjmp_bufDecl; +  /// \brief Type for the Block descriptor for Blocks CodeGen. +  RecordDecl *BlockDescriptorType; + +  /// \brief Type for the Block descriptor for Blocks CodeGen. +  RecordDecl *BlockDescriptorExtendedType; +    /// \brief Keeps track of all declaration attributes.    ///    /// Since so few decls have attrs, we keep them in a hash map instead of @@ -390,9 +396,47 @@ public:    /// of the specified type.    QualType getBlockPointerType(QualType T); +  /// This gets the struct used to keep track of the descriptor for pointer to +  /// blocks. +  QualType getBlockDescriptorType(); + +  // Set the type for a Block descriptor type. +  void setBlockDescriptorType(QualType T); +  /// Get the BlockDescriptorType type, or NULL if it hasn't yet been built. +  QualType getRawBlockdescriptorType() { +    if (BlockDescriptorType) +      return getTagDeclType(BlockDescriptorType); +    return QualType(); +  } + +  /// This gets the struct used to keep track of the extended descriptor for +  /// pointer to blocks. +  QualType getBlockDescriptorExtendedType(); + +  // Set the type for a Block descriptor extended type. +  void setBlockDescriptorExtendedType(QualType T); +  /// Get the BlockDescriptorExtendedType type, or NULL if it hasn't yet been +  /// built. +  QualType getRawBlockdescriptorExtendedType() { +    if (BlockDescriptorExtendedType) +      return getTagDeclType(BlockDescriptorExtendedType); +    return QualType(); +  } + +  /// This gets the struct used to keep track of pointer to blocks, complete +  /// with captured variables. +  QualType getBlockParmType(bool BlockHasCopyDispose, +                            llvm::SmallVector<const Expr *, 8> &BDRDs); + +  /// This builds the struct used for __block variables. +  QualType BuildByRefType(const char *DeclName, QualType Ty); + +  /// Returns true iff we need copy/dispose helpers for the given type. +  bool BlockRequiresCopying(QualType Ty); +    /// getLValueReferenceType - Return the uniqued reference to the type for an    /// lvalue reference to the specified type. -  QualType getLValueReferenceType(QualType T); +  QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true);    /// getRValueReferenceType - Return the uniqued reference to the type for an    /// rvalue reference to the specified type. @@ -431,22 +475,6 @@ public:                                  ArrayType::ArraySizeModifier ASM,                                  unsigned EltTypeQuals); -  /// getConstantArrayWithExprType - Return a reference to the type for a -  /// constant array of the specified element type. -  QualType getConstantArrayWithExprType(QualType EltTy, -                                        const llvm::APInt &ArySize, -                                        Expr *ArySizeExpr, -                                        ArrayType::ArraySizeModifier ASM, -                                        unsigned EltTypeQuals, -                                        SourceRange Brackets); - -  /// getConstantArrayWithoutExprType - Return a reference to the type -  /// for a constant array of the specified element type. -  QualType getConstantArrayWithoutExprType(QualType EltTy, -                                           const llvm::APInt &ArySize, -                                           ArrayType::ArraySizeModifier ASM, -                                           unsigned EltTypeQuals); -    /// getVectorType - Return the unique reference to a vector type of    /// the specified element type and size. VectorType must be a built-in type.    QualType getVectorType(QualType VectorType, unsigned NumElts); @@ -485,6 +513,9 @@ public:    /// specified typename decl.    QualType getTypedefType(TypedefDecl *Decl); +  QualType getSubstTemplateTypeParmType(const TemplateTypeParmType *Replaced, +                                        QualType Replacement); +    QualType getTemplateTypeParmType(unsigned Depth, unsigned Index,                                     bool ParameterPack,                                     IdentifierInfo *Name = 0); @@ -515,10 +546,6 @@ public:                                      ObjCProtocolDecl **ProtocolList = 0,                                      unsigned NumProtocols = 0); -  QualType getObjCProtocolListType(QualType T, -                                   ObjCProtocolDecl **Protocols, -                                   unsigned NumProtocols); -    /// getTypeOfType - GCC extension.    QualType getTypeOfExprType(Expr *e);    QualType getTypeOfType(QualType t); @@ -815,6 +842,12 @@ public:      return T->getCanonicalTypeInternal().getTypePtr();    } +  /// getCanonicalParamType - Return the canonical parameter type +  /// corresponding to the specific potentially non-canonical one. +  /// Qualifiers are stripped off, functions are turned into function +  /// pointers, and arrays decay one level into pointers. +  CanQualType getCanonicalParamType(QualType T); +    /// \brief Determine whether the given types are equivalent.    bool hasSameType(QualType T1, QualType T2) {      return getCanonicalType(T1) == getCanonicalType(T2); @@ -1047,7 +1080,10 @@ public:    /// \param T the type that will be the basis for type source info. This type    /// should refer to how the declarator was written in source code, not to    /// what type semantic analysis resolved the declarator to. -  DeclaratorInfo *CreateDeclaratorInfo(QualType T); +  /// +  /// \param Size the size of the type info to create, or 0 if the size +  /// should be calculated based on the type. +  DeclaratorInfo *CreateDeclaratorInfo(QualType T, unsigned Size = 0);  private:    ASTContext(const ASTContext&); // DO NOT IMPLEMENT diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 6a5e3666a92c..f7a47364a7f6 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -185,7 +185,6 @@ class AlignedAttr : public Attr {  public:    AlignedAttr(unsigned alignment) : Attr(Aligned), Alignment(alignment) {} -  // FIXME: Should use addressable units, not bits, to match llvm    /// getAlignment - The specified alignment in bits.    unsigned getAlignment() const { return Alignment; } diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index a57bcc184a93..7c826fe75d11 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -63,7 +63,8 @@ struct CXXBasePathElement {  /// structure, which captures both the link from a derived class to one of its  /// direct bases and identification describing which base class  /// subobject is being used. -struct CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> { +class CXXBasePath : public llvm::SmallVector<CXXBasePathElement, 4> { +public:    /// \brief The set of declarations found inside this base class    /// subobject.    DeclContext::lookup_result Decls; diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index d7ac76dd32e4..8b84bc267997 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -487,30 +487,6 @@ struct CanProxyAdaptor<ConstantArrayType>  };  template<> -struct CanProxyAdaptor<ConstantArrayWithExprType> -  : public CanProxyBase<ConstantArrayWithExprType> { -  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, -                                      getSizeModifier) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Expr *, getSizeExpr) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceRange, getBracketsRange) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getLBracketLoc) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(SourceLocation, getRBracketLoc) -}; - -template<> -struct CanProxyAdaptor<ConstantArrayWithoutExprType> -  : public CanProxyBase<ConstantArrayWithoutExprType> { -  LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(ArrayType::ArraySizeModifier, -                                      getSizeModifier) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Qualifiers, getIndexTypeQualifiers) -  LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(const llvm::APInt &, getSize) -}; - -template<>  struct CanProxyAdaptor<IncompleteArrayType>    : public CanProxyBase<IncompleteArrayType> {    LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getElementType) @@ -684,7 +660,7 @@ CanQual<T> CanQual<T>::getFromOpaquePtr(void *Ptr) {  template<typename T>  CanQual<T> CanQual<T>::CreateUnsafe(QualType Other) { -  assert((Other.isNull() || Other->isCanonical()) && "Type is not canonical!"); +  assert((Other.isNull() || Other.isCanonical()) && "Type is not canonical!");    assert((Other.isNull() || isa<T>(Other.getTypePtr())) &&           "Dynamic type does not meet the static type's requires");    CanQual<T> Result; diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index f21541c3e710..72ce0d852cfc 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -47,6 +47,9 @@ class DeclaratorInfo {    friend class ASTContext;    DeclaratorInfo(QualType ty) : Ty(ty) { }  public: +  /// \brief Return the type wrapped by this type source info. +  QualType getType() const { return Ty; } +    /// \brief Return the TypeLoc wrapper for the type source info.    TypeLoc getTypeLoc() const;  }; @@ -93,28 +96,43 @@ public:    /// name (C++ constructor, Objective-C selector, etc.).    IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); } +  /// getName - Get the name of identifier for this declaration as a StringRef. +  /// This requires that the declaration have a name and that it be a simple +  /// identifier. +  llvm::StringRef getName() const { +    assert(Name.isIdentifier() && "Name is not a simple identifier"); +    return getIdentifier() ? getIdentifier()->getName() : ""; +  } +    /// getNameAsCString - Get the name of identifier for this declaration as a    /// C string (const char*).  This requires that the declaration have a name    /// and that it be a simple identifier. +  // +  // FIXME: Deprecated, move clients to getName().    const char *getNameAsCString() const { -    assert(getIdentifier() && "Name is not a simple identifier"); -    return getIdentifier()->getName(); +    assert(Name.isIdentifier() && "Name is not a simple identifier"); +    return getIdentifier() ? getIdentifier()->getNameStart() : "";    } -  /// getDeclName - Get the actual, stored name of the declaration, -  /// which may be a special name. -  DeclarationName getDeclName() const { return Name; } - -  /// \brief Set the name of this declaration. -  void setDeclName(DeclarationName N) { Name = N; } -    /// getNameAsString - Get a human-readable name for the declaration, even if    /// it is one of the special kinds of names (C++ constructor, Objective-C    /// selector, etc).  Creating this name requires expensive string    /// manipulation, so it should be called only when performance doesn't matter.    /// For simple declarations, getNameAsCString() should suffice. +  // +  // FIXME: This function should be renamed to indicate that it is not just an +  // alternate form of getName(), and clients should move as appropriate. +  // +  // FIXME: Deprecated, move clients to getName().    std::string getNameAsString() const { return Name.getAsString(); } +  /// getDeclName - Get the actual, stored name of the declaration, +  /// which may be a special name. +  DeclarationName getDeclName() const { return Name; } + +  /// \brief Set the name of this declaration. +  void setDeclName(DeclarationName N) { Name = N; } +    /// getQualifiedNameAsString - Returns human-readable qualified name for    /// declaration, like A::B::i, for i being member of namespace A::B.    /// If declaration is not member of context which can be named (record, @@ -604,7 +622,8 @@ public:    /// \brief For a static data member that was instantiated from a static    /// data member of a class template, set the template specialiation kind. -  void setTemplateSpecializationKind(TemplateSpecializationKind TSK); +  void setTemplateSpecializationKind(TemplateSpecializationKind TSK, +                        SourceLocation PointOfInstantiation = SourceLocation());    /// isFileVarDecl - Returns true for file scoped variable declaration.    bool isFileVarDecl() const { @@ -1170,7 +1189,16 @@ public:    /// \brief Determine what kind of template instantiation this function    /// represents. -  void setTemplateSpecializationKind(TemplateSpecializationKind TSK); +  void setTemplateSpecializationKind(TemplateSpecializationKind TSK, +                        SourceLocation PointOfInstantiation = SourceLocation()); + +  /// \brief Retrieve the (first) point of instantiation of a function template +  /// specialization or a member of a class template specialization. +  /// +  /// \returns the first point of instantiation, if this function was  +  /// instantiated from a template; otherwie, returns an invalid source  +  /// location. +  SourceLocation getPointOfInstantiation() const;    /// \brief Determine whether this is or was instantiated from an out-of-line     /// definition of a member function. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 9e88871565f1..10db7030db18 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -166,6 +166,15 @@ private:    bool Used : 1;  protected: +  /// Access - Used by C++ decls for the access specifier. +  // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum +  unsigned Access : 2; +  friend class CXXClassMemberWrapper; +   +  // PCHLevel - the "level" of precompiled header/AST file from which this +  // declaration was built. +  unsigned PCHLevel : 2; +      /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in.    unsigned IdentifierNamespace : 16; @@ -177,16 +186,13 @@ private:  #endif  protected: -  /// Access - Used by C++ decls for the access specifier. -  // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum -  unsigned Access : 2; -  friend class CXXClassMemberWrapper;    Decl(Kind DK, DeclContext *DC, SourceLocation L)      : NextDeclInContext(0), DeclCtx(DC),        Loc(L), DeclKind(DK), InvalidDecl(0),        HasAttrs(false), Implicit(false), Used(false), -      IdentifierNamespace(getIdentifierNamespaceForKind(DK)), Access(AS_none) { +      Access(AS_none), PCHLevel(0), +      IdentifierNamespace(getIdentifierNamespaceForKind(DK)) {      if (Decl::CollectingStats()) addDeclKind(DK);    } @@ -274,6 +280,26 @@ public:    bool isUsed() const { return Used; }    void setUsed(bool U = true) { Used = U; } +  /// \brief Retrieve the level of precompiled header from which this +  /// declaration was generated. +  /// +  /// The PCH level of a declaration describes where the declaration originated +  /// from. A PCH level of 0 indicates that the declaration was not from a  +  /// precompiled header. A PCH level of 1 indicates that the declaration was +  /// from a top-level precompiled header; 2 indicates that the declaration  +  /// comes from a precompiled header on which the top-level precompiled header +  /// depends, and so on.  +  unsigned getPCHLevel() const { return PCHLevel; } + +  /// \brief The maximum PCH level that any declaration may have. +  static const unsigned MaxPCHLevel = 3; +   +  /// \brief Set the PCH level of this declaration. +  void setPCHLevel(unsigned Level) {  +    assert(Level < MaxPCHLevel && "PCH level exceeds the maximum"); +    PCHLevel = Level; +  } +      unsigned getIdentifierNamespace() const {      return IdentifierNamespace;    } diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 2b12bb5c1b6d..729a2f138303 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -944,16 +944,29 @@ public:    ObjCCategoryDecl *getCategoryClass() const; +  /// getName - Get the name of identifier for the class interface associated +  /// with this implementation as a StringRef. +  // +  // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean +  // something different. +  llvm::StringRef getName() const { +    return Id ? Id->getNameStart() : ""; +  } +    /// getNameAsCString - Get the name of identifier for the class    /// interface associated with this implementation as a C string    /// (const char*). +  // +  // FIXME: Deprecated, move clients to getName().    const char *getNameAsCString() const { -    return Id ? Id->getName() : ""; +    return Id ? Id->getNameStart() : "";    }    /// @brief Get the name of the class associated with this interface. +  // +  // FIXME: Deprecated, move clients to getName().    std::string getNameAsString() const { -    return Id ? Id->getName() : ""; +    return getName();    }    static bool classof(const Decl *D) { return D->getKind() == ObjCCategoryImpl;} @@ -995,17 +1008,30 @@ public:      return getClassInterface()->getIdentifier();    } +  /// getName - Get the name of identifier for the class interface associated +  /// with this implementation as a StringRef. +  // +  // FIXME: This is a bad API, we are overriding the NamedDecl::getName, to mean +  // something different. +  llvm::StringRef getName() const { +    assert(getIdentifier() && "Name is not a simple identifier"); +    return getIdentifier()->getName(); +  } +    /// getNameAsCString - Get the name of identifier for the class    /// interface associated with this implementation as a C string    /// (const char*). +  // +  // FIXME: Move to StringRef API.    const char *getNameAsCString() const { -    assert(getIdentifier() && "Name is not a simple identifier"); -    return getIdentifier()->getName(); +    return getName().data();    }    /// @brief Get the name of the class associated with this interface. +  // +  // FIXME: Move to StringRef API.    std::string getNameAsString() const { -    return getClassInterface()->getNameAsString(); +    return getName();    }    const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index d5dff5065d49..0d09ea325c31 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -1399,7 +1399,27 @@ public:      CK_IntegralToPointer,      /// CK_PointerToIntegral - Pointer to integral -    CK_PointerToIntegral +    CK_PointerToIntegral, +     +    /// CK_ToVoid - Cast to void. +    CK_ToVoid, +     +    /// CK_VectorSplat - Casting from an integer/floating type to an extended +    /// vector type with the same element type as the src type. Splats the  +    /// src expression into the destination expression. +    CK_VectorSplat, +     +    /// CK_IntegralCast - Casting between integral types of different size. +    CK_IntegralCast, + +    /// CK_IntegralToFloating - Integral to floating point. +    CK_IntegralToFloating, +     +    /// CK_FloatingToIntegral - Floating point to integral. +    CK_FloatingToIntegral, +     +    /// CK_FloatingCast - Casting between floating types of different size. +    CK_FloatingCast    };  private: @@ -1665,7 +1685,8 @@ public:    /// predicates to categorize the respective opcodes.    bool isMultiplicativeOp() const { return Opc >= Mul && Opc <= Rem; }    bool isAdditiveOp() const { return Opc == Add || Opc == Sub; } -  bool isShiftOp() const { return Opc == Shl || Opc == Shr; } +  static bool isShiftOp(Opcode Opc) { return Opc == Shl || Opc == Shr; } +  bool isShiftOp() const { return isShiftOp(Opc); }    bool isBitwiseOp() const { return Opc >= And && Opc <= Or; }    static bool isRelationalOp(Opcode Opc) { return Opc >= LT && Opc <= GE; } diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 89776b91fe4a..db02a68a984d 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -443,6 +443,9 @@ public:      return getTypePtr();    } +  bool isCanonical() const; +  bool isCanonicalAsParam() const; +    /// isNull - Return true if this QualType doesn't point to a type yet.    bool isNull() const {      return Value.getPointer().isNull(); @@ -702,7 +705,9 @@ protected:  public:    TypeClass getTypeClass() const { return static_cast<TypeClass>(TC); } -  bool isCanonical() const { return CanonicalType.getTypePtr() == this; } +  bool isCanonicalUnqualified() const { +    return CanonicalType.getTypePtr() == this; +  }    /// Types are partitioned into 3 broad categories (C99 6.2.5p1):    /// object types, function types, and incomplete types. @@ -1089,19 +1094,50 @@ public:  class ReferenceType : public Type, public llvm::FoldingSetNode {    QualType PointeeType; +  /// True if the type was originally spelled with an lvalue sigil. +  /// This is never true of rvalue references but can also be false +  /// on lvalue references because of C++0x [dcl.typedef]p9, +  /// as follows: +  /// +  ///   typedef int &ref;    // lvalue, spelled lvalue +  ///   typedef int &&rvref; // rvalue +  ///   ref &a;              // lvalue, inner ref, spelled lvalue +  ///   ref &&a;             // lvalue, inner ref +  ///   rvref &a;            // lvalue, inner ref, spelled lvalue +  ///   rvref &&a;           // rvalue, inner ref +  bool SpelledAsLValue; + +  /// True if the inner type is a reference type.  This only happens +  /// in non-canonical forms. +  bool InnerRef; +  protected: -  ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef) : +  ReferenceType(TypeClass tc, QualType Referencee, QualType CanonicalRef, +                bool SpelledAsLValue) :      Type(tc, CanonicalRef, Referencee->isDependentType()), -    PointeeType(Referencee) { +    PointeeType(Referencee), SpelledAsLValue(SpelledAsLValue), +    InnerRef(Referencee->isReferenceType()) {    }  public: -  QualType getPointeeType() const { return PointeeType; } +  bool isSpelledAsLValue() const { return SpelledAsLValue; } + +  QualType getPointeeTypeAsWritten() const { return PointeeType; } +  QualType getPointeeType() const { +    // FIXME: this might strip inner qualifiers; okay? +    const ReferenceType *T = this; +    while (T->InnerRef) +      T = T->PointeeType->getAs<ReferenceType>(); +    return T->PointeeType; +  }    void Profile(llvm::FoldingSetNodeID &ID) { -    Profile(ID, getPointeeType()); +    Profile(ID, PointeeType, SpelledAsLValue);    } -  static void Profile(llvm::FoldingSetNodeID &ID, QualType Referencee) { +  static void Profile(llvm::FoldingSetNodeID &ID, +                      QualType Referencee, +                      bool SpelledAsLValue) {      ID.AddPointer(Referencee.getAsOpaquePtr()); +    ID.AddBoolean(SpelledAsLValue);    }    static bool classof(const Type *T) { @@ -1114,9 +1150,10 @@ public:  /// LValueReferenceType - C++ [dcl.ref] - Lvalue reference  ///  class LValueReferenceType : public ReferenceType { -  LValueReferenceType(QualType Referencee, QualType CanonicalRef) : -    ReferenceType(LValueReference, Referencee, CanonicalRef) { -  } +  LValueReferenceType(QualType Referencee, QualType CanonicalRef, +                      bool SpelledAsLValue) : +    ReferenceType(LValueReference, Referencee, CanonicalRef, SpelledAsLValue) +  {}    friend class ASTContext; // ASTContext creates these  public:    virtual void getAsStringInternal(std::string &InnerString, @@ -1135,7 +1172,7 @@ public:  ///  class RValueReferenceType : public ReferenceType {    RValueReferenceType(QualType Referencee, QualType CanonicalRef) : -    ReferenceType(RValueReference, Referencee, CanonicalRef) { +    ReferenceType(RValueReference, Referencee, CanonicalRef, false) {    }    friend class ASTContext; // ASTContext creates these  public: @@ -1239,8 +1276,6 @@ public:    static bool classof(const Type *T) {      return T->getTypeClass() == ConstantArray || -           T->getTypeClass() == ConstantArrayWithExpr || -           T->getTypeClass() == ConstantArrayWithoutExpr ||             T->getTypeClass() == VariableArray ||             T->getTypeClass() == IncompleteArray ||             T->getTypeClass() == DependentSizedArray; @@ -1285,86 +1320,11 @@ public:      ID.AddInteger(TypeQuals);    }    static bool classof(const Type *T) { -    return T->getTypeClass() == ConstantArray || -           T->getTypeClass() == ConstantArrayWithExpr || -           T->getTypeClass() == ConstantArrayWithoutExpr; +    return T->getTypeClass() == ConstantArray;    }    static bool classof(const ConstantArrayType *) { return true; }  }; -/// ConstantArrayWithExprType - This class represents C arrays with a -/// constant size specified by means of an integer constant expression. -/// For example 'int A[sizeof(int)]' has ConstantArrayWithExprType where -/// the element type is 'int' and the size expression is 'sizeof(int)'. -/// These types are non-canonical. -class ConstantArrayWithExprType : public ConstantArrayType { -  /// SizeExpr - The ICE occurring in the concrete syntax. -  Expr *SizeExpr; -  /// Brackets - The left and right array brackets. -  SourceRange Brackets; - -  ConstantArrayWithExprType(QualType et, QualType can, -                            const llvm::APInt &size, Expr *e, -                            ArraySizeModifier sm, unsigned tq, -                            SourceRange brackets) -    : ConstantArrayType(ConstantArrayWithExpr, et, can, size, sm, tq), -      SizeExpr(e), Brackets(brackets) {} -  friend class ASTContext;  // ASTContext creates these. -  virtual void Destroy(ASTContext& C); - -public: -  Expr *getSizeExpr() const { return SizeExpr; } -  SourceRange getBracketsRange() const { return Brackets; } -  SourceLocation getLBracketLoc() const { return Brackets.getBegin(); } -  SourceLocation getRBracketLoc() const { return Brackets.getEnd(); } - -  virtual void getAsStringInternal(std::string &InnerString, -                                   const PrintingPolicy &Policy) const; - -  bool isSugared() const { return false; } -  QualType desugar() const { return QualType(this, 0); } - -  static bool classof(const Type *T) { -    return T->getTypeClass() == ConstantArrayWithExpr; -  } -  static bool classof(const ConstantArrayWithExprType *) { return true; } - -  void Profile(llvm::FoldingSetNodeID &ID) { -    assert(0 && "Cannot unique ConstantArrayWithExprTypes."); -  } -}; - -/// ConstantArrayWithoutExprType - This class represents C arrays with a -/// constant size that was not specified by an integer constant expression, -/// but inferred by static semantics. -/// For example 'int A[] = { 0, 1, 2 }' has ConstantArrayWithoutExprType. -/// These types are non-canonical: the corresponding canonical type, -/// having the size specified in an APInt object, is a ConstantArrayType. -class ConstantArrayWithoutExprType : public ConstantArrayType { - -  ConstantArrayWithoutExprType(QualType et, QualType can, -                               const llvm::APInt &size, -                               ArraySizeModifier sm, unsigned tq) -    : ConstantArrayType(ConstantArrayWithoutExpr, et, can, size, sm, tq) {} -  friend class ASTContext;  // ASTContext creates these. - -public: -  virtual void getAsStringInternal(std::string &InnerString, -                                   const PrintingPolicy &Policy) const; - -  bool isSugared() const { return false; } -  QualType desugar() const { return QualType(this, 0); } - -  static bool classof(const Type *T) { -    return T->getTypeClass() == ConstantArrayWithoutExpr; -  } -  static bool classof(const ConstantArrayWithoutExprType *) { return true; } - -  void Profile(llvm::FoldingSetNodeID &ID) { -    assert(0 && "Cannot unique ConstantArrayWithoutExprTypes."); -  } -}; -  /// IncompleteArrayType - This class represents C arrays with an unspecified  /// size.  For example 'int A[]' has an IncompleteArrayType where the element  /// type is 'int' and the size is unspecified. @@ -2219,6 +2179,59 @@ public:    static bool classof(const TemplateTypeParmType *T) { return true; }  }; +/// \brief Represents the result of substituting a type for a template +/// type parameter. +/// +/// Within an instantiated template, all template type parameters have +/// been replaced with these.  They are used solely to record that a +/// type was originally written as a template type parameter; +/// therefore they are never canonical. +class SubstTemplateTypeParmType : public Type, public llvm::FoldingSetNode { +  // The original type parameter. +  const TemplateTypeParmType *Replaced; + +  SubstTemplateTypeParmType(const TemplateTypeParmType *Param, QualType Canon) +    : Type(SubstTemplateTypeParm, Canon, Canon->isDependentType()), +      Replaced(Param) { } + +  friend class ASTContext; + +public: +  IdentifierInfo *getName() const { return Replaced->getName(); } + +  /// Gets the template parameter that was substituted for. +  const TemplateTypeParmType *getReplacedParameter() const { +    return Replaced; +  } + +  /// Gets the type that was substituted for the template +  /// parameter. +  QualType getReplacementType() const { +    return getCanonicalTypeInternal(); +  } + +  virtual void getAsStringInternal(std::string &InnerString, +                                   const PrintingPolicy &Policy) const; + +  bool isSugared() const { return true; } +  QualType desugar() const { return getReplacementType(); } + +  void Profile(llvm::FoldingSetNodeID &ID) { +    Profile(ID, getReplacedParameter(), getReplacementType()); +  } +  static void Profile(llvm::FoldingSetNodeID &ID, +                      const TemplateTypeParmType *Replaced, +                      QualType Replacement) { +    ID.AddPointer(Replaced); +    ID.AddPointer(Replacement.getAsOpaquePtr()); +  } + +  static bool classof(const Type *T) { +    return T->getTypeClass() == SubstTemplateTypeParm; +  } +  static bool classof(const SubstTemplateTypeParmType *T) { return true; } +}; +  /// \brief Represents the type of a template specialization as written  /// in the source code.  /// @@ -2453,9 +2466,9 @@ class ObjCInterfaceType : public Type, public llvm::FoldingSetNode {    // List is sorted on protocol name. No protocol is enterred more than once.    llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols; -  ObjCInterfaceType(ObjCInterfaceDecl *D, +  ObjCInterfaceType(QualType Canonical, ObjCInterfaceDecl *D,                      ObjCProtocolDecl **Protos, unsigned NumP) : -    Type(ObjCInterface, QualType(), /*Dependent=*/false), +    Type(ObjCInterface, Canonical, /*Dependent=*/false),      Decl(D), Protocols(Protos, Protos+NumP) { }    friend class ASTContext;  // ASTContext creates these.  public: @@ -2501,8 +2514,9 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {    // List is sorted on protocol name. No protocol is entered more than once.    llvm::SmallVector<ObjCProtocolDecl*, 8> Protocols; -  ObjCObjectPointerType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) : -    Type(ObjCObjectPointer, QualType(), /*Dependent=*/false), +  ObjCObjectPointerType(QualType Canonical, QualType T, +                        ObjCProtocolDecl **Protos, unsigned NumP) : +    Type(ObjCObjectPointer, Canonical, /*Dependent=*/false),      PointeeType(T), Protocols(Protos, Protos+NumP) { }    friend class ASTContext;  // ASTContext creates these. @@ -2567,49 +2581,6 @@ public:    static bool classof(const ObjCObjectPointerType *) { return true; }  }; -/// \brief An ObjC Protocol list that qualifies a type. -/// -/// This is used only for keeping detailed type source information, it should -/// not participate in the semantics of the type system. -/// The protocol list is not canonicalized. -class ObjCProtocolListType : public Type, public llvm::FoldingSetNode { -  QualType BaseType; - -  // List of protocols for this protocol conforming object type. -  llvm::SmallVector<ObjCProtocolDecl*, 4> Protocols; - -  ObjCProtocolListType(QualType T, ObjCProtocolDecl **Protos, unsigned NumP) : -    Type(ObjCProtocolList, QualType(), /*Dependent=*/false), -    BaseType(T), Protocols(Protos, Protos+NumP) { } -  friend class ASTContext;  // ASTContext creates these. - -public: -  QualType getBaseType() const { return BaseType; } - -  /// \brief Provides access to the list of protocols qualifying the base type. -  typedef llvm::SmallVector<ObjCProtocolDecl*, 4>::const_iterator qual_iterator; - -  qual_iterator qual_begin() const { return Protocols.begin(); } -  qual_iterator qual_end() const   { return Protocols.end(); } -  bool qual_empty() const { return Protocols.size() == 0; } - -  /// \brief Return the number of qualifying protocols. -  unsigned getNumProtocols() const { return Protocols.size(); } - -  bool isSugared() const { return false; } -  QualType desugar() const { return QualType(this, 0); } - -  void Profile(llvm::FoldingSetNodeID &ID); -  static void Profile(llvm::FoldingSetNodeID &ID, QualType T, -                      ObjCProtocolDecl **protocols, unsigned NumProtocols); -  virtual void getAsStringInternal(std::string &InnerString, -                                   const PrintingPolicy &Policy) const; -  static bool classof(const Type *T) { -    return T->getTypeClass() == ObjCProtocolList; -  } -  static bool classof(const ObjCProtocolListType *) { return true; } -}; -  /// A qualifier set is used to build a set of qualifiers.  class QualifierCollector : public Qualifiers {    ASTContext *Context; @@ -2646,6 +2617,20 @@ public:  // Inline function definitions. +inline bool QualType::isCanonical() const { +  const Type *T = getTypePtr(); +  if (hasQualifiers()) +    return T->isCanonicalUnqualified() && !isa<ArrayType>(T); +  return T->isCanonicalUnqualified(); +} + +inline bool QualType::isCanonicalAsParam() const { +  if (hasQualifiers()) return false; +  const Type *T = getTypePtr(); +  return T->isCanonicalUnqualified() && +           !isa<FunctionType>(T) && !isa<ArrayType>(T); +} +  inline void QualType::removeConst() {    removeFastQualifiers(Qualifiers::Const);  } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 3735eee47629..1d7181b531f8 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -18,10 +18,15 @@  namespace clang {    class ParmVarDecl; -  class TypeSpecLoc;    class DeclaratorInfo;    class UnqualTypeLoc; +// Predeclare all the type nodes. +#define ABSTRACT_TYPELOC(Class, Base) +#define TYPELOC(Class, Base) \ +  class Class##TypeLoc; +#include "clang/AST/TypeLocNodes.def" +  /// \brief Base wrapper for a particular "section" of type source info.  ///  /// A client should use the TypeLoc subclasses through cast/dyn_cast in order to @@ -34,12 +39,28 @@ protected:    void *Data;  public: +  /// The kinds of TypeLocs.  Equivalent to the Type::TypeClass enum, +  /// except it also defines a Qualified enum that corresponds to the +  /// QualifiedLoc class. +  enum TypeLocClass { +#define ABSTRACT_TYPE(Class, Base) +#define TYPE(Class, Base) \ +    Class = Type::Class, +#include "clang/AST/TypeNodes.def" +    Qualified +  }; +    TypeLoc() : Ty(0), Data(0) { }    TypeLoc(QualType ty, void *opaqueData)      : Ty(ty.getAsOpaquePtr()), Data(opaqueData) { }    TypeLoc(Type *ty, void *opaqueData)      : Ty(ty), Data(opaqueData) { } +  TypeLocClass getTypeLocClass() const { +    if (getType().hasQualifiers()) return Qualified; +    return (TypeLocClass) getType()->getTypeClass(); +  } +    bool isNull() const { return !Ty; }    operator bool() const { return Ty; } @@ -48,35 +69,45 @@ public:    /// \brief Get the type for which this source info wrapper provides    /// information. -  QualType getSourceType() const { return QualType::getFromOpaquePtr(Ty); } +  QualType getType() const { +    return QualType::getFromOpaquePtr(Ty); +  } -  Type *getSourceTypePtr() const { +  Type *getTypePtr() const {      return QualType::getFromOpaquePtr(Ty).getTypePtr();    }    /// \brief Get the pointer where source information is stored. -  void *getOpaqueData() const { return Data; } - -  SourceRange getSourceRange() const; - -  /// \brief Find the TypeSpecLoc that is part of this TypeLoc. -  TypeSpecLoc getTypeSpecLoc() const; +  void *getOpaqueData() const { +    return Data; +  } -  /// \brief Find the TypeSpecLoc that is part of this TypeLoc and return its -  /// SourceRange. -  SourceRange getTypeSpecRange() const; +  SourceRange getSourceRange() const { +    return getSourceRangeImpl(*this); +  }    /// \brief Returns the size of the type source info data block.    unsigned getFullDataSize() const { -    return getFullDataSizeForType(getSourceType()); +    return getFullDataSizeForType(getType());    }    /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the    /// TypeLoc is a PointerLoc and next TypeLoc is for "int". -  TypeLoc getNextTypeLoc() const; +  TypeLoc getNextTypeLoc() const { +    return getNextTypeLocImpl(*this); +  }    /// \brief Skips past any qualifiers, if this is qualified. -  UnqualTypeLoc getUnqualifiedLoc() const; +  UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header + +  /// \brief Initializes this to state that every location in this +  /// type is the given location. +  /// +  /// This method exists to provide a simple transition for code that +  /// relies on location-less types. +  void initialize(SourceLocation Loc) const { +    initializeImpl(*this, Loc); +  }    friend bool operator==(const TypeLoc &LHS, const TypeLoc &RHS) {      return LHS.Ty == RHS.Ty && LHS.Data == RHS.Data; @@ -87,6 +118,11 @@ public:    }    static bool classof(const TypeLoc *TL) { return true; } + +private: +  static void initializeImpl(TypeLoc TL, SourceLocation Loc); +  static TypeLoc getNextTypeLocImpl(TypeLoc TL); +  static SourceRange getSourceRangeImpl(TypeLoc TL);  };  /// \brief Wrapper of type source information for a type with @@ -96,12 +132,16 @@ public:    UnqualTypeLoc() {}    UnqualTypeLoc(Type *Ty, void *Data) : TypeLoc(Ty, Data) {} -  Type *getSourceTypePtr() const { +  Type *getTypePtr() const {      return reinterpret_cast<Type*>(Ty);    } +  TypeLocClass getTypeLocClass() const { +    return (TypeLocClass) getTypePtr()->getTypeClass(); +  } +    static bool classof(const TypeLoc *TL) { -    return !TL->getSourceType().hasQualifiers(); +    return !TL->getType().hasQualifiers();    }    static bool classof(const UnqualTypeLoc *TL) { return true; }  }; @@ -111,14 +151,24 @@ public:  ///  /// Currently, we intentionally do not provide source location for  /// type qualifiers. -class QualifiedLoc : public TypeLoc { +class QualifiedTypeLoc : public TypeLoc {  public:    SourceRange getSourceRange() const {      return SourceRange();    }    UnqualTypeLoc getUnqualifiedLoc() const { -    return UnqualTypeLoc(getSourceTypePtr(), Data); +    return UnqualTypeLoc(getTypePtr(), Data); +  } + +  /// Initializes the local data of this type source info block to +  /// provide no information. +  void initializeLocal(SourceLocation Loc) { +    // do nothing +  } + +  TypeLoc getNextTypeLoc() const { +    return getUnqualifiedLoc();    }    /// \brief Returns the size of the type source info data block that is @@ -132,52 +182,21 @@ public:    /// \brief Returns the size of the type source info data block.    unsigned getFullDataSize() const {      return getLocalDataSize() +  -      getFullDataSizeForType(getSourceType().getUnqualifiedType()); +      getFullDataSizeForType(getType().getUnqualifiedType());    }    static bool classof(const TypeLoc *TL) { -    return TL->getSourceType().hasQualifiers(); +    return TL->getType().hasQualifiers();    } -  static bool classof(const QualifiedLoc *TL) { return true; } +  static bool classof(const QualifiedTypeLoc *TL) { return true; }  };  inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { -  if (isa<QualifiedLoc>(this)) -    return cast<QualifiedLoc>(this)->getUnqualifiedLoc(); +  if (isa<QualifiedTypeLoc>(this)) +    return cast<QualifiedTypeLoc>(this)->getUnqualifiedLoc();    return cast<UnqualTypeLoc>(*this);  } -/// \brief Base wrapper of type source info data for type-spec types. -class TypeSpecLoc : public UnqualTypeLoc  { -public: -  static bool classof(const TypeLoc *TL) { -    return (UnqualTypeLoc::classof(TL) && -            classof(static_cast<const UnqualTypeLoc*>(TL))); -  } -  static bool classof(const UnqualTypeLoc *TL); -  static bool classof(const TypeSpecLoc *TL) { return true; } -}; - -inline SourceRange TypeLoc::getTypeSpecRange() const { -  return getTypeSpecLoc().getSourceRange(); -} -   -/// \brief Base wrapper of type source info data for types part of a declarator, -/// excluding type-spec types. -class DeclaratorLoc : public UnqualTypeLoc  { -public: -  /// \brief Find the TypeSpecLoc that is part of this DeclaratorLoc. -  TypeSpecLoc getTypeSpecLoc() const; - -  static bool classof(const TypeLoc *TL) { -    return (UnqualTypeLoc::classof(TL) && -            classof(static_cast<const UnqualTypeLoc*>(TL))); -  } -  static bool classof(const UnqualTypeLoc *TL); -  static bool classof(const DeclaratorLoc *TL) { return true; } -}; - -  /// A metaprogramming base class for TypeLoc classes which correspond  /// to a particular Type subclass.  It is accepted for a single  /// TypeLoc class to correspond to multiple Type classes. @@ -196,9 +215,19 @@ public:  /// getExtraLocalDataSize(); getExtraLocalData() will then point to  /// this extra memory.  /// -/// TypeLocs with an inner type should override hasInnerType() and -/// getInnerType(); getInnerTypeLoc() will then point to this inner -/// type's location data. +/// TypeLocs with an inner type should define +///   QualType getInnerType() const +/// and getInnerTypeLoc() will then point to this inner type's +/// location data. +/// +/// A word about hierarchies: this template is not designed to be +/// derived from multiple times in a hierarchy.  It is also not +/// designed to be used for classes where subtypes might provide +/// different amounts of source information.  It should be subclassed +/// only at the deepest portion of the hierarchy where all children +/// have identical source information; if that's an abstract type, +/// then further descendents should inherit from +/// InheritingConcreteTypeLoc instead.  template <class Base, class Derived, class TypeClass, class LocalData>  class ConcreteTypeLoc : public Base { @@ -215,25 +244,19 @@ public:      return asDerived()->getLocalDataSize() + getInnerTypeSize();    } -  static bool classof(const TypeLoc *TL) { -    return Derived::classofType(TL->getSourceTypePtr()); -  } -  static bool classof(const UnqualTypeLoc *TL) { -    return Derived::classofType(TL->getSourceTypePtr()); -  } -  static bool classof(const Derived *TL) { -    return true; -  } -    static bool classofType(const Type *Ty) {      return TypeClass::classof(Ty);    } -protected: +  TypeLoc getNextTypeLoc() const { +    return getNextTypeLoc(asDerived()->getInnerType()); +  } +    TypeClass *getTypePtr() const { -    return cast<TypeClass>(Base::getSourceTypePtr()); +    return cast<TypeClass>(Base::getTypePtr());    } +protected:    unsigned getExtraLocalDataSize() const {      return 0;    } @@ -253,136 +276,151 @@ protected:      return static_cast<char*>(Base::Data) + asDerived()->getLocalDataSize();    } -  bool hasInnerType() const { -    return false; -  } +  struct HasNoInnerType {}; +  HasNoInnerType getInnerType() const { return HasNoInnerType(); }    TypeLoc getInnerTypeLoc() const { -    assert(asDerived()->hasInnerType());      return TypeLoc(asDerived()->getInnerType(), getNonLocalData());    }  private:    unsigned getInnerTypeSize() const { -    if (asDerived()->hasInnerType()) -      return getInnerTypeLoc().getFullDataSize(); +    return getInnerTypeSize(asDerived()->getInnerType()); +  } + +  unsigned getInnerTypeSize(HasNoInnerType _) const {      return 0;    } -  // Required here because my metaprogramming is too weak to avoid it. -  QualType getInnerType() const { -    assert(0 && "getInnerType() not overridden"); -    return QualType(); +  unsigned getInnerTypeSize(QualType _) const { +    return getInnerTypeLoc().getFullDataSize();    } -}; +  TypeLoc getNextTypeLoc(HasNoInnerType _) const { +    return TypeLoc(); +  } -struct DefaultTypeSpecLocInfo { -  SourceLocation StartLoc; +  TypeLoc getNextTypeLoc(QualType T) const { +    return TypeLoc(T, getNonLocalData()); +  }  }; -/// \brief The default wrapper for type-spec types that are not handled by -/// another specific wrapper. -class DefaultTypeSpecLoc : public ConcreteTypeLoc<TypeSpecLoc, -                                                  DefaultTypeSpecLoc, -                                                  Type, -                                                  DefaultTypeSpecLocInfo> { +/// A metaprogramming class designed for concrete subtypes of abstract +/// types where all subtypes share equivalently-structured source +/// information.  See the note on ConcreteTypeLoc. +template <class Base, class Derived, class TypeClass> +class InheritingConcreteTypeLoc : public Base {  public: -  SourceLocation getStartLoc() const { -    return getLocalData()->StartLoc; +  static bool classof(const TypeLoc *TL) { +    return Derived::classofType(TL->getTypePtr());    } -  void setStartLoc(SourceLocation Loc) { -    getLocalData()->StartLoc = Loc; +  static bool classof(const UnqualTypeLoc *TL) { +    return Derived::classofType(TL->getTypePtr());    } -  SourceRange getSourceRange() const { -    return SourceRange(getStartLoc(), getStartLoc()); +  static bool classof(const Derived *TL) { +    return true;    } -  static bool classofType(const Type *T); +  TypeClass *getTypePtr() const { +    return cast<TypeClass>(Base::getTypePtr()); +  }  }; - -struct TypedefLocInfo { +struct TypeSpecLocInfo {    SourceLocation NameLoc;  }; -/// \brief Wrapper for source info for typedefs. -class TypedefLoc : public ConcreteTypeLoc<TypeSpecLoc,TypedefLoc, -                                          TypedefType,TypedefLocInfo> { +/// \brief A reasonable base class for TypeLocs that correspond to +/// types that are written as a type-specifier. +template <class Derived, class TypeClass, class LocalData = TypeSpecLocInfo> +class TypeSpecTypeLoc +  : public ConcreteTypeLoc<UnqualTypeLoc, Derived, TypeClass, LocalData> {  public:    SourceLocation getNameLoc() const { -    return getLocalData()->NameLoc; +    return this->getLocalData()->NameLoc;    }    void setNameLoc(SourceLocation Loc) { -    getLocalData()->NameLoc = Loc; +    this->getLocalData()->NameLoc = Loc;    }    SourceRange getSourceRange() const {      return SourceRange(getNameLoc(), getNameLoc());    } +  void initializeLocal(SourceLocation Loc) { +    setNameLoc(Loc); +  } +}; +/// \brief Wrapper for source info for typedefs. +class TypedefTypeLoc : public TypeSpecTypeLoc<TypedefTypeLoc,TypedefType> { +public:    TypedefDecl *getTypedefDecl() const {      return getTypePtr()->getDecl();    }  }; -struct ObjCInterfaceLocInfo { -  SourceLocation NameLoc; +/// \brief Wrapper for source info for builtin types. +class BuiltinTypeLoc : public TypeSpecTypeLoc<BuiltinTypeLoc, +                                              BuiltinType> {  }; -/// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceLoc : public ConcreteTypeLoc<TypeSpecLoc, -                                                ObjCInterfaceLoc, -                                                ObjCInterfaceType, -                                                ObjCInterfaceLocInfo> { -public: -  SourceLocation getNameLoc() const { -    return getLocalData()->NameLoc; -  } -  void setNameLoc(SourceLocation Loc) { -    getLocalData()->NameLoc = Loc; -  } -  SourceRange getSourceRange() const { -    return SourceRange(getNameLoc(), getNameLoc()); -  } +/// \brief Wrapper for template type parameters. +class TemplateTypeParmTypeLoc : public TypeSpecTypeLoc<TemplateTypeParmTypeLoc, +                                                       TemplateTypeParmType> { +}; -  ObjCInterfaceDecl *getIFaceDecl() const { -    return getTypePtr()->getDecl(); -  } +/// \brief Wrapper for substituted template type parameters. +class SubstTemplateTypeParmTypeLoc : +    public TypeSpecTypeLoc<SubstTemplateTypeParmTypeLoc, +                           SubstTemplateTypeParmType> {  };  struct ObjCProtocolListLocInfo { -  SourceLocation LAngleLoc, RAngleLoc; +  SourceLocation LAngleLoc; +  SourceLocation RAngleLoc;  }; -/// \brief Wrapper for source info for ObjC protocol lists. -class ObjCProtocolListLoc : public ConcreteTypeLoc<TypeSpecLoc, -                                                   ObjCProtocolListLoc, -                                                   ObjCProtocolListType, -                                                   ObjCProtocolListLocInfo> { +// A helper class for defining ObjC TypeLocs that can qualified with +// protocols. +// +// TypeClass basically has to be either ObjCInterfaceType or +// ObjCObjectPointerType. +template <class Derived, class TypeClass, class LocalData> +class ObjCProtocolListTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, +                                                       Derived, +                                                       TypeClass, +                                                       LocalData> {    // SourceLocations are stored after Info, one for each Protocol.    SourceLocation *getProtocolLocArray() const { -    return (SourceLocation*) getExtraLocalData(); +    return (SourceLocation*) this->getExtraLocalData(); +  } + +protected: +  void initializeLocalBase(SourceLocation Loc) { +    setLAngleLoc(Loc); +    setRAngleLoc(Loc); +    for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) +      setProtocolLoc(i, Loc);    }  public:    SourceLocation getLAngleLoc() const { -    return getLocalData()->LAngleLoc; +    return this->getLocalData()->LAngleLoc;    }    void setLAngleLoc(SourceLocation Loc) { -    getLocalData()->LAngleLoc = Loc; +    this->getLocalData()->LAngleLoc = Loc;    }    SourceLocation getRAngleLoc() const { -    return getLocalData()->RAngleLoc; +    return this->getLocalData()->RAngleLoc;    }    void setRAngleLoc(SourceLocation Loc) { -    getLocalData()->RAngleLoc = Loc; +    this->getLocalData()->RAngleLoc = Loc;    }    unsigned getNumProtocols() const { -    return getTypePtr()->getNumProtocols(); +    return this->getTypePtr()->getNumProtocols();    }    SourceLocation getProtocolLoc(unsigned i) const { @@ -396,165 +434,229 @@ public:    ObjCProtocolDecl *getProtocol(unsigned i) const {      assert(i < getNumProtocols() && "Index is out of bounds!"); -    return *(getTypePtr()->qual_begin() + i); +    return *(this->getTypePtr()->qual_begin() + i);    } -  TypeLoc getBaseTypeLoc() const { -    return getInnerTypeLoc(); -  } -    SourceRange getSourceRange() const {      return SourceRange(getLAngleLoc(), getRAngleLoc());    } -  /// \brief Returns the size of the type source info data block that is -  /// specific to this type. -  unsigned getExtraLocalDataSize() const { -    return getNumProtocols() * sizeof(SourceLocation); +  void initializeLocal(SourceLocation Loc) { +    initializeLocalBase(Loc);    } -  bool hasInnerType() const { return true; } -  QualType getInnerType() const { return getTypePtr()->getBaseType(); } +  unsigned getExtraLocalDataSize() const { +    return this->getNumProtocols() * sizeof(SourceLocation); +  }  }; -struct PointerLocInfo { -  SourceLocation StarLoc; +struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo { +  SourceLocation NameLoc;  }; -/// \brief Wrapper for source info for pointers. -class PointerLoc : public ConcreteTypeLoc<DeclaratorLoc, -                                          PointerLoc, -                                          PointerType, -                                          PointerLocInfo> { +/// \brief Wrapper for source info for ObjC interfaces. +class ObjCInterfaceTypeLoc : +    public ObjCProtocolListTypeLoc<ObjCInterfaceTypeLoc, +                                   ObjCInterfaceType, +                                   ObjCInterfaceLocInfo> {  public: -  SourceLocation getStarLoc() const { -    return getLocalData()->StarLoc; -  } -  void setStarLoc(SourceLocation Loc) { -    getLocalData()->StarLoc = Loc; +  ObjCInterfaceDecl *getIFaceDecl() const { +    return getTypePtr()->getDecl();    } -  TypeLoc getPointeeLoc() const { -    return getInnerTypeLoc(); +  SourceLocation getNameLoc() const { +    return getLocalData()->NameLoc;    } -  /// \brief Find the TypeSpecLoc that is part of this PointerLoc. -  TypeSpecLoc getTypeSpecLoc() const { -    return getPointeeLoc().getTypeSpecLoc(); +  void setNameLoc(SourceLocation Loc) { +    getLocalData()->NameLoc = Loc;    }    SourceRange getSourceRange() const { -    return SourceRange(getStarLoc(), getStarLoc()); +    if (getNumProtocols())  +      return SourceRange(getNameLoc(), getRAngleLoc()); +    else +      return SourceRange(getNameLoc(), getNameLoc());    } -  bool hasInnerType() const { return true; } -  QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +  void initializeLocal(SourceLocation Loc) { +    initializeLocalBase(Loc); +    setNameLoc(Loc); +  }  }; -struct BlockPointerLocInfo { -  SourceLocation CaretLoc; +struct ObjCObjectPointerLocInfo : ObjCProtocolListLocInfo { +  SourceLocation StarLoc; +  bool HasProtocols; +  bool HasBaseType;  }; -/// \brief Wrapper for source info for block pointers. -class BlockPointerLoc : public ConcreteTypeLoc<DeclaratorLoc, -                                               BlockPointerLoc, -                                               BlockPointerType, -                                               BlockPointerLocInfo> { +/// Wraps an ObjCPointerType with source location information.  Note +/// that not all ObjCPointerTypes actually have a star location; nor +/// are protocol locations necessarily written in the source just +/// because they're present on the type. +class ObjCObjectPointerTypeLoc : +    public ObjCProtocolListTypeLoc<ObjCObjectPointerTypeLoc, +                                   ObjCObjectPointerType, +                                   ObjCObjectPointerLocInfo> {  public: -  SourceLocation getCaretLoc() const { -    return getLocalData()->CaretLoc; +  bool hasProtocolsAsWritten() const { +    return getLocalData()->HasProtocols;    } -  void setCaretLoc(SourceLocation Loc) { -    getLocalData()->CaretLoc = Loc; + +  void setHasProtocolsAsWritten(bool HasProtocols) { +    getLocalData()->HasProtocols = HasProtocols;    } -  TypeLoc getPointeeLoc() const { -    return getInnerTypeLoc(); +  bool hasBaseTypeAsWritten() const { +    return getLocalData()->HasBaseType;    } -  /// \brief Find the TypeSpecLoc that is part of this BlockPointerLoc. -  TypeSpecLoc getTypeSpecLoc() const { -    return getPointeeLoc().getTypeSpecLoc(); +  void setHasBaseTypeAsWritten(bool HasBaseType) { +    getLocalData()->HasBaseType = HasBaseType; +  } + +  SourceLocation getStarLoc() const { +    return getLocalData()->StarLoc; +  } + +  void setStarLoc(SourceLocation Loc) { +    getLocalData()->StarLoc = Loc;    }    SourceRange getSourceRange() const { -    return SourceRange(getCaretLoc(), getCaretLoc()); +    // Being written with protocols is incompatible with being written +    // with a star. +    if (hasProtocolsAsWritten()) +      return SourceRange(getLAngleLoc(), getRAngleLoc()); +    else +      return SourceRange(getStarLoc(), getStarLoc()); +  } + +  void initializeLocal(SourceLocation Loc) { +    initializeLocalBase(Loc); +    setHasProtocolsAsWritten(false); +    setHasBaseTypeAsWritten(false); +    setStarLoc(Loc); +  } + +  TypeLoc getBaseTypeLoc() const { +    return getInnerTypeLoc();    } -  bool hasInnerType() const { return true; } -  QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +  QualType getInnerType() const { +    return getTypePtr()->getPointeeType(); +  }  }; -struct MemberPointerLocInfo { +struct PointerLikeLocInfo {    SourceLocation StarLoc;  }; -/// \brief Wrapper for source info for member pointers. -class MemberPointerLoc : public ConcreteTypeLoc<DeclaratorLoc, -                                                MemberPointerLoc, -                                                MemberPointerType, -                                                MemberPointerLocInfo> { -public: -  SourceLocation getStarLoc() const { -    return getLocalData()->StarLoc; +/// A base class for  +template <class Derived, class TypeClass, class LocalData = PointerLikeLocInfo> +class PointerLikeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, Derived, +                                                  TypeClass, LocalData> { +public:   +  SourceLocation getSigilLoc() const { +    return this->getLocalData()->StarLoc;    } -  void setStarLoc(SourceLocation Loc) { -    getLocalData()->StarLoc = Loc; +  void setSigilLoc(SourceLocation Loc) { +    this->getLocalData()->StarLoc = Loc;    }    TypeLoc getPointeeLoc() const { -    return getInnerTypeLoc(); +    return this->getInnerTypeLoc();    } -  /// \brief Find the TypeSpecLoc that is part of this MemberPointerLoc. -  TypeSpecLoc getTypeSpecLoc() const { -    return getPointeeLoc().getTypeSpecLoc(); +  SourceRange getSourceRange() const { +    return SourceRange(getSigilLoc(), getSigilLoc());    } -  SourceRange getSourceRange() const { -    return SourceRange(getStarLoc(), getStarLoc()); +  void initializeLocal(SourceLocation Loc) { +    setSigilLoc(Loc);    } -  bool hasInnerType() const { return true; } -  QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +  QualType getInnerType() const { +    return this->getTypePtr()->getPointeeType(); +  }  }; -struct ReferenceLocInfo { -  SourceLocation AmpLoc; +/// \brief Wrapper for source info for pointers. +class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, +                                                 PointerType> { +public: +  SourceLocation getStarLoc() const { +    return getSigilLoc(); +  } +  void setStarLoc(SourceLocation Loc) { +    setSigilLoc(Loc); +  }  }; -/// \brief Wrapper for source info for references. -class ReferenceLoc : public ConcreteTypeLoc<DeclaratorLoc, -                                            ReferenceLoc, -                                            ReferenceType, -                                            ReferenceLocInfo> { + +/// \brief Wrapper for source info for block pointers. +class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, +                                                      BlockPointerType> {  public: -  SourceLocation getAmpLoc() const { -    return getLocalData()->AmpLoc; +  SourceLocation getCaretLoc() const { +    return getSigilLoc();    } -  void setAmpLoc(SourceLocation Loc) { -    getLocalData()->AmpLoc = Loc; +  void setCaretLoc(SourceLocation Loc) { +    setSigilLoc(Loc);    } +}; -  TypeLoc getPointeeLoc() const { -    return TypeLoc(getTypePtr()->getPointeeType(), getNonLocalData()); + +/// \brief Wrapper for source info for member pointers. +class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, +                                                       MemberPointerType> { +public: +  SourceLocation getStarLoc() const { +    return getSigilLoc(); +  } +  void setStarLoc(SourceLocation Loc) { +    setSigilLoc(Loc);    } +}; -  /// \brief Find the TypeSpecLoc that is part of this ReferenceLoc. -  TypeSpecLoc getTypeSpecLoc() const { -    return getPointeeLoc().getTypeSpecLoc(); + +class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, +                                                   ReferenceType> { +public: +  QualType getInnerType() const { +    return getTypePtr()->getPointeeTypeAsWritten();    } +}; -  SourceRange getSourceRange() const { -    return SourceRange(getAmpLoc(), getAmpLoc()); +class LValueReferenceTypeLoc : +    public InheritingConcreteTypeLoc<ReferenceTypeLoc, +                                     LValueReferenceTypeLoc, +                                     LValueReferenceType> { +public: +  SourceLocation getAmpLoc() const { +    return getSigilLoc(); +  } +  void setAmpLoc(SourceLocation Loc) { +    setSigilLoc(Loc);    } +}; -  bool hasInnerType() const { return true; } -  QualType getInnerType() const { return getTypePtr()->getPointeeType(); } +class RValueReferenceTypeLoc : +    public InheritingConcreteTypeLoc<ReferenceTypeLoc, +                                     RValueReferenceTypeLoc, +                                     RValueReferenceType> { +public: +  SourceLocation getAmpAmpLoc() const { +    return getSigilLoc(); +  } +  void setAmpAmpLoc(SourceLocation Loc) { +    setSigilLoc(Loc); +  }  }; @@ -563,10 +665,10 @@ struct FunctionLocInfo {  };  /// \brief Wrapper for source info for functions. -class FunctionLoc : public ConcreteTypeLoc<DeclaratorLoc, -                                           FunctionLoc, -                                           FunctionType, -                                           FunctionLocInfo> { +class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, +                                               FunctionTypeLoc, +                                               FunctionType, +                                               FunctionLocInfo> {    // ParmVarDecls* are stored after Info, one for each argument.    ParmVarDecl **getParmArray() const {      return (ParmVarDecl**) getExtraLocalData(); @@ -601,24 +703,38 @@ public:      return getInnerTypeLoc();    } -  /// \brief Find the TypeSpecLoc that is part of this FunctionLoc. -  TypeSpecLoc getTypeSpecLoc() const { -    return getResultLoc().getTypeSpecLoc(); -  }    SourceRange getSourceRange() const {      return SourceRange(getLParenLoc(), getRParenLoc());    } +  void initializeLocal(SourceLocation Loc) { +    setLParenLoc(Loc); +    setRParenLoc(Loc); +    for (unsigned i = 0, e = getNumArgs(); i != e; ++i) +      setArg(i, NULL); +  } +    /// \brief Returns the size of the type source info data block that is    /// specific to this type.    unsigned getExtraLocalDataSize() const {      return getNumArgs() * sizeof(ParmVarDecl*);    } -  bool hasInnerType() const { return true; }    QualType getInnerType() const { return getTypePtr()->getResultType(); }  }; +class FunctionProtoTypeLoc : +    public InheritingConcreteTypeLoc<FunctionTypeLoc, +                                     FunctionProtoTypeLoc, +                                     FunctionProtoType> { +}; + +class FunctionNoProtoTypeLoc : +    public InheritingConcreteTypeLoc<FunctionTypeLoc, +                                     FunctionNoProtoTypeLoc, +                                     FunctionNoProtoType> { +}; +  struct ArrayLocInfo {    SourceLocation LBracketLoc, RBracketLoc; @@ -626,10 +742,10 @@ struct ArrayLocInfo {  };  /// \brief Wrapper for source info for arrays. -class ArrayLoc : public ConcreteTypeLoc<DeclaratorLoc, -                                        ArrayLoc, -                                        ArrayType, -                                        ArrayLocInfo> { +class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, +                                            ArrayTypeLoc, +                                            ArrayType, +                                            ArrayLocInfo> {  public:    SourceLocation getLBracketLoc() const {      return getLocalData()->LBracketLoc; @@ -656,18 +772,108 @@ public:      return getInnerTypeLoc();    } -  /// \brief Find the TypeSpecLoc that is part of this ArrayLoc. -  TypeSpecLoc getTypeSpecLoc() const { -    return getElementLoc().getTypeSpecLoc(); -  }    SourceRange getSourceRange() const {      return SourceRange(getLBracketLoc(), getRBracketLoc());    } -  bool hasInnerType() const { return true; } +  void initializeLocal(SourceLocation Loc) { +    setLBracketLoc(Loc); +    setRBracketLoc(Loc); +    setSizeExpr(NULL); +  } +    QualType getInnerType() const { return getTypePtr()->getElementType(); }  }; +class ConstantArrayTypeLoc : +    public InheritingConcreteTypeLoc<ArrayTypeLoc, +                                     ConstantArrayTypeLoc, +                                     ConstantArrayType> { +}; + +class IncompleteArrayTypeLoc : +    public InheritingConcreteTypeLoc<ArrayTypeLoc, +                                     IncompleteArrayTypeLoc, +                                     IncompleteArrayType> { +}; + +class DependentSizedArrayTypeLoc : +    public InheritingConcreteTypeLoc<ArrayTypeLoc, +                                     DependentSizedArrayTypeLoc, +                                     DependentSizedArrayType> { + +}; + +class VariableArrayTypeLoc : +    public InheritingConcreteTypeLoc<ArrayTypeLoc, +                                     VariableArrayTypeLoc, +                                     VariableArrayType> { +}; + +// None of these types have proper implementations yet. + +class VectorTypeLoc : public TypeSpecTypeLoc<VectorTypeLoc, VectorType> { +}; + +class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc, +                                                          ExtVectorTypeLoc, +                                                          ExtVectorType> { +}; + +// For some reason, this isn't a subtype of VectorType. +class DependentSizedExtVectorTypeLoc : +    public TypeSpecTypeLoc<DependentSizedExtVectorTypeLoc, +                           DependentSizedExtVectorType> { +}; + +class FixedWidthIntTypeLoc : public TypeSpecTypeLoc<FixedWidthIntTypeLoc, +                                                    FixedWidthIntType> { +}; + +class ComplexTypeLoc : public TypeSpecTypeLoc<ComplexTypeLoc, +                                              ComplexType> { +}; + +class TypeOfExprTypeLoc : public TypeSpecTypeLoc<TypeOfExprTypeLoc, +                                                 TypeOfExprType> { +}; + +class TypeOfTypeLoc : public TypeSpecTypeLoc<TypeOfTypeLoc, TypeOfType> { +}; + +class DecltypeTypeLoc : public TypeSpecTypeLoc<DecltypeTypeLoc, DecltypeType> { +}; + +class TagTypeLoc : public TypeSpecTypeLoc<TagTypeLoc, TagType> { +}; + +class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, +                                                       RecordTypeLoc, +                                                       RecordType> { +}; + +class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, +                                                     EnumTypeLoc, +                                                     EnumType> { +}; + +class ElaboratedTypeLoc : public TypeSpecTypeLoc<ElaboratedTypeLoc, +                                                 ElaboratedType> { +}; + +class TemplateSpecializationTypeLoc +  : public TypeSpecTypeLoc<TemplateSpecializationTypeLoc, +                           TemplateSpecializationType> { +}; + +class QualifiedNameTypeLoc : public TypeSpecTypeLoc<QualifiedNameTypeLoc, +                                                    QualifiedNameType> { +}; + +class TypenameTypeLoc : public TypeSpecTypeLoc<TypenameTypeLoc, +                                               TypenameType> { +}; +  }  #endif diff --git a/include/clang/AST/TypeLocBuilder.h b/include/clang/AST/TypeLocBuilder.h new file mode 100644 index 000000000000..4e1fbaaf4c5e --- /dev/null +++ b/include/clang/AST/TypeLocBuilder.h @@ -0,0 +1,122 @@ +//===--- TypeLocBuilder.h - Type Source Info collector ----------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//  This files defines TypeLocBuilder, a class for building TypeLocs +//  bottom-up. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_TYPELOCBUILDER_H +#define LLVM_CLANG_AST_TYPELOCBUILDER_H + +#include "clang/AST/TypeLoc.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + +class TypeLocBuilder { +  enum { InlineCapacity = 8 * sizeof(SourceLocation) }; + +  /// The underlying location-data buffer.  Data grows from the end +  /// of the buffer backwards. +  char *Buffer; + +  /// The capacity of the current buffer. +  size_t Capacity; + +  /// The index of the first occupied byte in the buffer. +  size_t Index; + +#ifndef NDEBUG +  /// The last type pushed on this builder. +  QualType LastTy; +#endif +     +  /// The inline buffer. +  char InlineBuffer[InlineCapacity]; + + public: +  TypeLocBuilder() +    : Buffer(InlineBuffer), Capacity(InlineCapacity), Index(InlineCapacity) +  {} + +  ~TypeLocBuilder() { +    if (Buffer != InlineBuffer) +      delete[] Buffer; +  } + +  /// Ensures that this buffer has at least as much capacity as described. +  void reserve(size_t Requested) { +    if (Requested > Capacity) +      // For now, match the request exactly. +      grow(Requested); +  } + +  /// Pushes space for a new TypeLoc onto the given type.  Invalidates +  /// any TypeLocs previously retrieved from this builder. +  template <class TyLocType> TyLocType push(QualType T) { +#ifndef NDEBUG +    QualType TLast = TypeLoc(T, 0).getNextTypeLoc().getType(); +    assert(TLast == LastTy && +           "mismatch between last type and new type's inner type"); +    LastTy = T; +#endif + +    size_t LocalSize = cast<TyLocType>(TypeLoc(T, 0)).getLocalDataSize(); + +    // If we need to grow, grow by a factor of 2. +    if (LocalSize > Index) { +      size_t RequiredCapacity = Capacity + (LocalSize - Index); +      size_t NewCapacity = Capacity * 2; +      while (RequiredCapacity > NewCapacity) +        NewCapacity *= 2; +      grow(NewCapacity); +    } + +    Index -= LocalSize; + +    return cast<TyLocType>(TypeLoc(T, &Buffer[Index])); +  } + +  /// Creates a DeclaratorInfo for the given type. +  DeclaratorInfo *getDeclaratorInfo(ASTContext& Context, QualType T) { +#ifndef NDEBUG +    assert(T == LastTy && "type doesn't match last type pushed!"); +#endif + +    size_t FullDataSize = Capacity - Index; +    DeclaratorInfo *DI = Context.CreateDeclaratorInfo(T, FullDataSize); +    memcpy(DI->getTypeLoc().getOpaqueData(), &Buffer[Index], FullDataSize); +    return DI; +  } + + private: +  /// Grow to the given capacity. +  void grow(size_t NewCapacity) { +    assert(NewCapacity > Capacity); + +    // Allocate the new buffer and copy the old data into it. +    char *NewBuffer = new char[NewCapacity]; +    unsigned NewIndex = Index + NewCapacity - Capacity; +    memcpy(&NewBuffer[NewIndex], +           &Buffer[Index], +           Capacity - Index); + +    if (Buffer != InlineBuffer) +      delete[] Buffer; + +    Buffer = NewBuffer; +    Capacity = NewCapacity; +    Index = NewIndex; +  } +}; + +} + +#endif diff --git a/include/clang/AST/TypeLocNodes.def b/include/clang/AST/TypeLocNodes.def index ecf7cc5c2995..4590e489e3f7 100644 --- a/include/clang/AST/TypeLocNodes.def +++ b/include/clang/AST/TypeLocNodes.def @@ -7,54 +7,32 @@  //  //===----------------------------------------------------------------------===//  // -//  This file defines the TypeLoc info database. Each node is -//  enumerated by providing its name (e.g., "PointerLoc" or "ArrayLoc"), -//  base class (e.g., "TypeSpecLoc" or "DeclaratorLoc"), and the Type subclass -//  that the TypeLoc is associated with. +//  This file defines the TypeLoc info database.  Each node is +//  enumerated by providing its core name (e.g., "Pointer" for "PointerTypeLoc") +//  and base class (e.g., "DeclaratorLoc").  All nodes except QualifiedTypeLoc +//  are associated  // -//    TYPELOC(Class, Base) - A TypeLoc subclass. +//    TYPELOC(Class, Base) - A TypeLoc subclass.  If UNQUAL_TYPELOC is +//      provided, there will be exactly one of these, Qualified.  //  //    UNQUAL_TYPELOC(Class, Base, Type) - An UnqualTypeLoc subclass.  //  //    ABSTRACT_TYPELOC(Class) - Refers to TypeSpecLoc and DeclaratorLoc.  // -//    TYPESPEC_TYPELOC(Class, Type) - A TypeLoc referring to a type-spec type. -// -//    DECLARATOR_TYPELOC(Class, Type) - A TypeLoc referring to a type part of -//    a declarator, excluding type-spec types. -//  //===----------------------------------------------------------------------===//  #ifndef UNQUAL_TYPELOC -#  define UNQUAL_TYPELOC(Class, Base, Type) TYPELOC(Class, Base) +#  define UNQUAL_TYPELOC(Class, Base) TYPELOC(Class, Base)  #endif  #ifndef ABSTRACT_TYPELOC -#  define ABSTRACT_TYPELOC(Class) TYPELOC(Class, TypeLoc) -#endif - -#ifndef TYPESPEC_TYPELOC -#  define TYPESPEC_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, TypeSpecLoc, Type) +#  define ABSTRACT_TYPELOC(Class, Base) UNQUAL_TYPELOC(Class, Base)  #endif -#ifndef DECLARATOR_TYPELOC -#  define DECLARATOR_TYPELOC(Class, Type) UNQUAL_TYPELOC(Class, DeclaratorLoc, Type) -#endif - -TYPESPEC_TYPELOC(DefaultTypeSpecLoc, Type) -TYPESPEC_TYPELOC(TypedefLoc, TypedefType) -TYPESPEC_TYPELOC(ObjCInterfaceLoc, ObjCInterfaceType) -TYPESPEC_TYPELOC(ObjCProtocolListLoc, ObjCProtocolListType) -DECLARATOR_TYPELOC(PointerLoc, PointerType) -DECLARATOR_TYPELOC(BlockPointerLoc, BlockPointerType) -DECLARATOR_TYPELOC(MemberPointerLoc, MemberPointerType) -DECLARATOR_TYPELOC(ReferenceLoc, ReferenceType) -DECLARATOR_TYPELOC(FunctionLoc, FunctionType) -DECLARATOR_TYPELOC(ArrayLoc, ArrayType) -ABSTRACT_TYPELOC(DeclaratorLoc) -ABSTRACT_TYPELOC(TypeSpecLoc) -TYPELOC(QualifiedLoc, TypeLoc) - +TYPELOC(Qualified, TypeLoc) +#define TYPE(Class, Base) UNQUAL_TYPELOC(Class, Base##Loc) +#define ABSTRACT_TYPE(Class, Base) ABSTRACT_TYPELOC(Class, Base##Loc) +#include "clang/AST/TypeNodes.def"  #undef DECLARATOR_TYPELOC  #undef TYPESPEC_TYPELOC diff --git a/include/clang/AST/TypeLocVisitor.h b/include/clang/AST/TypeLocVisitor.h index a96757f123e8..a62bb3f853bc 100644 --- a/include/clang/AST/TypeLocVisitor.h +++ b/include/clang/AST/TypeLocVisitor.h @@ -15,46 +15,38 @@  #include "clang/AST/TypeLoc.h"  #include "clang/AST/TypeVisitor.h" +#include "llvm/Support/ErrorHandling.h"  namespace clang { -#define DISPATCH(CLASS) \ -  return static_cast<ImplClass*>(this)->Visit ## CLASS(cast<CLASS>(TyLoc)) +#define DISPATCH(CLASSNAME) \ +  return static_cast<ImplClass*>(this)-> \ +    Visit##CLASSNAME(cast<CLASSNAME>(TyLoc))  template<typename ImplClass, typename RetTy=void>  class TypeLocVisitor { -  class TypeDispatch : public TypeVisitor<TypeDispatch, RetTy> { -    ImplClass *Impl; -    UnqualTypeLoc TyLoc; - -  public: -    TypeDispatch(ImplClass *impl, UnqualTypeLoc &tyLoc)  -      : Impl(impl), TyLoc(tyLoc) { } -#define TYPELOC(CLASS, BASE) -#define ABSTRACT_TYPELOC(CLASS) -#define UNQUAL_TYPELOC(CLASS, PARENT, TYPE)                       \ -    RetTy Visit##TYPE(TYPE *) {                                   \ -      return Impl->Visit##CLASS(reinterpret_cast<CLASS&>(TyLoc)); \ -    } -#include "clang/AST/TypeLocNodes.def" -  }; -  public:    RetTy Visit(TypeLoc TyLoc) { -    if (isa<QualifiedLoc>(TyLoc)) -      return static_cast<ImplClass*>(this)-> -        VisitQualifiedLoc(cast<QualifiedLoc>(TyLoc)); - -    return Visit(cast<UnqualTypeLoc>(TyLoc)); +    switch (TyLoc.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ +    case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); +#include "clang/AST/TypeLocNodes.def" +    } +    llvm::llvm_unreachable("unexpected type loc class!");    }    RetTy Visit(UnqualTypeLoc TyLoc) { -    TypeDispatch TD(static_cast<ImplClass*>(this), TyLoc); -    return TD.Visit(TyLoc.getSourceTypePtr()); +    switch (TyLoc.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ +    case TypeLoc::CLASS: DISPATCH(CLASS##TypeLoc); +#include "clang/AST/TypeLocNodes.def" +    }    }  #define TYPELOC(CLASS, PARENT)      \ -  RetTy Visit##CLASS(CLASS TyLoc) { \ +  RetTy Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \      DISPATCH(PARENT);               \    }  #include "clang/AST/TypeLocNodes.def" diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 6c6bd20e8528..c2721236af02 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -62,8 +62,6 @@ TYPE(RValueReference, ReferenceType)  TYPE(MemberPointer, Type)  ABSTRACT_TYPE(Array, Type)  TYPE(ConstantArray, ArrayType) -NON_CANONICAL_TYPE(ConstantArrayWithExpr, ConstantArrayType) -NON_CANONICAL_TYPE(ConstantArrayWithoutExpr, ConstantArrayType)  TYPE(IncompleteArray, ArrayType)  TYPE(VariableArray, ArrayType)  DEPENDENT_TYPE(DependentSizedArray, ArrayType) @@ -82,12 +80,12 @@ TYPE(Record, TagType)  TYPE(Enum, TagType)  NON_CANONICAL_TYPE(Elaborated, Type)  DEPENDENT_TYPE(TemplateTypeParm, Type) +NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type)  TYPE(TemplateSpecialization, Type)  NON_CANONICAL_TYPE(QualifiedName, Type)  DEPENDENT_TYPE(Typename, Type)  TYPE(ObjCInterface, Type)  TYPE(ObjCObjectPointer, Type) -NON_CANONICAL_TYPE(ObjCProtocolList, Type)  // These types are always leaves in the type hierarchy.  #ifdef LEAF_TYPE @@ -95,7 +93,6 @@ LEAF_TYPE(Enum)  LEAF_TYPE(Builtin)  LEAF_TYPE(FixedWidthInt)  LEAF_TYPE(ObjCInterface) -LEAF_TYPE(ObjCObjectPointer)  LEAF_TYPE(TemplateTypeParm)  #undef LEAF_TYPE  #endif diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index ffe282d3caa3..8e02ccf38209 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -60,6 +60,9 @@ public:    ~AnalysisContextManager();    AnalysisContext *getContext(const Decl *D); +   +  // Discard all previously created AnalysisContexts. +  void clear();  };  class LocationContext : public llvm::FoldingSetNode { @@ -155,12 +158,17 @@ class LocationContextManager {    llvm::FoldingSet<LocationContext> Contexts;  public: +  ~LocationContextManager(); +      StackFrameContext *getStackFrame(AnalysisContext *ctx,                                     const LocationContext *parent,                                     const Stmt *s);    ScopeContext *getScope(AnalysisContext *ctx, const LocationContext *parent,                           const Stmt *s); +   +  /// Discard all previously created LocationContext objects. +  void clear();  };  } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/AnalysisManager.h b/include/clang/Analysis/PathSensitive/AnalysisManager.h index e97f80576a8b..1a64f56ee8a4 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisManager.h +++ b/include/clang/Analysis/PathSensitive/AnalysisManager.h @@ -65,6 +65,11 @@ public:        AScope(ScopeDecl), DisplayedFunction(!displayProgress),        VisualizeEGDot(vizdot), VisualizeEGUbi(vizubi), PurgeDead(purge),        EagerlyAssume(eager), TrimGraph(trim) {} +   +  void ClearContexts() { +    LocCtxMgr.clear(); +    AnaCtxMgr.clear(); +  }    StoreManagerCreator getStoreManagerCreator() {      return CreateStoreMgr; diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 3ff253d0abf3..7a462c579f9f 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -141,9 +141,12 @@ public:                                              const VarDecl *VD,                                              const LocationContext *LC) = 0; +  typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; +      virtual const GRState *InvalidateRegion(const GRState *state,                                            const MemRegion *R, -                                          const Expr *E, unsigned Count) = 0; +                                          const Expr *E, unsigned Count, +                                          InvalidatedSymbols *IS) = 0;    // FIXME: Make out-of-line.    virtual const GRState *setExtent(const GRState *state, diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index a5e11a100665..b23a80ed481a 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -27,16 +27,16 @@  namespace clang {  class BumpVectorContext { -  llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1, bool> Alloc; +  llvm::PointerIntPair<llvm::BumpPtrAllocator*, 1> Alloc;  public:    /// Construct a new BumpVectorContext that creates a new BumpPtrAllocator    /// and destroys it when the BumpVectorContext object is destroyed. -  BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), true) {} +  BumpVectorContext() : Alloc(new llvm::BumpPtrAllocator(), 1) {}    /// Construct a new BumpVectorContext that reuses an existing    /// BumpPtrAllocator.  This BumpPtrAllocator is not destroyed when the    /// BumpVectorContext object is destroyed. -  BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, false) {} +  BumpVectorContext(llvm::BumpPtrAllocator &A) : Alloc(&A, 0) {}    ~BumpVectorContext() {      if (Alloc.getInt()) diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index 380192e9dae6..005aab3fa6a1 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -15,6 +15,7 @@  #define LLVM_CLANG_DIAGNOSTIC_H  #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/StringRef.h"  #include "llvm/Support/type_traits.h"  #include <string>  #include <vector> @@ -43,7 +44,7 @@ namespace clang {        DIAG_START_PARSE    = DIAG_START_LEX      +  300,        DIAG_START_AST      = DIAG_START_PARSE    +  300,        DIAG_START_SEMA     = DIAG_START_AST      +  100, -      DIAG_START_ANALYSIS = DIAG_START_SEMA     + 1000, +      DIAG_START_ANALYSIS = DIAG_START_SEMA     + 1100,        DIAG_UPPER_LIMIT    = DIAG_START_ANALYSIS +  100      }; @@ -107,7 +108,7 @@ public:    /// \brief Create a code modification hint that inserts the given    /// code string at a specific location.    static CodeModificationHint CreateInsertion(SourceLocation InsertionLoc, -                                              const std::string &Code) { +                                              llvm::StringRef Code) {      CodeModificationHint Hint;      Hint.InsertionLoc = InsertionLoc;      Hint.CodeToInsert = Code; @@ -125,7 +126,7 @@ public:    /// \brief Create a code modification hint that replaces the given    /// source range with the given code string.    static CodeModificationHint CreateReplacement(SourceRange RemoveRange, -                                                const std::string &Code) { +                                                llvm::StringRef Code) {      CodeModificationHint Hint;      Hint.RemoveRange = RemoveRange;      Hint.InsertionLoc = RemoveRange.getBegin(); @@ -163,6 +164,10 @@ public:      ak_nestednamespec,  // NestedNameSpecifier *      ak_declcontext      // DeclContext *    }; +   +  /// ArgumentValue - This typedef represents on argument value, which is a +  /// union discriminated by ArgumentKind, with a value. +  typedef std::pair<ArgumentKind, intptr_t> ArgumentValue;  private:    unsigned char AllExtensionsSilenced; // Used by __extension__ @@ -202,10 +207,17 @@ private:    /// ArgToStringFn - A function pointer that converts an opaque diagnostic    /// argument to a strings.  This takes the modifiers and argument that was    /// present in the diagnostic. +  /// +  /// The PrevArgs array (whose length is NumPrevArgs) indicates the previous +  /// arguments formatted for this diagnostic.  Implementations of this function +  /// can use this information to avoid redundancy across arguments. +  ///    /// This is a hack to avoid a layering violation between libbasic and libsema.    typedef void (*ArgToStringFnTy)(ArgumentKind Kind, intptr_t Val,                                    const char *Modifier, unsigned ModifierLen,                                    const char *Argument, unsigned ArgumentLen, +                                  const ArgumentValue *PrevArgs, +                                  unsigned NumPrevArgs,                                    llvm::SmallVectorImpl<char> &Output,                                    void *Cookie);    void *ArgToStringCookie; @@ -310,9 +322,10 @@ public:    void ConvertArgToString(ArgumentKind Kind, intptr_t Val,                            const char *Modifier, unsigned ModLen,                            const char *Argument, unsigned ArgLen, +                          const ArgumentValue *PrevArgs, unsigned NumPrevArgs,                            llvm::SmallVectorImpl<char> &Output) const { -    ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, Output, -                  ArgToStringCookie); +    ArgToStringFn(Kind, Val, Modifier, ModLen, Argument, ArgLen, +                  PrevArgs, NumPrevArgs, Output, ArgToStringCookie);    }    void SetArgToStringFn(ArgToStringFnTy Fn, void *Cookie) { @@ -546,7 +559,7 @@ public:    /// return Diag(...);    operator bool() const { return true; } -  void AddString(const std::string &S) const { +  void AddString(llvm::StringRef S) const {      assert(NumArgs < Diagnostic::MaxArguments &&             "Too many arguments to diagnostic!");      if (DiagObj) { @@ -581,7 +594,7 @@ public:  };  inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, -                                           const std::string &S) { +                                           llvm::StringRef S) {    DB.AddString(S);    return DB;  } diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 6971df50cb55..19b0ea3932a5 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -201,6 +201,9 @@ def warn_expected_implementation : Warning<    "@end must appear in an @implementation context">;  def error_property_ivar_decl : Error<    "property synthesize requires specification of an ivar">; +def warn_semicolon_before_method_nody : Warning< +  "semicolon before method body is ignored">, +  InGroup<DiagGroup<"semicolon-before-method-body">>;  def err_expected_field_designator : Error<    "expected a field designator, such as '.field = 4'">; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b1222a3f84eb..7a87e244f77c 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -383,6 +383,8 @@ def note_ambig_member_ref_object_type : Note<    "lookup in the object type %0 refers here">;  def note_ambig_member_ref_scope : Note<    "lookup from the current scope refers here">; +def err_qualified_member_nonclass : Error< +  "qualified member access refers to a member in %0">;  // C++ class members  def err_storageclass_invalid_for_member : Error< @@ -785,9 +787,9 @@ def err_ovl_template_candidate : Note<  def err_ovl_candidate_deleted : Note<    "candidate function has been explicitly %select{made unavailable|deleted}0">;  def err_ovl_builtin_binary_candidate : Note< -    "built-in candidate operator %0 (%1, %2)">; +    "built-in candidate %0">;  def err_ovl_builtin_unary_candidate : Note< -    "built-in candidate operator %0 (%1)">; +    "built-in candidate %0">;  def err_ovl_no_viable_function_in_init : Error<    "no matching constructor for initialization of %0">;  def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">; @@ -1112,7 +1114,17 @@ def err_explicit_instantiation_without_qualified_id_quals : Error<    "qualifier in explicit instantiation of '%0%1' requires a template-id">;  def err_explicit_instantiation_unqualified_wrong_namespace : Error<    "explicit instantiation of %q0 must occur in %1">; - +def err_explicit_instantiation_undefined_member : Error< +  "explicit instantiation of undefined %select{member class|member function|" +  "static data member}0 %1 of class template %2">; +def err_explicit_instantiation_undefined_func_template : Error< +  "explicit instantiation of undefined function template %0">; +def err_explicit_instantiation_declaration_after_definition : Error< +  "explicit instantiation declaration (with 'extern') follows explicit " +  "instantiation definition (without 'extern')">; +def note_explicit_instantiation_definition_here : Note< +  "explicit instantiation definition is here">; +    // C++ typename-specifiers  def err_typename_nested_not_found : Error<"no type named %0 in %1">;  def err_typename_nested_not_type : Error< @@ -1734,7 +1746,9 @@ def err_not_tag_in_scope : Error<  def err_cannot_form_pointer_to_member_of_reference_type : Error<    "cannot form a pointer-to-member to member %0 of reference type %1">; - +def err_incomplete_object_call : Error< +  "incomplete type in call to object of type %0">; +    def warn_condition_is_assignment : Warning<"using the result of an "    "assignment as a condition without parentheses">,    InGroup<Parentheses>; @@ -2156,6 +2170,8 @@ def err_break_not_in_loop_or_switch : Error<  def err_default_not_in_switch : Error<    "'default' statement not in switch statement">;  def err_case_not_in_switch : Error<"'case' statement not in switch statement">; +def warn_bool_switch_condition : Warning< +  "switch condition is a bool">;  def warn_case_value_overflow : Warning<    "overflow converting case value to switch condition type (%0 to %1)">;  def err_duplicate_case : Error<"duplicate case value '%0'">; @@ -2187,7 +2203,7 @@ def ext_return_has_expr : ExtWarn<  def ext_return_has_void_expr : Extension<    "void %select{function|method}1 %0 should not return void expression">;  def warn_noreturn_function_has_return_expr : Warning< -  "function %0 declared 'noreturn' should not return">, DefaultError, +  "function %0 declared 'noreturn' should not return">,    InGroup<DiagGroup<"invalid-noreturn">>;  def warn_falloff_noreturn_function : Warning<    "function declared 'noreturn' should not return">, diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 7c9113c497ef..5e7ac4f3c859 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -71,16 +71,38 @@ public:    }  }; -// FIXME: This is a lightweight shim that is used by FileManager to cache -//  'stat' system calls.  We will use it with PTH to identify if caching -//  stat calls in PTH files is a performance win. +/// \brief Abstract interface for introducing a FileManager cache for 'stat' +/// system calls, which is used by precompiled and pretokenized headers to +/// improve performance.  class StatSysCallCache { +protected: +  llvm::OwningPtr<StatSysCallCache> NextStatCache; +    public:    virtual ~StatSysCallCache() {} -  virtual int stat(const char *path, struct stat *buf) = 0; +  virtual int stat(const char *path, struct stat *buf) { +    if (getNextStatCache()) +      return getNextStatCache()->stat(path, buf); +     +    return ::stat(path, buf); +  } +   +  /// \brief Sets the next stat call cache in the chain of stat caches. +  /// Takes ownership of the given stat cache. +  void setNextStatCache(StatSysCallCache *Cache) { +    NextStatCache.reset(Cache); +  } +   +  /// \brief Retrieve the next stat call cache in the chain. +  StatSysCallCache *getNextStatCache() { return NextStatCache.get(); } + +  /// \brief Retrieve the next stat call cache in the chain, transferring +  /// ownership of this cache (and, transitively, all of the remaining caches) +  /// to the caller. +  StatSysCallCache *takeNextStatCache() { return NextStatCache.take(); }  }; -/// \brief A stat listener that can be used by FileManager to keep +/// \brief A stat "cache" that can be used by FileManager to keep  /// track of the results of stat() calls that occur throughout the  /// execution of the front end.  class MemorizeStatCalls : public StatSysCallCache { @@ -144,13 +166,22 @@ public:    FileManager();    ~FileManager(); -  /// setStatCache - Installs the provided StatSysCallCache object within -  ///  the FileManager.  Ownership of this object is transferred to the -  ///  FileManager. -  void setStatCache(StatSysCallCache *statCache) { -    StatCache.reset(statCache); -  } - +  /// \brief Installs the provided StatSysCallCache object within +  /// the FileManager.  +  /// +  /// Ownership of this object is transferred to the FileManager. +  /// +  /// \param statCache the new stat cache to install. Ownership of this +  /// object is transferred to the FileManager. +  /// +  /// \param AtBeginning whether this new stat cache must be installed at the +  /// beginning of the chain of stat caches. Otherwise, it will be added to +  /// the end of the chain. +  void addStatCache(StatSysCallCache *statCache, bool AtBeginning = false); + +  /// \brief Removes the provided StatSysCallCache object from the file manager. +  void removeStatCache(StatSysCallCache *statCache); +      /// getDirectory - Lookup, cache, and verify the specified directory.  This    /// returns null if the directory doesn't exist.    /// diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 84c2fc910d11..e06dfbb2cf1b 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -75,13 +75,13 @@ public:    /// This is intended to be used for string literals only: II->isStr("foo").    template <std::size_t StrLen>    bool isStr(const char (&Str)[StrLen]) const { -    return getLength() == StrLen-1 && !memcmp(getName(), Str, StrLen-1); +    return getLength() == StrLen-1 && !memcmp(getNameStart(), Str, StrLen-1);    } -  /// getName - Return the actual string for this identifier.  The returned -  /// string is properly null terminated. +  /// getNameStart - Return the beginning of the actual string for this +  /// identifier.  The returned string is properly null terminated.    /// -  const char *getName() const { +  const char *getNameStart() const {      if (Entry) return Entry->getKeyData();      // FIXME: This is gross. It would be best not to embed specific details      // of the PTH file format here. @@ -101,8 +101,12 @@ public:      // std::pair<IdentifierInfo, const char*>, where internal pointer      // points to the external string data.      const char* p = ((std::pair<IdentifierInfo, const char*>*) this)->second-2; -    return (((unsigned) p[0]) -        | (((unsigned) p[1]) << 8)) - 1; +    return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; +  } + +  /// getName - Return the actual identifier string. +  llvm::StringRef getName() const { +    return llvm::StringRef(getNameStart(), getLength());    }    /// hasMacroDefinition - Return true if this identifier is #defined to some @@ -232,6 +236,8 @@ public:    ///  Unlike the version in IdentifierTable, this returns a pointer instead    ///  of a reference.  If the pointer is NULL then the IdentifierInfo cannot    ///  be found. +  // +  // FIXME: Move to StringRef API.    virtual IdentifierInfo* get(const char *NameStart, const char *NameEnd) = 0;  }; @@ -333,8 +339,11 @@ public:      return *II;    } +  IdentifierInfo &CreateIdentifierInfo(llvm::StringRef Name) { +    return CreateIdentifierInfo(Name.begin(), Name.end()); +  } -  IdentifierInfo &get(const llvm::StringRef& Name) { +  IdentifierInfo &get(llvm::StringRef Name) {      return get(Name.begin(), Name.end());    } @@ -463,7 +472,7 @@ public:                                        const IdentifierInfo *Name) {      llvm::SmallString<100> SelectorName;      SelectorName = "set"; -    SelectorName.append(Name->getName(), Name->getName()+Name->getLength()); +    SelectorName += Name->getName();      SelectorName[3] = toupper(SelectorName[3]);      IdentifierInfo *SetterName =        &Idents.get(SelectorName.data(), diff --git a/include/clang/Basic/OnDiskHashTable.h b/include/clang/Basic/OnDiskHashTable.h index 65245167d8d5..2184bf3c457c 100644 --- a/include/clang/Basic/OnDiskHashTable.h +++ b/include/clang/Basic/OnDiskHashTable.h @@ -25,27 +25,6 @@  namespace clang { -// Bernstein hash function: -// This is basically copy-and-paste from StringMap.  This likely won't -// stay here, which is why I didn't both to expose this function from -// String Map. -inline unsigned BernsteinHash(const char* x) { -  unsigned int R = 0; -  for ( ; *x != '\0' ; ++x) R = R * 33 + *x; -  return R + (R >> 5); -} - -inline unsigned BernsteinHash(const char* x, unsigned n) { -  unsigned int R = 0; -  for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x; -  return R + (R >> 5); -} - -inline unsigned BernsteinHashPartial(const char* x, unsigned n, unsigned R) { -  for (unsigned i = 0 ; i < n ; ++i, ++x) R = R * 33 + *x; -  return R + (R >> 5); -} -  namespace io {  typedef uint32_t Offset; diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 7eb988f005ec..8a69cba066b3 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -685,26 +685,19 @@ public:    ///    void PrintStats() const; -  // Iteration over the source location entry table. -  typedef std::vector<SrcMgr::SLocEntry>::const_iterator sloc_entry_iterator; - -  sloc_entry_iterator sloc_entry_begin() const { -    return SLocEntryTable.begin(); -  } - -  sloc_entry_iterator sloc_entry_end() const { -    return SLocEntryTable.end(); -  } -    unsigned sloc_entry_size() const { return SLocEntryTable.size(); } -  const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const { -    assert(FID.ID < SLocEntryTable.size() && "Invalid id"); +  const SrcMgr::SLocEntry &getSLocEntry(unsigned ID) const { +    assert(ID < SLocEntryTable.size() && "Invalid id");      if (ExternalSLocEntries && -        FID.ID < SLocEntryLoaded.size() && -        !SLocEntryLoaded[FID.ID]) -      ExternalSLocEntries->ReadSLocEntry(FID.ID); -    return SLocEntryTable[FID.ID]; +        ID < SLocEntryLoaded.size() && +        !SLocEntryLoaded[ID]) +      ExternalSLocEntries->ReadSLocEntry(ID); +    return SLocEntryTable[ID]; +  } +   +  const SrcMgr::SLocEntry &getSLocEntry(FileID FID) const {     +    return getSLocEntry(FID.ID);    }    unsigned getNextOffset() const { return NextOffset; } diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index a1e0a17c882e..b88e2aaba383 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -83,7 +83,7 @@ public:    };  protected:    IntType SizeType, IntMaxType, UIntMaxType, PtrDiffType, IntPtrType, WCharType, -          Char16Type, Char32Type, Int64Type; +          WIntType, Char16Type, Char32Type, Int64Type;  public:    IntType getSizeType() const { return SizeType; }    IntType getIntMaxType() const { return IntMaxType; } @@ -93,10 +93,20 @@ public:    }    IntType getIntPtrType() const { return IntPtrType; }    IntType getWCharType() const { return WCharType; } +  IntType getWIntType() const { return WIntType; }    IntType getChar16Type() const { return Char16Type; }    IntType getChar32Type() const { return Char32Type; }    IntType getInt64Type() const { return Int64Type; } + +  /// getTypeWidth - Return the width (in bits) of the specified integer type  +  /// enum. For example, SignedInt -> getIntWidth(). +  unsigned getTypeWidth(IntType T) const; + +  /// getTypeSigned - Return whether an integer types is signed. Returns true if +  /// the type is signed; false otherwise. +  bool getTypeSigned(IntType T) const; +    /// getPointerWidth - Return the width of pointers on this target, for the    /// specified address space.    uint64_t getPointerWidth(unsigned AddrSpace) const { @@ -185,6 +195,10 @@ public:    /// For example, SignedShort -> "short".    static const char *getTypeName(IntType T); +  /// getTypeConstantSuffix - Return the constant suffix for the specified +  /// integer type enum. For example, SignedLong -> "L". +  static const char *getTypeConstantSuffix(IntType T); +    ///===---- Other target property query methods --------------------------===//    /// getTargetDefines - Appends the target-specific #define values for this @@ -192,6 +206,7 @@ public:    virtual void getTargetDefines(const LangOptions &Opts,                                  std::vector<char> &DefineBuffer) const = 0; +    /// getTargetBuiltins - Return information about target-specific builtins for    /// the current primary target, and info about which builtins are non-portable    /// across the current set of primary and secondary targets. diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 89eb3b8821ca..9573777b5f6f 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -16,6 +16,8 @@  #include "clang/Basic/SourceManager.h"  #include "llvm/ADT/OwningPtr.h" +#include "clang/Frontend/TextDiagnosticBuffer.h" +#include "clang/Basic/FileManager.h"  #include <string>  namespace clang { @@ -23,6 +25,7 @@ namespace clang {    class FileEntry;    class SourceManager;    class Diagnostic; +  class TextDiagnosticBuffer;    class HeaderSearch;    class TargetInfo;    class Preprocessor; @@ -32,18 +35,27 @@ namespace clang {  /// \brief Utility class for loading a ASTContext from a PCH file.  ///  class ASTUnit { -  Diagnostic                       &Diags; +  Diagnostic Diags; +  FileManager FileMgr; +    SourceManager                     SourceMgr;    llvm::OwningPtr<HeaderSearch>     HeaderInfo;    llvm::OwningPtr<TargetInfo>       Target;    llvm::OwningPtr<Preprocessor>     PP;    llvm::OwningPtr<ASTContext>       Ctx; - +  bool                              tempFile; +   +  // OnlyLocalDecls - when true, walking this AST should only visit declarations +  // that come from the AST itself, not from included precompiled headers. +  // FIXME: This is temporary; eventually, CIndex will always do this. +  bool                              OnlyLocalDecls; +      ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT    ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT -  ASTUnit(Diagnostic &_Diag); +  ASTUnit();  public: +  ASTUnit(DiagnosticClient *diagClient = NULL);    ~ASTUnit();    const SourceManager &getSourceManager() const { return SourceMgr; } @@ -58,14 +70,23 @@ public:    const Diagnostic &getDiagnostic() const { return Diags; }          Diagnostic &getDiagnostic()       { return Diags; } -  FileManager &getFileManager(); +  const FileManager &getFileManager() const { return FileMgr; } +        FileManager &getFileManager()       { return FileMgr; } +      const std::string &getOriginalSourceFileName(); +  const std::string &getPCHFileName(); +  void unlinkTemporaryFile() { tempFile = true; } +   +  bool getOnlyLocalDecls() const { return OnlyLocalDecls; } +      /// \brief Create a ASTUnit from a PCH file.    ///    /// \param Filename - The PCH file to load.    /// -  /// \param Diags - The Diagnostic implementation to use. +  /// \param diagClient - The diagnostics client to use.  Specify NULL +  /// to use a default client that emits warnings/errors to standard error. +  /// The ASTUnit objects takes ownership of this object.    ///    /// \param FileMgr - The FileManager to use.    /// @@ -74,9 +95,10 @@ public:    ///    /// \returns - The initialized ASTUnit or null if the PCH failed to load.    static ASTUnit *LoadFromPCHFile(const std::string &Filename, -                                  Diagnostic &Diags, -                                  FileManager &FileMgr, -                                  std::string *ErrMsg = 0); +                                  std::string *ErrMsg = 0, +                                  DiagnosticClient *diagClient = NULL, +                                  bool OnlyLocalDecls = false, +                                  bool UseBumpAllocator = false);  };  } // namespace clang diff --git a/include/clang/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index 716780e68a52..1e953d671226 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -86,38 +86,33 @@ namespace clang {        PREPROCESSOR_BLOCK_ID,        /// \brief The block containing the definitions of all of the -      /// types used within the PCH file. -      TYPES_BLOCK_ID, - -      /// \brief The block containing the definitions of all of the -      /// declarations stored in the PCH file. -      DECLS_BLOCK_ID +      /// types and decls used within the PCH file. +      DECLTYPES_BLOCK_ID      };      /// \brief Record types that occur within the PCH block itself.      enum PCHRecordTypes { -      /// \brief Offset of each type within the types block. +      /// \brief Record code for the offsets of each type.        ///        /// The TYPE_OFFSET constant describes the record that occurs -      /// within the block identified by TYPE_OFFSETS_BLOCK_ID within -      /// the PCH file. The record itself is an array of offsets that -      /// point into the types block (identified by TYPES_BLOCK_ID in -      /// the PCH file). The index into the array is based on the ID +      /// within the PCH block. The record itself is an array of offsets that +      /// point into the declarations and types block (identified by  +      /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID        /// of a type. For a given type ID @c T, the lower three bits of        /// @c T are its qualifiers (const, volatile, restrict), as in        /// the QualType class. The upper bits, after being shifted and        /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the        /// TYPE_OFFSET block to determine the offset of that type's -      /// corresponding record within the TYPES_BLOCK_ID block. +      /// corresponding record within the DECLTYPES_BLOCK_ID block.        TYPE_OFFSET = 1,        /// \brief Record code for the offsets of each decl.        ///        /// The DECL_OFFSET constant describes the record that occurs -      /// within the block identifier by DECL_OFFSETS_BLOCK_ID within -      /// the PCH file. The record itself is an array of offsets that -      /// point into the declarations block (identified by -      /// DECLS_BLOCK_ID). The declaration ID is an index into this +      /// within the block identified by DECL_OFFSETS_BLOCK_ID within +      /// the PCH block. The record itself is an array of offsets that +      /// point into the declarations and types block (identified by +      /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this        /// record, after subtracting one to account for the use of        /// declaration ID 0 for a NULL declaration pointer. Index 0 is        /// reserved for the translation unit declaration. @@ -353,8 +348,8 @@ namespace clang {      /// \brief Record codes for each kind of type.      /// -    /// These constants describe the records that can occur within a -    /// block identified by TYPES_BLOCK_ID in the PCH file. Each +    /// These constants describe the type records that can occur within a +    /// block identified by DECLTYPES_BLOCK_ID in the PCH file. Each      /// constant describes a record for a specific type class in the      /// AST.      enum TypeCode { @@ -402,16 +397,12 @@ namespace clang {        TYPE_OBJC_INTERFACE           = 21,        /// \brief An ObjCObjectPointerType record.        TYPE_OBJC_OBJECT_POINTER      = 22, -      /// \brief An ObjCProtocolListType record. -      TYPE_OBJC_PROTOCOL_LIST       = 23,        /// \brief a DecltypeType record. -      TYPE_DECLTYPE                 = 24, -      /// \brief A ConstantArrayWithExprType record. -      TYPE_CONSTANT_ARRAY_WITH_EXPR = 25, -      /// \brief A ConstantArrayWithoutExprType record. -      TYPE_CONSTANT_ARRAY_WITHOUT_EXPR = 26, +      TYPE_DECLTYPE                 = 23,        /// \brief An ElaboratedType record. -      TYPE_ELABORATED               = 27 +      TYPE_ELABORATED               = 24, +      /// \brief A SubstTemplateTypeParmType record. +      TYPE_SUBST_TEMPLATE_TYPE_PARM = 25      };      /// \brief The type IDs for special types constructed by semantic @@ -443,18 +434,22 @@ namespace clang {        /// \brief Objective-C "id" redefinition type        SPECIAL_TYPE_OBJC_ID_REDEFINITION        = 10,        /// \brief Objective-C "Class" redefinition type -      SPECIAL_TYPE_OBJC_CLASS_REDEFINITION     = 11 +      SPECIAL_TYPE_OBJC_CLASS_REDEFINITION     = 11, +      /// \brief Block descriptor type for Blocks CodeGen +      SPECIAL_TYPE_BLOCK_DESCRIPTOR            = 12, +      /// \brief Block extedned descriptor type for Blocks CodeGen +      SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR   = 13      };      /// \brief Record codes for each kind of declaration.      /// -    /// These constants describe the records that can occur within a -    /// declarations block (identified by DECLS_BLOCK_ID). Each +    /// These constants describe the declaration records that can occur within +    /// a declarations block (identified by DECLS_BLOCK_ID). Each      /// constant describes a record for a specific declaration class      /// in the AST.      enum DeclCode {        /// \brief Attributes attached to a declaration. -      DECL_ATTR = 1, +      DECL_ATTR = 50,        /// \brief A TranslationUnitDecl record.        DECL_TRANSLATION_UNIT,        /// \brief A TypedefDecl record. @@ -529,14 +524,14 @@ namespace clang {      /// \brief Record codes for each kind of statement or expression.      ///      /// These constants describe the records that describe statements -    /// or expressions. These records can occur within either the type -    /// or declaration blocks, so they begin with record values of -    /// 50.  Each constant describes a record for a specific -    /// statement or expression class in the AST. +    /// or expressions. These records  occur within type and declarations +    /// block, so they begin with record values of 100.  Each constant  +    /// describes a record for a specific statement or expression class in the +    /// AST.      enum StmtCode {        /// \brief A marker record that indicates that we are at the end        /// of an expression. -      STMT_STOP = 50, +      STMT_STOP = 100,        /// \brief A NULL expression.        STMT_NULL_PTR,        /// \brief A NullStmt record. diff --git a/include/clang/Frontend/PCHReader.h b/include/clang/Frontend/PCHReader.h index 1230e3753e04..cc16970b0040 100644 --- a/include/clang/Frontend/PCHReader.h +++ b/include/clang/Frontend/PCHReader.h @@ -169,6 +169,11 @@ private:    /// \brief The AST context into which we'll read the PCH file.    ASTContext *Context; +  /// \brief The PCH stat cache installed by this PCHReader, if any. +  /// +  /// The dynamic type of this stat cache is always PCHStatCache +  void *StatCache; +          /// \brief The AST consumer.    ASTConsumer *Consumer; @@ -492,8 +497,8 @@ public:    /// \param isysroot If non-NULL, the system include path specified by the    /// user. This is only used with relocatable PCH files. If non-NULL,    /// a relocatable PCH file will use the default path "/". -      PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, -                Diagnostic &Diags, const char *isysroot = 0); +  PCHReader(SourceManager &SourceMgr, FileManager &FileMgr, +            Diagnostic &Diags, const char *isysroot = 0);    ~PCHReader();    /// \brief Load the precompiled header designated by the given file @@ -513,6 +518,9 @@ public:    /// \brief Sets and initializes the given Context.    void InitializeContext(ASTContext &Context); +  /// \brief Retrieve the name of the PCH file +  const std::string &getFileName() { return FileName; } +    /// \brief Retrieve the name of the original source file name    const std::string &getOriginalSourceFile() { return OriginalFileName; } @@ -534,6 +542,10 @@ public:    /// comments in the source code.    virtual void ReadComments(std::vector<SourceRange> &Comments); +  /// \brief Reads a declarator info from the given record. +  virtual DeclaratorInfo *GetDeclaratorInfo(const RecordData &Record, +                                            unsigned &Idx); +    /// \brief Resolve a type ID into a type, potentially building a new    /// type.    virtual QualType GetType(pch::TypeID ID); diff --git a/include/clang/Frontend/PCHWriter.h b/include/clang/Frontend/PCHWriter.h index a807cd7c4d1f..728e138d9e7c 100644 --- a/include/clang/Frontend/PCHWriter.h +++ b/include/clang/Frontend/PCHWriter.h @@ -73,6 +73,33 @@ private:    /// \brief The bitstream writer used to emit this precompiled header.    llvm::BitstreamWriter &Stream; +  /// \brief Stores a declaration or a type to be written to the PCH file. +  class DeclOrType { +  public: +    DeclOrType(Decl *D) : Stored(D), IsType(false) { } +    DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { } +     +    bool isType() const { return IsType; } +    bool isDecl() const { return !IsType; } +     +    QualType getType() const { +      assert(isType() && "Not a type!"); +      return QualType::getFromOpaquePtr(Stored); +    } +     +    Decl *getDecl() const { +      assert(isDecl() && "Not a decl!"); +      return static_cast<Decl *>(Stored); +    } +     +  private: +    void *Stored; +    bool IsType; +  }; +   +  /// \brief The declarations and types to emit. +  std::queue<DeclOrType> DeclTypesToEmit; +      /// \brief Map that provides the ID numbers of each declaration within    /// the output stream.    /// @@ -85,10 +112,6 @@ private:    /// the declaration's ID.    std::vector<uint32_t> DeclOffsets; -  /// \brief Queue containing the declarations that we still need to -  /// emit. -  std::queue<Decl *> DeclsToEmit; -    /// \brief Map that provides the ID numbers of each type within the    /// output stream.    /// @@ -107,10 +130,6 @@ private:    /// \brief The type ID that will be assigned to the next new type.    pch::TypeID NextTypeID; -  /// \brief Queue containing the types that we still need to -  /// emit. -  std::queue<QualType> TypesToEmit; -    /// \brief Map that provides the ID numbers of each identifier in    /// the output stream.    /// @@ -189,18 +208,17 @@ private:    void WritePreprocessor(const Preprocessor &PP);    void WriteComments(ASTContext &Context);    void WriteType(QualType T); -  void WriteTypesBlock(ASTContext &Context);    uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);    uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC); -  void WriteDeclsBlock(ASTContext &Context);    void WriteMethodPool(Sema &SemaRef);    void WriteIdentifierTable(Preprocessor &PP);    void WriteAttributeRecord(const Attr *Attr);    unsigned ParmVarDeclAbbrev;    void WriteDeclsBlockAbbrevs(); - +  void WriteDecl(ASTContext &Context, Decl *D); +    public:    /// \brief Create a new precompiled header writer that outputs to    /// the given bitstream. @@ -254,6 +272,9 @@ public:    /// \brief Emit a reference to a type.    void AddTypeRef(QualType T, RecordData &Record); +  /// \brief Emits a reference to a declarator info. +  void AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record); +    /// \brief Emit a reference to a declaration.    void AddDeclRef(const Decl *D, RecordData &Record); diff --git a/include/clang/Index/ASTLocation.h b/include/clang/Index/ASTLocation.h index 9620ec5dbd4f..fc18dae1a20c 100644 --- a/include/clang/Index/ASTLocation.h +++ b/include/clang/Index/ASTLocation.h @@ -91,7 +91,7 @@ public:    ASTLocation(const Decl *parentDecl, TypeLoc tyLoc)      : ParentDecl(const_cast<Decl*>(parentDecl), N_Type) {      if (tyLoc) { -      Ty.TyPtr = tyLoc.getSourceType().getAsOpaquePtr(); +      Ty.TyPtr = tyLoc.getType().getAsOpaquePtr();        Ty.Data = tyLoc.getOpaqueData();      } else        ParentDecl.setPointer(0); @@ -124,8 +124,8 @@ public:      return TypeLoc(QualType::getFromOpaquePtr(Ty.TyPtr), Ty.Data);    } -  Decl *dyn_AsDecl() const { return getKind() == N_Decl ? D : 0; } -  Stmt *dyn_AsStmt() const { return getKind() == N_Stmt ? Stm : 0; } +  Decl *dyn_AsDecl() const { return isValid() && getKind() == N_Decl ? D : 0; } +  Stmt *dyn_AsStmt() const { return isValid() && getKind() == N_Stmt ? Stm : 0; }    NamedRef dyn_AsNamedRef() const {      return getKind() == N_Type ? AsNamedRef() : NamedRef();    } diff --git a/include/clang/Index/Indexer.h b/include/clang/Index/Indexer.h index 8b1d2dd38bff..361e729feab2 100644 --- a/include/clang/Index/Indexer.h +++ b/include/clang/Index/Indexer.h @@ -14,13 +14,11 @@  #ifndef LLVM_CLANG_INDEX_INDEXER_H  #define LLVM_CLANG_INDEX_INDEXER_H -#include "clang/Frontend/TextDiagnosticBuffer.h"  #include "clang/Index/IndexProvider.h"  #include "clang/Index/Entity.h"  #include "clang/Index/GlobalSelector.h"  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/DenseMap.h" -#include "clang/Basic/FileManager.h"  #include <map>  namespace clang { @@ -39,16 +37,10 @@ public:    typedef std::map<GlobalSelector, TUSetTy> SelMapTy;    explicit Indexer(Program &prog) : -    Prog(prog), Diags(&DiagClient) { } +    Prog(prog) { }    Program &getProgram() const { return Prog; } -  Diagnostic &getDiagnostics() { return Diags; } -  const Diagnostic &getDiagnostics() const { return Diags; } - -  FileManager &getFileManager() { return FileMgr; } -  const FileManager &getFileManager() const { return FileMgr; } -    /// \brief Find all Entities and map them to the given translation unit.    void IndexAST(TranslationUnit *TU); @@ -59,9 +51,6 @@ public:  private:    Program &Prog; -  TextDiagnosticBuffer DiagClient; -  Diagnostic Diags; -  FileManager FileMgr;    MapTy Map;    CtxTUMapTy CtxTUMap; diff --git a/include/clang/Index/Utils.h b/include/clang/Index/Utils.h index e78ef8a15563..36cf56dea203 100644 --- a/include/clang/Index/Utils.h +++ b/include/clang/Index/Utils.h @@ -18,7 +18,8 @@  namespace clang {    class ASTContext;    class SourceLocation; - +  class Decl; +    namespace idx {    class ASTLocation; @@ -26,7 +27,8 @@ namespace idx {  ///  /// \returns the resolved ASTLocation or an invalid ASTLocation if the source  /// location could not be resolved. -ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc); +ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,  +                                 Decl *RelativeToDecl = 0);  } // end namespace idx diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 1ee14701fa2d..050b3f42e4cd 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -1390,6 +1390,34 @@ public:      return ExprEmpty();    } +  /// \brief Parsed a C++ destructor reference that refers to a type. +  /// +  /// This action is used when parsing a destructor reference that uses a  +  /// template-id, e.g., +  /// +  /// \code +  /// t->~Tmpl<T1, T2> +  /// \endcode +  /// +  /// \param S the scope in which the destructor reference occurs. +  /// \param Base the base object of the destructor reference expression. +  /// \param OpLoc the location of the operator ('.' or '->'). +  /// \param OpKind the kind of the destructor reference operator ('.' or '->'). +  /// \param TypeRange the source range that covers the destructor type. +  /// \param Type the type that is being destroyed. +  /// \param SS the scope specifier that precedes the destructor name. +  /// \param HasTrailingLParen whether the destructor name is followed by a '('. +  virtual OwningExprResult +  ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, +                               SourceLocation OpLoc, +                               tok::TokenKind OpKind, +                               SourceRange TypeRange, +                               TypeTy *Type, +                               const CXXScopeSpec &SS, +                               bool HasTrailingLParen) { +    return ExprEmpty(); +  } +      /// ActOnOverloadedOperatorReferenceExpr - Parsed an overloaded operator    /// reference, for example:    /// @@ -1691,9 +1719,25 @@ public:    /// possibly checking well-formedness of the template arguments. It does not    /// imply the declaration of any entity.    /// +  /// \param SS  The scope specifier that may precede the template name. +  ///    /// \param Template  A template whose specialization results in a    /// function or a dependent template. -  virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template, +  /// +  /// \param TemplateNameLoc The location of the template name. +  ///  +  /// \param LAngleLoc The location of the left angle bracket ('<') that starts  +  /// the template argument list. +  /// +  /// \param TemplateArgs The template arguments in the template argument list, +  /// which may be empty. +  /// +  /// \param TemplateArgLocs The locations of the template arguments. +  /// +  /// \param RAngleLoc The location of the right angle bracket ('>') that  +  /// closes the template argument list. +  virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS, +                                               TemplateTy Template,                                                 SourceLocation TemplateNameLoc,                                                 SourceLocation LAngleLoc,                                                 ASTTemplateArgsPtr TemplateArgs, diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index e028186d46e5..7f5fa35842af 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -40,7 +40,8 @@ ASTContext::ASTContext(const LangOptions& LOpts, SourceManager &SM,                         bool FreeMem, unsigned size_reserve) :    GlobalNestedNameSpecifier(0), CFConstantStringTypeDecl(0),    ObjCFastEnumerationStateTypeDecl(0), FILEDecl(0), jmp_bufDecl(0), -  sigjmp_bufDecl(0), SourceMgr(SM), LangOpts(LOpts), +  sigjmp_bufDecl(0), BlockDescriptorType(0), BlockDescriptorExtendedType(0), +  SourceMgr(SM), LangOpts(LOpts),    LoadedExternalComments(false), FreeMemory(FreeMem), Target(t),    Idents(idents), Selectors(sels),    BuiltinInfo(builtins), ExternalSource(0), PrintingPolicy(LOpts) { @@ -554,10 +555,6 @@ ASTContext::getTypeInfo(const Type *T) {      assert(false && "Should not see dependent types");      break; -  case Type::ObjCProtocolList: -    assert(false && "Should not see protocol list types"); -    break; -    case Type::FunctionNoProto:    case Type::FunctionProto:      // GCC extension: alignof(function) = 32 bits @@ -571,8 +568,6 @@ ASTContext::getTypeInfo(const Type *T) {      Align = getTypeAlign(cast<ArrayType>(T)->getElementType());      break; -  case Type::ConstantArrayWithExpr: -  case Type::ConstantArrayWithoutExpr:    case Type::ConstantArray: {      const ConstantArrayType *CAT = cast<ConstantArrayType>(T); @@ -583,14 +578,16 @@ ASTContext::getTypeInfo(const Type *T) {    }    case Type::ExtVector:    case Type::Vector: { -    std::pair<uint64_t, unsigned> EltInfo = -      getTypeInfo(cast<VectorType>(T)->getElementType()); -    Width = EltInfo.first*cast<VectorType>(T)->getNumElements(); +    const VectorType *VT = cast<VectorType>(T); +    std::pair<uint64_t, unsigned> EltInfo = getTypeInfo(VT->getElementType()); +    Width = EltInfo.first*VT->getNumElements();      Align = Width;      // If the alignment is not a power of 2, round up to the next power of 2.      // This happens for non-power-of-2 length vectors. -    // FIXME: this should probably be a target property. -    Align = 1 << llvm::Log2_32_Ceil(Align); +    if (VT->getNumElements() & (VT->getNumElements()-1)) { +      Align = llvm::NextPowerOf2(Align); +      Width = llvm::RoundUpToAlignment(Width, Align); +    }      break;    } @@ -749,9 +746,13 @@ ASTContext::getTypeInfo(const Type *T) {      break;    } -  case Type::Elaborated: { -    return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType().getTypePtr()); -  } +  case Type::SubstTemplateTypeParm: +    return getTypeInfo(cast<SubstTemplateTypeParmType>(T)-> +                       getReplacementType().getTypePtr()); + +  case Type::Elaborated: +    return getTypeInfo(cast<ElaboratedType>(T)->getUnderlyingType() +                         .getTypePtr());    case Type::Typedef: {      const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl(); @@ -940,8 +941,14 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD,  /// \param T the type that will be the basis for type source info. This type  /// should refer to how the declarator was written in source code, not to  /// what type semantic analysis resolved the declarator to. -DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T) { -  unsigned DataSize = TypeLoc::getFullDataSizeForType(T); +DeclaratorInfo *ASTContext::CreateDeclaratorInfo(QualType T, +                                                 unsigned DataSize) { +  if (!DataSize) +    DataSize = TypeLoc::getFullDataSizeForType(T); +  else +    assert(DataSize == TypeLoc::getFullDataSizeForType(T) && +           "incorrect data size provided to CreateDeclaratorInfo!"); +    DeclaratorInfo *DInfo =      (DeclaratorInfo*)BumpAlloc.Allocate(sizeof(DeclaratorInfo) + DataSize, 8);    new (DInfo) DeclaratorInfo(T); @@ -1140,7 +1147,7 @@ QualType ASTContext::getComplexType(QualType T) {    // If the pointee type isn't canonical, this won't be a canonical type either,    // so fill in the canonical type field.    QualType Canonical; -  if (!T->isCanonical()) { +  if (!T.isCanonical()) {      Canonical = getComplexType(getCanonicalType(T));      // Get the new insert position for the node we care about. @@ -1177,7 +1184,7 @@ QualType ASTContext::getPointerType(QualType T) {    // If the pointee type isn't canonical, this won't be a canonical type either,    // so fill in the canonical type field.    QualType Canonical; -  if (!T->isCanonical()) { +  if (!T.isCanonical()) {      Canonical = getPointerType(getCanonicalType(T));      // Get the new insert position for the node we care about. @@ -1207,7 +1214,7 @@ QualType ASTContext::getBlockPointerType(QualType T) {    // If the block pointee type isn't canonical, this won't be a canonical    // type either so fill in the canonical type field.    QualType Canonical; -  if (!T->isCanonical()) { +  if (!T.isCanonical()) {      Canonical = getBlockPointerType(getCanonicalType(T));      // Get the new insert position for the node we care about. @@ -1224,22 +1231,25 @@ QualType ASTContext::getBlockPointerType(QualType T) {  /// getLValueReferenceType - Return the uniqued reference to the type for an  /// lvalue reference to the specified type. -QualType ASTContext::getLValueReferenceType(QualType T) { +QualType ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) {    // Unique pointers, to guarantee there is only one pointer of a particular    // structure.    llvm::FoldingSetNodeID ID; -  ReferenceType::Profile(ID, T); +  ReferenceType::Profile(ID, T, SpelledAsLValue);    void *InsertPos = 0;    if (LValueReferenceType *RT =          LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))      return QualType(RT, 0); +  const ReferenceType *InnerRef = T->getAs<ReferenceType>(); +    // If the referencee type isn't canonical, this won't be a canonical type    // either, so fill in the canonical type field.    QualType Canonical; -  if (!T->isCanonical()) { -    Canonical = getLValueReferenceType(getCanonicalType(T)); +  if (!SpelledAsLValue || InnerRef || !T.isCanonical()) { +    QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T); +    Canonical = getLValueReferenceType(getCanonicalType(PointeeType));      // Get the new insert position for the node we care about.      LValueReferenceType *NewIP = @@ -1248,9 +1258,11 @@ QualType ASTContext::getLValueReferenceType(QualType T) {    }    LValueReferenceType *New -    = new (*this, TypeAlignment) LValueReferenceType(T, Canonical); +    = new (*this, TypeAlignment) LValueReferenceType(T, Canonical, +                                                     SpelledAsLValue);    Types.push_back(New);    LValueReferenceTypes.InsertNode(New, InsertPos); +    return QualType(New, 0);  } @@ -1260,18 +1272,21 @@ QualType ASTContext::getRValueReferenceType(QualType T) {    // Unique pointers, to guarantee there is only one pointer of a particular    // structure.    llvm::FoldingSetNodeID ID; -  ReferenceType::Profile(ID, T); +  ReferenceType::Profile(ID, T, false);    void *InsertPos = 0;    if (RValueReferenceType *RT =          RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos))      return QualType(RT, 0); +  const ReferenceType *InnerRef = T->getAs<ReferenceType>(); +    // If the referencee type isn't canonical, this won't be a canonical type    // either, so fill in the canonical type field.    QualType Canonical; -  if (!T->isCanonical()) { -    Canonical = getRValueReferenceType(getCanonicalType(T)); +  if (InnerRef || !T.isCanonical()) { +    QualType PointeeType = (InnerRef ? InnerRef->getPointeeType() : T); +    Canonical = getRValueReferenceType(getCanonicalType(PointeeType));      // Get the new insert position for the node we care about.      RValueReferenceType *NewIP = @@ -1302,7 +1317,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) {    // If the pointee or class type isn't canonical, this won't be a canonical    // type either, so fill in the canonical type field.    QualType Canonical; -  if (!T->isCanonical()) { +  if (!T.isCanonical()) {      Canonical = getMemberPointerType(getCanonicalType(T),getCanonicalType(Cls));      // Get the new insert position for the node we care about. @@ -1342,7 +1357,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,    // If the element type isn't canonical, this won't be a canonical type either,    // so fill in the canonical type field.    QualType Canonical; -  if (!EltTy->isCanonical()) { +  if (!EltTy.isCanonical()) {      Canonical = getConstantArrayType(getCanonicalType(EltTy), ArySize,                                       ASM, EltTypeQuals);      // Get the new insert position for the node we care about. @@ -1358,53 +1373,6 @@ QualType ASTContext::getConstantArrayType(QualType EltTy,    return QualType(New, 0);  } -/// getConstantArrayWithExprType - Return a reference to the type for -/// an array of the specified element type. -QualType -ASTContext::getConstantArrayWithExprType(QualType EltTy, -                                         const llvm::APInt &ArySizeIn, -                                         Expr *ArySizeExpr, -                                         ArrayType::ArraySizeModifier ASM, -                                         unsigned EltTypeQuals, -                                         SourceRange Brackets) { -  // Convert the array size into a canonical width matching the pointer -  // size for the target. -  llvm::APInt ArySize(ArySizeIn); -  ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); - -  // Compute the canonical ConstantArrayType. -  QualType Canonical = getConstantArrayType(getCanonicalType(EltTy), -                                            ArySize, ASM, EltTypeQuals); -  // Since we don't unique expressions, it isn't possible to unique VLA's -  // that have an expression provided for their size. -  ConstantArrayWithExprType *New = new(*this, TypeAlignment) -    ConstantArrayWithExprType(EltTy, Canonical, ArySize, ArySizeExpr, -                              ASM, EltTypeQuals, Brackets); -  Types.push_back(New); -  return QualType(New, 0); -} - -/// getConstantArrayWithoutExprType - Return a reference to the type for -/// an array of the specified element type. -QualType -ASTContext::getConstantArrayWithoutExprType(QualType EltTy, -                                            const llvm::APInt &ArySizeIn, -                                            ArrayType::ArraySizeModifier ASM, -                                            unsigned EltTypeQuals) { -  // Convert the array size into a canonical width matching the pointer -  // size for the target. -  llvm::APInt ArySize(ArySizeIn); -  ArySize.zextOrTrunc(Target.getPointerWidth(EltTy.getAddressSpace())); - -  // Compute the canonical ConstantArrayType. -  QualType Canonical = getConstantArrayType(getCanonicalType(EltTy), -                                            ArySize, ASM, EltTypeQuals); -  ConstantArrayWithoutExprType *New = new(*this, TypeAlignment) -    ConstantArrayWithoutExprType(EltTy, Canonical, ArySize, ASM, EltTypeQuals); -  Types.push_back(New); -  return QualType(New, 0); -} -  /// getVariableArrayType - Returns a non-unique reference to the type for a  /// variable array of the specified element type.  QualType ASTContext::getVariableArrayType(QualType EltTy, @@ -1484,7 +1452,7 @@ QualType ASTContext::getIncompleteArrayType(QualType EltTy,    // either, so fill in the canonical type field.    QualType Canonical; -  if (!EltTy->isCanonical()) { +  if (!EltTy.isCanonical()) {      Canonical = getIncompleteArrayType(getCanonicalType(EltTy),                                         ASM, EltTypeQuals); @@ -1520,7 +1488,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts) {    // If the element type isn't canonical, this won't be a canonical type either,    // so fill in the canonical type field.    QualType Canonical; -  if (!vecType->isCanonical()) { +  if (!vecType.isCanonical()) {      Canonical = getVectorType(getCanonicalType(vecType), NumElts);      // Get the new insert position for the node we care about. @@ -1552,7 +1520,7 @@ QualType ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) {    // If the element type isn't canonical, this won't be a canonical type either,    // so fill in the canonical type field.    QualType Canonical; -  if (!vecType->isCanonical()) { +  if (!vecType.isCanonical()) {      Canonical = getExtVectorType(getCanonicalType(vecType), NumElts);      // Get the new insert position for the node we care about. @@ -1616,7 +1584,7 @@ QualType ASTContext::getFunctionNoProtoType(QualType ResultTy, bool NoReturn) {      return QualType(FT, 0);    QualType Canonical; -  if (!ResultTy->isCanonical()) { +  if (!ResultTy.isCanonical()) {      Canonical = getFunctionNoProtoType(getCanonicalType(ResultTy), NoReturn);      // Get the new insert position for the node we care about. @@ -1639,12 +1607,6 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,                                       unsigned TypeQuals, bool hasExceptionSpec,                                       bool hasAnyExceptionSpec, unsigned NumExs,                                       const QualType *ExArray, bool NoReturn) { -  if (LangOpts.CPlusPlus) { -    for (unsigned i = 0; i != NumArgs; ++i) -      assert(!ArgArray[i].hasQualifiers() &&  -             "C++ arguments can't have toplevel qualifiers!"); -  } -      // Unique functions, to guarantee there is only one function of a particular    // structure.    llvm::FoldingSetNodeID ID; @@ -1658,11 +1620,9 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,      return QualType(FTP, 0);    // Determine whether the type being created is already canonical or not. -  bool isCanonical = ResultTy->isCanonical(); -  if (hasExceptionSpec) -    isCanonical = false; +  bool isCanonical = !hasExceptionSpec && ResultTy.isCanonical();    for (unsigned i = 0; i != NumArgs && isCanonical; ++i) -    if (!ArgArray[i]->isCanonical()) +    if (!ArgArray[i].isCanonicalAsParam())        isCanonical = false;    // If this type isn't canonical, get the canonical version of it. @@ -1672,7 +1632,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,      llvm::SmallVector<QualType, 16> CanonicalArgs;      CanonicalArgs.reserve(NumArgs);      for (unsigned i = 0; i != NumArgs; ++i) -      CanonicalArgs.push_back(getCanonicalType(ArgArray[i])); +      CanonicalArgs.push_back(getCanonicalParamType(ArgArray[i]));      Canonical = getFunctionType(getCanonicalType(ResultTy),                                  CanonicalArgs.data(), NumArgs, @@ -1743,6 +1703,29 @@ QualType ASTContext::getTypedefType(TypedefDecl *Decl) {    return QualType(Decl->TypeForDecl, 0);  } +/// \brief Retrieve a substitution-result type. +QualType +ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, +                                         QualType Replacement) { +  assert(Replacement.isCanonical() +         && "replacement types must always be canonical"); + +  llvm::FoldingSetNodeID ID; +  SubstTemplateTypeParmType::Profile(ID, Parm, Replacement); +  void *InsertPos = 0; +  SubstTemplateTypeParmType *SubstParm +    = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); + +  if (!SubstParm) { +    SubstParm = new (*this, TypeAlignment) +      SubstTemplateTypeParmType(Parm, Replacement); +    Types.push_back(SubstParm); +    SubstTemplateTypeParmTypes.InsertNode(SubstParm, InsertPos); +  } + +  return QualType(SubstParm, 0); +} +  /// \brief Retrieve the template type parameter type for a template  /// parameter or parameter pack with the given depth, index, and (optionally)  /// name. @@ -1933,7 +1916,17 @@ static bool CmpProtocolNames(const ObjCProtocolDecl *LHS,    return LHS->getDeclName() < RHS->getDeclName();  } -static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols, +static bool areSortedAndUniqued(ObjCProtocolDecl **Protocols, +                                unsigned NumProtocols) { +  if (NumProtocols == 0) return true; + +  for (unsigned i = 1; i != NumProtocols; ++i) +    if (!CmpProtocolNames(Protocols[i-1], Protocols[i])) +      return false; +  return true; +} + +static void SortAndUniqueProtocols(ObjCProtocolDecl **Protocols,                                     unsigned &NumProtocols) {    ObjCProtocolDecl **ProtocolsEnd = Protocols+NumProtocols; @@ -1950,10 +1943,6 @@ static void SortAndUniqueProtocols(ObjCProtocolDecl **&Protocols,  QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,                                                ObjCProtocolDecl **Protocols,                                                unsigned NumProtocols) { -  // Sort the protocol list alphabetically to canonicalize it. -  if (NumProtocols) -    SortAndUniqueProtocols(Protocols, NumProtocols); -    llvm::FoldingSetNodeID ID;    ObjCObjectPointerType::Profile(ID, InterfaceT, Protocols, NumProtocols); @@ -1962,9 +1951,31 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,                ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos))      return QualType(QT, 0); +  // Sort the protocol list alphabetically to canonicalize it. +  QualType Canonical; +  if (!InterfaceT.isCanonical() ||  +      !areSortedAndUniqued(Protocols, NumProtocols)) { +    if (!areSortedAndUniqued(Protocols, NumProtocols)) { +      llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols); +      unsigned UniqueCount = NumProtocols; + +      std::copy(Protocols, Protocols + NumProtocols, Sorted.begin()); +      SortAndUniqueProtocols(&Sorted[0], UniqueCount); + +      Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT), +                                           &Sorted[0], UniqueCount); +    } else { +      Canonical = getObjCObjectPointerType(getCanonicalType(InterfaceT), +                                           Protocols, NumProtocols); +    } + +    // Regenerate InsertPos. +    ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos); +  } +    // No Match;    ObjCObjectPointerType *QType = new (*this, TypeAlignment) -    ObjCObjectPointerType(InterfaceT, Protocols, NumProtocols); +    ObjCObjectPointerType(Canonical, InterfaceT, Protocols, NumProtocols);    Types.push_back(QType);    ObjCObjectPointerTypes.InsertNode(QType, InsertPos); @@ -1975,10 +1986,6 @@ QualType ASTContext::getObjCObjectPointerType(QualType InterfaceT,  /// specified ObjC interface decl. The list of protocols is optional.  QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,                         ObjCProtocolDecl **Protocols, unsigned NumProtocols) { -  if (NumProtocols) -    // Sort the protocol list alphabetically to canonicalize it. -    SortAndUniqueProtocols(Protocols, NumProtocols); -    llvm::FoldingSetNodeID ID;    ObjCInterfaceType::Profile(ID, Decl, Protocols, NumProtocols); @@ -1987,31 +1994,26 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl,        ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos))      return QualType(QT, 0); -  // No Match; -  ObjCInterfaceType *QType = new (*this, TypeAlignment) -    ObjCInterfaceType(const_cast<ObjCInterfaceDecl*>(Decl), -                      Protocols, NumProtocols); -  Types.push_back(QType); -  ObjCInterfaceTypes.InsertNode(QType, InsertPos); -  return QualType(QType, 0); -} +  // Sort the protocol list alphabetically to canonicalize it. +  QualType Canonical; +  if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) { +    llvm::SmallVector<ObjCProtocolDecl*, 8> Sorted(NumProtocols); +    std::copy(Protocols, Protocols + NumProtocols, Sorted.begin()); -QualType ASTContext::getObjCProtocolListType(QualType T, -                                             ObjCProtocolDecl **Protocols, -                                             unsigned NumProtocols) { -  llvm::FoldingSetNodeID ID; -  ObjCProtocolListType::Profile(ID, T, Protocols, NumProtocols); +    unsigned UniqueCount = NumProtocols; +    SortAndUniqueProtocols(&Sorted[0], UniqueCount); -  void *InsertPos = 0; -  if (ObjCProtocolListType *QT = -      ObjCProtocolListTypes.FindNodeOrInsertPos(ID, InsertPos)) -    return QualType(QT, 0); +    Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount); + +    ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos); +  } + +  ObjCInterfaceType *QType = new (*this, TypeAlignment) +    ObjCInterfaceType(Canonical, const_cast<ObjCInterfaceDecl*>(Decl), +                      Protocols, NumProtocols); -  // No Match; -  ObjCProtocolListType *QType = new (*this, TypeAlignment) -    ObjCProtocolListType(T, Protocols, NumProtocols);    Types.push_back(QType); -  ObjCProtocolListTypes.InsertNode(QType, InsertPos); +  ObjCInterfaceTypes.InsertNode(QType, InsertPos);    return QualType(QType, 0);  } @@ -2168,6 +2170,24 @@ QualType ASTContext::getPointerDiffType() const {  //                              Type Operators  //===----------------------------------------------------------------------===// +CanQualType ASTContext::getCanonicalParamType(QualType T) { +  // Push qualifiers into arrays, and then discard any remaining +  // qualifiers. +  T = getCanonicalType(T); +  const Type *Ty = T.getTypePtr(); + +  QualType Result; +  if (isa<ArrayType>(Ty)) { +    Result = getArrayDecayedType(QualType(Ty,0)); +  } else if (isa<FunctionType>(Ty)) { +    Result = getPointerType(QualType(Ty, 0)); +  } else { +    Result = QualType(Ty, 0); +  } + +  return CanQualType::CreateUnsafe(Result); +} +  /// getCanonicalType - Return the canonical (structural) type corresponding to  /// the specified potentially non-canonical type.  The non-canonical version  /// of a type may have many "decorated" versions of types.  Decorators can @@ -2512,7 +2532,7 @@ int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) {  /// routine will assert if passed a built-in type that isn't an integer or enum,  /// or if it is not canonicalized.  unsigned ASTContext::getIntegerRank(Type *T) { -  assert(T->isCanonical() && "T should be canonicalized"); +  assert(T->isCanonicalUnqualified() && "T should be canonicalized");    if (EnumType* ET = dyn_cast<EnumType>(T))      T = ET->getDecl()->getIntegerType().getTypePtr(); @@ -2713,6 +2733,226 @@ QualType ASTContext::getObjCFastEnumerationStateType() {    return getTagDeclType(ObjCFastEnumerationStateTypeDecl);  } +QualType ASTContext::getBlockDescriptorType() { +  if (BlockDescriptorType) +    return getTagDeclType(BlockDescriptorType); + +  RecordDecl *T; +  // FIXME: Needs the FlagAppleBlock bit. +  T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), +                         &Idents.get("__block_descriptor")); +   +  QualType FieldTypes[] = { +    UnsignedLongTy, +    UnsignedLongTy, +  }; + +  const char *FieldNames[] = { +    "reserved", +    "Size" +  }; + +  for (size_t i = 0; i < 2; ++i) { +    FieldDecl *Field = FieldDecl::Create(*this, +                                         T, +                                         SourceLocation(), +                                         &Idents.get(FieldNames[i]), +                                         FieldTypes[i], /*DInfo=*/0, +                                         /*BitWidth=*/0, +                                         /*Mutable=*/false); +    T->addDecl(Field); +  } + +  T->completeDefinition(*this); + +  BlockDescriptorType = T; + +  return getTagDeclType(BlockDescriptorType); +} + +void ASTContext::setBlockDescriptorType(QualType T) { +  const RecordType *Rec = T->getAs<RecordType>(); +  assert(Rec && "Invalid BlockDescriptorType"); +  BlockDescriptorType = Rec->getDecl(); +} + +QualType ASTContext::getBlockDescriptorExtendedType() { +  if (BlockDescriptorExtendedType) +    return getTagDeclType(BlockDescriptorExtendedType); + +  RecordDecl *T; +  // FIXME: Needs the FlagAppleBlock bit. +  T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), +                         &Idents.get("__block_descriptor_withcopydispose")); +   +  QualType FieldTypes[] = { +    UnsignedLongTy, +    UnsignedLongTy, +    getPointerType(VoidPtrTy), +    getPointerType(VoidPtrTy) +  }; + +  const char *FieldNames[] = { +    "reserved", +    "Size", +    "CopyFuncPtr", +    "DestroyFuncPtr" +  }; + +  for (size_t i = 0; i < 4; ++i) { +    FieldDecl *Field = FieldDecl::Create(*this, +                                         T, +                                         SourceLocation(), +                                         &Idents.get(FieldNames[i]), +                                         FieldTypes[i], /*DInfo=*/0, +                                         /*BitWidth=*/0, +                                         /*Mutable=*/false); +    T->addDecl(Field); +  } + +  T->completeDefinition(*this); + +  BlockDescriptorExtendedType = T; + +  return getTagDeclType(BlockDescriptorExtendedType); +} + +void ASTContext::setBlockDescriptorExtendedType(QualType T) { +  const RecordType *Rec = T->getAs<RecordType>(); +  assert(Rec && "Invalid BlockDescriptorType"); +  BlockDescriptorExtendedType = Rec->getDecl(); +} + +bool ASTContext::BlockRequiresCopying(QualType Ty) { +  if (Ty->isBlockPointerType()) +    return true; +  if (isObjCNSObjectType(Ty)) +    return true; +  if (Ty->isObjCObjectPointerType()) +    return true; +  return false; +} + +QualType ASTContext::BuildByRefType(const char *DeclName, QualType Ty) { +  //  type = struct __Block_byref_1_X { +  //    void *__isa; +  //    struct __Block_byref_1_X *__forwarding; +  //    unsigned int __flags; +  //    unsigned int __size; +  //    void *__copy_helper;		// as needed +  //    void *__destroy_help		// as needed +  //    int X; +  //  } * + +  bool HasCopyAndDispose = BlockRequiresCopying(Ty); + +  // FIXME: Move up +  static int UniqueBlockByRefTypeID = 0; +  char Name[36]; +  sprintf(Name, "__Block_byref_%d_%s", ++UniqueBlockByRefTypeID, DeclName); +  RecordDecl *T; +  T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), +                         &Idents.get(Name)); +  T->startDefinition(); +  QualType Int32Ty = IntTy; +  assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported"); +  QualType FieldTypes[] = { +    getPointerType(VoidPtrTy), +    getPointerType(getTagDeclType(T)), +    Int32Ty, +    Int32Ty, +    getPointerType(VoidPtrTy), +    getPointerType(VoidPtrTy), +    Ty +  }; + +  const char *FieldNames[] = { +    "__isa", +    "__forwarding", +    "__flags", +    "__size", +    "__copy_helper", +    "__destroy_helper", +    DeclName, +  }; + +  for (size_t i = 0; i < 7; ++i) { +    if (!HasCopyAndDispose && i >=4 && i <= 5) +      continue; +    FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), +                                         &Idents.get(FieldNames[i]), +                                         FieldTypes[i], /*DInfo=*/0, +                                         /*BitWidth=*/0, /*Mutable=*/false); +    T->addDecl(Field); +  } + +  T->completeDefinition(*this); + +  return getPointerType(getTagDeclType(T)); +} + + +QualType ASTContext::getBlockParmType( +  bool BlockHasCopyDispose, +  llvm::SmallVector<const Expr *, 8> &BlockDeclRefDecls) { +  // FIXME: Move up +  static int UniqueBlockParmTypeID = 0; +  char Name[36]; +  sprintf(Name, "__block_literal_%u", ++UniqueBlockParmTypeID); +  RecordDecl *T; +  T = RecordDecl::Create(*this, TagDecl::TK_struct, TUDecl, SourceLocation(), +                         &Idents.get(Name)); +  QualType FieldTypes[] = { +    getPointerType(VoidPtrTy), +    IntTy, +    IntTy, +    getPointerType(VoidPtrTy), +    (BlockHasCopyDispose ? +     getPointerType(getBlockDescriptorExtendedType()) : +     getPointerType(getBlockDescriptorType())) +  }; + +  const char *FieldNames[] = { +    "__isa", +    "__flags", +    "__reserved", +    "__FuncPtr", +    "__descriptor" +  }; + +  for (size_t i = 0; i < 5; ++i) { +    FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), +                                         &Idents.get(FieldNames[i]), +                                         FieldTypes[i], /*DInfo=*/0, +                                         /*BitWidth=*/0, /*Mutable=*/false); +    T->addDecl(Field); +  } + +  for (size_t i = 0; i < BlockDeclRefDecls.size(); ++i) { +    const Expr *E = BlockDeclRefDecls[i]; +    const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(E); +    clang::IdentifierInfo *Name = 0; +    if (BDRE) { +      const ValueDecl *D = BDRE->getDecl(); +      Name = &Idents.get(D->getName()); +    } +    QualType FieldType = E->getType(); + +    if (BDRE && BDRE->isByRef()) +      FieldType = BuildByRefType(BDRE->getDecl()->getNameAsCString(), +                                 FieldType); + +    FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), +                                         Name, FieldType, /*DInfo=*/0, +                                         /*BitWidth=*/0, /*Mutable=*/false); +    T->addDecl(Field); +  } + +  T->completeDefinition(*this); + +  return getPointerType(getTagDeclType(T)); +} +  void ASTContext::setObjCFastEnumerationStateType(QualType T) {    const RecordType *Rec = T->getAs<RecordType>();    assert(Rec && "Invalid ObjCFAstEnumerationStateType"); @@ -2945,6 +3185,7 @@ static void EncodeBitField(const ASTContext *Context, std::string& S,    S += llvm::utostr(N);  } +// FIXME: Use SmallString for accumulating string.  void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,                                              bool ExpandPointedToStructures,                                              bool ExpandStructures, @@ -3420,7 +3661,7 @@ Qualifiers::GC ASTContext::getObjCGCAttrKind(const QualType &Ty) const {  /// compatible.  static bool areCompatVectorTypes(const VectorType *LHS,                                   const VectorType *RHS) { -  assert(LHS->isCanonical() && RHS->isCanonical()); +  assert(LHS->isCanonicalUnqualified() && RHS->isCanonicalUnqualified());    return LHS->getElementType() == RHS->getElementType() &&           LHS->getNumElements() == RHS->getNumElements();  } @@ -3979,7 +4220,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) {  unsigned ASTContext::getIntWidth(QualType T) {    if (T == BoolTy)      return 1; -  if (FixedWidthIntType* FWIT = dyn_cast<FixedWidthIntType>(T)) { +  if (FixedWidthIntType *FWIT = dyn_cast<FixedWidthIntType>(T)) {      return FWIT->getWidth();    }    // For builtin types, just use the standard type sizing method @@ -3988,10 +4229,18 @@ unsigned ASTContext::getIntWidth(QualType T) {  QualType ASTContext::getCorrespondingUnsignedType(QualType T) {    assert(T->isSignedIntegerType() && "Unexpected type"); -  if (const EnumType* ETy = T->getAs<EnumType>()) +   +  // Turn <4 x signed int> -> <4 x unsigned int> +  if (const VectorType *VTy = T->getAs<VectorType>()) +    return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()), +                         VTy->getNumElements()); + +  // For enums, we return the unsigned version of the base type. +  if (const EnumType *ETy = T->getAs<EnumType>())      T = ETy->getDecl()->getIntegerType(); -  const BuiltinType* BTy = T->getAs<BuiltinType>(); -  assert (BTy && "Unexpected signed integer type"); +   +  const BuiltinType *BTy = T->getAs<BuiltinType>(); +  assert(BTy && "Unexpected signed integer type");    switch (BTy->getKind()) {    case BuiltinType::Char_S:    case BuiltinType::SChar: diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index 4a46eab2e603..b59b45f6467e 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -50,7 +50,7 @@ CXXBasePaths::decl_iterator CXXBasePaths::found_decls_end() {  /// different base class subobjects of the same type. BaseType must be  /// an unqualified, canonical class type.  bool CXXBasePaths::isAmbiguous(QualType BaseType) { -  assert(BaseType->isCanonical() && "Base type must be the canonical type"); +  assert(BaseType.isCanonical() && "Base type must be the canonical type");    assert(BaseType.hasQualifiers() == 0 && "Base type must be unqualified");    std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType];    return Subobjects.second + (Subobjects.first? 1 : 0) > 1; diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index da7959b16f9f..d270a958f0ae 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -231,6 +231,8 @@ std::string NamedDecl::getQualifiedNameAsString() const {  }  std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { +  // FIXME: Collect contexts, then accumulate names to avoid unnecessary +  // std::string thrashing.    std::vector<std::string> Names;    std::string QualName;    const DeclContext *Ctx = getDeclContext(); @@ -252,7 +254,7 @@ std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const {                                             TemplateArgs.getFlatArgumentList(),                                             TemplateArgs.flat_size(),                                             P); -      Names.push_back(Spec->getIdentifier()->getName() + TemplateArgsStr); +      Names.push_back(Spec->getIdentifier()->getNameStart() + TemplateArgsStr);      } else if (const NamedDecl *ND = dyn_cast<NamedDecl>(Ctx))        Names.push_back(ND->getNameAsString());      else @@ -336,8 +338,15 @@ NamedDecl *NamedDecl::getUnderlyingDecl() {  //===----------------------------------------------------------------------===//  SourceLocation DeclaratorDecl::getTypeSpecStartLoc() const { -  if (DeclInfo) -    return DeclInfo->getTypeLoc().getTypeSpecRange().getBegin(); +  if (DeclInfo) { +    TypeLoc TL = DeclInfo->getTypeLoc(); +    while (true) { +      TypeLoc NextTL = TL.getNextTypeLoc(); +      if (!NextTL) +        return TL.getSourceRange().getBegin(); +      TL = NextTL; +    } +  }    return SourceLocation();  } @@ -408,10 +417,15 @@ MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const {    return getASTContext().getInstantiatedFromStaticDataMember(this);  } -void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { +void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, +                                         SourceLocation PointOfInstantiation) {    MemberSpecializationInfo *MSI = getMemberSpecializationInfo();    assert(MSI && "Not an instantiated static data member?");    MSI->setTemplateSpecializationKind(TSK); +  if (TSK != TSK_ExplicitSpecialization && +      PointOfInstantiation.isValid() && +      MSI->getPointOfInstantiation().isInvalid()) +    MSI->setPointOfInstantiation(PointOfInstantiation);  }  bool VarDecl::isTentativeDefinition(ASTContext &Context) const { @@ -812,18 +826,39 @@ TemplateSpecializationKind FunctionDecl::getTemplateSpecializationKind() const {  }  void -FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK) { +FunctionDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, +                                          SourceLocation PointOfInstantiation) {    if (FunctionTemplateSpecializationInfo *FTSInfo          = TemplateOrSpecialization.dyn_cast< -                                        FunctionTemplateSpecializationInfo*>()) +                                    FunctionTemplateSpecializationInfo*>()) {      FTSInfo->setTemplateSpecializationKind(TSK); -  else if (MemberSpecializationInfo *MSInfo -             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) +    if (TSK != TSK_ExplicitSpecialization && +        PointOfInstantiation.isValid() && +        FTSInfo->getPointOfInstantiation().isInvalid()) +      FTSInfo->setPointOfInstantiation(PointOfInstantiation); +  } else if (MemberSpecializationInfo *MSInfo +             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) {      MSInfo->setTemplateSpecializationKind(TSK); -  else +    if (TSK != TSK_ExplicitSpecialization && +        PointOfInstantiation.isValid() && +        MSInfo->getPointOfInstantiation().isInvalid()) +      MSInfo->setPointOfInstantiation(PointOfInstantiation); +  } else      assert(false && "Function cannot have a template specialization kind");  } +SourceLocation FunctionDecl::getPointOfInstantiation() const { +  if (FunctionTemplateSpecializationInfo *FTSInfo +        = TemplateOrSpecialization.dyn_cast< +                                        FunctionTemplateSpecializationInfo*>()) +    return FTSInfo->getPointOfInstantiation(); +  else if (MemberSpecializationInfo *MSInfo +             = TemplateOrSpecialization.dyn_cast<MemberSpecializationInfo*>()) +    return MSInfo->getPointOfInstantiation(); +   +  return SourceLocation(); +} +  bool FunctionDecl::isOutOfLine() const {    if (Decl::isOutOfLine())      return true; diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 7836b3f827ce..9a1c65416f71 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -299,7 +299,7 @@ void TemplateArgumentListBuilder::Append(const TemplateArgument& Arg) {    switch (Arg.getKind()) {      default: break;      case TemplateArgument::Type: -      assert(Arg.getAsType()->isCanonical() && "Type must be canonical!"); +      assert(Arg.getAsType().isCanonical() && "Type must be canonical!");        break;    } diff --git a/lib/AST/DeclarationName.cpp b/lib/AST/DeclarationName.cpp index 101ddd250933..56a597570dd0 100644 --- a/lib/AST/DeclarationName.cpp +++ b/lib/AST/DeclarationName.cpp @@ -51,7 +51,7 @@ public:  bool operator<(DeclarationName LHS, DeclarationName RHS) {    if (IdentifierInfo *LhsId = LHS.getAsIdentifierInfo())      if (IdentifierInfo *RhsId = RHS.getAsIdentifierInfo()) -      return strcmp(LhsId->getName(), RhsId->getName()) < 0; +      return LhsId->getName() < RhsId->getName();    return LHS.getAsOpaqueInteger() < RHS.getAsOpaqueInteger();  } @@ -60,7 +60,7 @@ bool operator<(DeclarationName LHS, DeclarationName RHS) {  DeclarationName::DeclarationName(Selector Sel) {    if (!Sel.getAsOpaquePtr()) { -    Ptr = StoredObjCZeroArgSelector; +    Ptr = 0;      return;    } diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 0e4a29f916fa..a4de3e5b0f7a 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -426,6 +426,18 @@ const char *CastExpr::getCastKindName() const {      return "IntegralToPointer";    case CastExpr::CK_PointerToIntegral:      return "PointerToIntegral"; +  case CastExpr::CK_ToVoid: +    return "ToVoid"; +  case CastExpr::CK_VectorSplat: +    return "VectorSplat"; +  case CastExpr::CK_IntegralCast: +    return "IntegralCast"; +  case CastExpr::CK_IntegralToFloating: +    return "IntegralToFloating"; +  case CastExpr::CK_FloatingToIntegral: +    return "FloatingToIntegral"; +  case CastExpr::CK_FloatingCast: +    return "FloatingCast";    }    assert(0 && "Unhandled cast kind!"); @@ -1740,40 +1752,36 @@ unsigned ExtVectorElementExpr::getNumElements() const {  /// containsDuplicateElements - Return true if any element access is repeated.  bool ExtVectorElementExpr::containsDuplicateElements() const { -  const char *compStr = Accessor->getName(); -  unsigned length = Accessor->getLength(); +  // FIXME: Refactor this code to an accessor on the AST node which returns the +  // "type" of component access, and share with code below and in Sema. +  llvm::StringRef Comp = Accessor->getName();    // Halving swizzles do not contain duplicate elements. -  if (!strcmp(compStr, "hi") || !strcmp(compStr, "lo") || -      !strcmp(compStr, "even") || !strcmp(compStr, "odd")) +  if (Comp == "hi" || Comp == "lo" || Comp == "even" || Comp == "odd")      return false;    // Advance past s-char prefix on hex swizzles. -  if (*compStr == 's' || *compStr == 'S') { -    compStr++; -    length--; -  } +  if (Comp[0] == 's' || Comp[0] == 'S') +    Comp = Comp.substr(1); -  for (unsigned i = 0; i != length-1; i++) { -    const char *s = compStr+i; -    for (const char c = *s++; *s; s++) -      if (c == *s) +  for (unsigned i = 0, e = Comp.size(); i != e; ++i) +    if (Comp.substr(i + 1).find(Comp[i]) != llvm::StringRef::npos)          return true; -  } +    return false;  }  /// getEncodedElementAccess - We encode the fields as a llvm ConstantArray.  void ExtVectorElementExpr::getEncodedElementAccess(                                    llvm::SmallVectorImpl<unsigned> &Elts) const { -  const char *compStr = Accessor->getName(); -  if (*compStr == 's' || *compStr == 'S') -    compStr++; +  llvm::StringRef Comp = Accessor->getName(); +  if (Comp[0] == 's' || Comp[0] == 'S') +    Comp = Comp.substr(1); -  bool isHi =   !strcmp(compStr, "hi"); -  bool isLo =   !strcmp(compStr, "lo"); -  bool isEven = !strcmp(compStr, "even"); -  bool isOdd  = !strcmp(compStr, "odd"); +  bool isHi =   Comp == "hi"; +  bool isLo =   Comp == "lo"; +  bool isEven = Comp == "even"; +  bool isOdd  = Comp == "odd";    for (unsigned i = 0, e = getNumElements(); i != e; ++i) {      uint64_t Index; @@ -1787,7 +1795,7 @@ void ExtVectorElementExpr::getEncodedElementAccess(      else if (isOdd)        Index = 2 * i + 1;      else -      Index = ExtVectorType::getAccessorIdx(compStr[i]); +      Index = ExtVectorType::getAccessorIdx(Comp[i]);      Elts.push_back(Index);    } diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 3a838fadafa4..6e0da4714912 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -117,7 +117,7 @@ void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {  }  const char *LabelStmt::getName() const { -  return getID()->getName(); +  return getID()->getNameStart();  }  // This is defined here to avoid polluting Stmt.h with importing Expr.h diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 0465999a94cc..cf71d6b986a2 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -244,7 +244,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {      // print a free standing tag decl (e.g. "struct x;").      const char *tagname;      if (const IdentifierInfo *II = TD->getIdentifier()) -      tagname = II->getName(); +      tagname = II->getNameStart();      else        tagname = "<anonymous>";      fprintf(F, "\"%s %s;\"", TD->getKindName(), tagname); @@ -253,7 +253,7 @@ void StmtDumper::DumpDeclarator(Decl *D) {      // print using-directive decl (e.g. "using namespace x;")      const char *ns;      if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier()) -      ns = II->getName(); +      ns = II->getNameStart();      else        ns = "<anonymous>";      fprintf(F, "\"%s %s;\"",UD->getDeclKindName(), ns); @@ -403,7 +403,7 @@ void StmtDumper::VisitMemberExpr(MemberExpr *Node) {  }  void StmtDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {    DumpExpr(Node); -  fprintf(F, " %s", Node->getAccessor().getName()); +  fprintf(F, " %s", Node->getAccessor().getNameStart());  }  void StmtDumper::VisitBinaryOperator(BinaryOperator *Node) {    DumpExpr(Node); @@ -495,7 +495,7 @@ void StmtDumper::VisitObjCMessageExpr(ObjCMessageExpr* Node) {    DumpExpr(Node);    fprintf(F, " selector=%s", Node->getSelector().getAsString().c_str());    IdentifierInfo* clsName = Node->getClassName(); -  if (clsName) fprintf(F, " class=%s", clsName->getName()); +  if (clsName) fprintf(F, " class=%s", clsName->getNameStart());  }  void StmtDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 05d0c2683545..2af19765dfaa 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1289,7 +1289,7 @@ void Stmt::printPretty(llvm::raw_ostream &OS, ASTContext& Context,      return;    } -  if (Policy.Dump) { +  if (Policy.Dump && &Context) {      dump(Context.getSourceManager());      return;    } diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 0293862baedb..5fb0178834ff 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -37,18 +37,6 @@ void Type::Destroy(ASTContext& C) {    C.Deallocate(this);  } -void ConstantArrayWithExprType::Destroy(ASTContext& C) { -  // FIXME: destruction of SizeExpr commented out due to resource contention. -  // SizeExpr->Destroy(C); -  // See FIXME in SemaDecl.cpp:1536: if we were able to either steal -  // or clone the SizeExpr there, then here we could freely delete it. -  // Since we do not know how to steal or clone, we keep a pointer to -  // a shared resource, but we cannot free it. -  // (There probably is a trivial solution ... for people knowing clang!). -  this->~ConstantArrayWithExprType(); -  C.Deallocate(this); -} -  void VariableArrayType::Destroy(ASTContext& C) {    if (SizeExpr)      SizeExpr->Destroy(C); @@ -177,8 +165,6 @@ bool Type::isDerivedType() const {    case Pointer:    case VariableArray:    case ConstantArray: -  case ConstantArrayWithExpr: -  case ConstantArrayWithoutExpr:    case IncompleteArray:    case FunctionProto:    case FunctionNoProto: @@ -642,6 +628,7 @@ bool Type::isSpecifierType() const {    case TypeOfExpr:    case TypeOf:    case TemplateTypeParm: +  case SubstTemplateTypeParm:    case TemplateSpecialization:    case QualifiedName:    case Typename: @@ -737,18 +724,6 @@ void ObjCObjectPointerType::Profile(llvm::FoldingSetNodeID &ID) {      Profile(ID, getPointeeType(), 0, 0);  } -void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID, -                                   QualType OIT, ObjCProtocolDecl **protocols, -                                   unsigned NumProtocols) { -  ID.AddPointer(OIT.getAsOpaquePtr()); -  for (unsigned i = 0; i != NumProtocols; i++) -    ID.AddPointer(protocols[i]); -} - -void ObjCProtocolListType::Profile(llvm::FoldingSetNodeID &ID) { -    Profile(ID, getBaseType(), &Protocols[0], getNumProtocols()); -} -  /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to  /// potentially looking through *all* consequtive typedefs.  This returns the  /// sum of the type qualifiers, so if you have: @@ -1072,10 +1047,10 @@ void LValueReferenceType::getAsStringInternal(std::string &S, const PrintingPoli    // Handle things like 'int (&A)[4];' correctly.    // FIXME: this should include vectors, but vectors use attributes I guess. -  if (isa<ArrayType>(getPointeeType())) +  if (isa<ArrayType>(getPointeeTypeAsWritten()))      S = '(' + S + ')'; -  getPointeeType().getAsStringInternal(S, Policy); +  getPointeeTypeAsWritten().getAsStringInternal(S, Policy);  }  void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { @@ -1083,10 +1058,10 @@ void RValueReferenceType::getAsStringInternal(std::string &S, const PrintingPoli    // Handle things like 'int (&&A)[4];' correctly.    // FIXME: this should include vectors, but vectors use attributes I guess. -  if (isa<ArrayType>(getPointeeType())) +  if (isa<ArrayType>(getPointeeTypeAsWritten()))      S = '(' + S + ')'; -  getPointeeType().getAsStringInternal(S, Policy); +  getPointeeTypeAsWritten().getAsStringInternal(S, Policy);  }  void MemberPointerType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { @@ -1111,29 +1086,6 @@ void ConstantArrayType::getAsStringInternal(std::string &S, const PrintingPolicy    getElementType().getAsStringInternal(S, Policy);  } -void ConstantArrayWithExprType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { -  if (Policy.ConstantArraySizeAsWritten) { -    std::string SStr; -    llvm::raw_string_ostream s(SStr); -    getSizeExpr()->printPretty(s, 0, Policy); -    S += '['; -    S += s.str(); -    S += ']'; -    getElementType().getAsStringInternal(S, Policy); -  } -  else -    ConstantArrayType::getAsStringInternal(S, Policy); -} - -void ConstantArrayWithoutExprType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const { -  if (Policy.ConstantArraySizeAsWritten) { -    S += "[]"; -    getElementType().getAsStringInternal(S, Policy); -  } -  else -    ConstantArrayType::getAsStringInternal(S, Policy); -} -  void IncompleteArrayType::getAsStringInternal(std::string &S, const PrintingPolicy &Policy) const {    S += "[]"; @@ -1290,7 +1242,7 @@ void FunctionProtoType::getAsStringInternal(std::string &S, const PrintingPolicy  void TypedefType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const {    if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'.      InnerString = ' ' + InnerString; -  InnerString = getDecl()->getIdentifier()->getName() + InnerString; +  InnerString = getDecl()->getIdentifier()->getName().str() + InnerString;  }  void TemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { @@ -1301,7 +1253,11 @@ void TemplateTypeParmType::getAsStringInternal(std::string &InnerString, const P      InnerString = "type-parameter-" + llvm::utostr_32(Depth) + '-' +        llvm::utostr_32(Index) + InnerString;    else -    InnerString = Name->getName() + InnerString; +    InnerString = Name->getName().str() + InnerString; +} + +void SubstTemplateTypeParmType::getAsStringInternal(std::string &InnerString, const PrintingPolicy &Policy) const { +  getReplacementType().getAsStringInternal(InnerString, Policy);  }  std::string @@ -1495,25 +1451,6 @@ void ObjCObjectPointerType::getAsStringInternal(std::string &InnerString,    InnerString = ObjCQIString + InnerString;  } -void ObjCProtocolListType::getAsStringInternal(std::string &InnerString, -                                           const PrintingPolicy &Policy) const { -  if (!InnerString.empty())    // Prefix the basic type, e.g. 'typedefname X'. -    InnerString = ' ' + InnerString; - -  std::string ObjCQIString = getBaseType().getAsString(Policy); -  ObjCQIString += '<'; -  bool isFirst = true; -  for (qual_iterator I = qual_begin(), E = qual_end(); I != E; ++I) { -    if (isFirst) -      isFirst = false; -    else -      ObjCQIString += ','; -    ObjCQIString += (*I)->getNameAsString(); -  } -  ObjCQIString += '>'; -  InnerString = ObjCQIString + InnerString; -} -  void ElaboratedType::getAsStringInternal(std::string &InnerString,                                           const PrintingPolicy &Policy) const {    std::string TypeStr; @@ -1534,11 +1471,11 @@ void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy    const char *Kind = Policy.SuppressTagKind? 0 : getDecl()->getKindName();    const char *ID;    if (const IdentifierInfo *II = getDecl()->getIdentifier()) -    ID = II->getName(); +    ID = II->getNameStart();    else if (TypedefDecl *Typedef = getDecl()->getTypedefForAnonDecl()) {      Kind = 0;      assert(Typedef->getIdentifier() && "Typedef without identifier?"); -    ID = Typedef->getIdentifier()->getName(); +    ID = Typedef->getIdentifier()->getNameStart();    } else      ID = "<anonymous>"; @@ -1573,7 +1510,7 @@ void TagType::getAsStringInternal(std::string &InnerString, const PrintingPolicy                                             TemplateArgs.getFlatArgumentList(),                                             TemplateArgs.flat_size(),                                             Policy); -        MyPart = Spec->getIdentifier()->getName() + TemplateArgsStr; +        MyPart = Spec->getIdentifier()->getName().str() + TemplateArgsStr;        } else if (TagDecl *Tag = dyn_cast<TagDecl>(DC)) {          if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl())            MyPart = Typedef->getIdentifier()->getName(); diff --git a/lib/AST/TypeLoc.cpp b/lib/AST/TypeLoc.cpp index 04e708370af3..50a512028e96 100644 --- a/lib/AST/TypeLoc.cpp +++ b/lib/AST/TypeLoc.cpp @@ -20,55 +20,32 @@ using namespace clang;  //===----------------------------------------------------------------------===//  namespace { - -/// \brief Return the source range for the visited TypeSpecLoc. -class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { -public: -#define ABSTRACT_TYPELOC(CLASS) +  class TypeLocRanger : public TypeLocVisitor<TypeLocRanger, SourceRange> { +  public: +#define ABSTRACT_TYPELOC(CLASS, PARENT)  #define TYPELOC(CLASS, PARENT) \ -    SourceRange Visit##CLASS(CLASS TyLoc) { return TyLoc.getSourceRange(); } +    SourceRange Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ +      return TyLoc.getSourceRange(); \ +    }  #include "clang/AST/TypeLocNodes.def" - -  SourceRange VisitTypeLoc(TypeLoc TyLoc) { -    assert(0 && "A typeloc wrapper was not handled!"); -    return SourceRange(); -  } -}; - -} - -SourceRange TypeLoc::getSourceRange() const { -  if (isNull()) -    return SourceRange(); -  return TypeLocRanger().Visit(*this); +  };  } -/// \brief Find the TypeSpecLoc that is part of this TypeLoc. -TypeSpecLoc TypeLoc::getTypeSpecLoc() const { -  if (isNull()) -    return TypeSpecLoc(); -  UnqualTypeLoc Cur = getUnqualifiedLoc(); -  if (const DeclaratorLoc *DL = dyn_cast<DeclaratorLoc>(&Cur)) -    return DL->getTypeSpecLoc(); -  return cast<TypeSpecLoc>(Cur); +SourceRange TypeLoc::getSourceRangeImpl(TypeLoc TL) { +  if (TL.isNull()) return SourceRange(); +  return TypeLocRanger().Visit(TL);  }  namespace { - -/// \brief Report the full source info data size for the visited TypeLoc. -class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { -public: -#define ABSTRACT_TYPELOC(CLASS) +  class TypeSizer : public TypeLocVisitor<TypeSizer, unsigned> { +  public: +#define ABSTRACT_TYPELOC(CLASS, PARENT)  #define TYPELOC(CLASS, PARENT) \ -    unsigned Visit##CLASS(CLASS TyLoc) { return TyLoc.getFullDataSize(); } +    unsigned Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ +      return TyLoc.getFullDataSize(); \ +    }  #include "clang/AST/TypeLocNodes.def" - -  unsigned VisitTypeLoc(TypeLoc TyLoc) { -    assert(0 && "A type loc wrapper was not handled!"); -    return 0; -  } -}; - +  };  }  /// \brief Returns the size of the type source info data block. @@ -78,138 +55,42 @@ unsigned TypeLoc::getFullDataSizeForType(QualType Ty) {  }  namespace { - -/// \brief Return the "next" TypeLoc for the visited TypeLoc, e.g for "int*" the -/// TypeLoc is a PointerLoc and next TypeLoc is for "int". -class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { -public: -#define TYPELOC(CLASS, PARENT) -#define DECLARATOR_TYPELOC(CLASS, TYPE) \ -  TypeLoc Visit##CLASS(CLASS TyLoc); +  class NextLoc : public TypeLocVisitor<NextLoc, TypeLoc> { +  public: +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ +    TypeLoc Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ +      return TyLoc.getNextTypeLoc(); \ +    }  #include "clang/AST/TypeLocNodes.def" - -  TypeLoc VisitTypeSpecLoc(TypeLoc TyLoc) { return TypeLoc(); } -  TypeLoc VisitObjCProtocolListLoc(ObjCProtocolListLoc TL); -  TypeLoc VisitQualifiedLoc(QualifiedLoc TyLoc) { -    return TyLoc.getUnqualifiedLoc(); -  } - -  TypeLoc VisitTypeLoc(TypeLoc TyLoc) { -    assert(0 && "A declarator loc wrapper was not handled!"); -    return TypeLoc(); -  } -}; - -} - -TypeLoc NextLoc::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) { -  return TL.getBaseTypeLoc(); -} - -TypeLoc NextLoc::VisitPointerLoc(PointerLoc TL) { -  return TL.getPointeeLoc(); -} -TypeLoc NextLoc::VisitMemberPointerLoc(MemberPointerLoc TL) { -  return TL.getPointeeLoc(); -} -TypeLoc NextLoc::VisitBlockPointerLoc(BlockPointerLoc TL) { -  return TL.getPointeeLoc(); -} -TypeLoc NextLoc::VisitReferenceLoc(ReferenceLoc TL) { -  return TL.getPointeeLoc(); -} -TypeLoc NextLoc::VisitFunctionLoc(FunctionLoc TL) { -  return TL.getResultLoc(); -} -TypeLoc NextLoc::VisitArrayLoc(ArrayLoc TL) { -  return TL.getElementLoc(); +  };  }  /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the  /// TypeLoc is a PointerLoc and next TypeLoc is for "int". -TypeLoc TypeLoc::getNextTypeLoc() const { -  //llvm::errs() << "getNextTypeLoc: Ty=" << Ty << ", Data=" << Data << "\n"; -  TypeLoc Tmp = NextLoc().Visit(*this); -  //llvm::errs() << "  result: Ty=" << Tmp.Ty << ", Data=" << Tmp.Data << "\n"; -  return Tmp; +TypeLoc TypeLoc::getNextTypeLocImpl(TypeLoc TL) { +  return NextLoc().Visit(TL);  } -//===----------------------------------------------------------------------===// -// TypeSpecLoc Implementation -//===----------------------------------------------------------------------===// -  namespace { -class TypeSpecChecker : public TypeLocVisitor<TypeSpecChecker, bool> { -public: -  bool VisitTypeSpecLoc(TypeSpecLoc TyLoc) { return true; } -}; - -} - -bool TypeSpecLoc::classof(const UnqualTypeLoc *TL) { -  return TypeSpecChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// DeclaratorLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -/// \brief Return the TypeSpecLoc for the visited DeclaratorLoc. -class TypeSpecGetter : public TypeLocVisitor<TypeSpecGetter, TypeSpecLoc> { -public: -#define TYPELOC(CLASS, PARENT) -#define DECLARATOR_TYPELOC(CLASS, TYPE) \ -    TypeSpecLoc Visit##CLASS(CLASS TyLoc) { return TyLoc.getTypeSpecLoc(); } +  struct TypeLocInitializer : public TypeLocVisitor<TypeLocInitializer> { +    SourceLocation Loc; +    TypeLocInitializer(SourceLocation Loc) : Loc(Loc) {} +   +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ +    void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc) { \ +      TyLoc.initializeLocal(Loc); \ +    }  #include "clang/AST/TypeLocNodes.def" - -  TypeSpecLoc VisitTypeLoc(TypeLoc TyLoc) { -    assert(0 && "A declarator loc wrapper was not handled!"); -    return TypeSpecLoc(); -  } - -  TypeSpecLoc VisitQualifiedLoc(QualifiedLoc TyLoc) { -    return Visit(TyLoc.getUnqualifiedLoc()); -  } -}; - -} - -/// \brief Find the TypeSpecLoc that is part of this DeclaratorLoc. -TypeSpecLoc DeclaratorLoc::getTypeSpecLoc() const { -  return TypeSpecGetter().Visit(*this); -} - -namespace { - -class DeclaratorLocChecker : public TypeLocVisitor<DeclaratorLocChecker, bool> { -public: -  bool VisitDeclaratorLoc(DeclaratorLoc TyLoc) { return true; } -}; - -} - -bool DeclaratorLoc::classof(const UnqualTypeLoc *TL) { -  return DeclaratorLocChecker().Visit(*TL); -} - -//===----------------------------------------------------------------------===// -// DefaultTypeSpecLoc Implementation -//===----------------------------------------------------------------------===// - -namespace { - -class DefaultTypeSpecLocChecker : -                        public TypeLocVisitor<DefaultTypeSpecLocChecker, bool> { -public: -  bool VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { return true; } -}; - +  };  } -bool DefaultTypeSpecLoc::classofType(const Type *Ty) { -  return -    DefaultTypeSpecLocChecker().Visit(UnqualTypeLoc(const_cast<Type*>(Ty), 0)); +/// \brief Initializes a type location, and all of its children +/// recursively, as if the entire tree had been written in the +/// given location. +void TypeLoc::initializeImpl(TypeLoc TL, SourceLocation Loc) { +  do { +    TypeLocInitializer(Loc).Visit(TL); +  } while ((TL = TL.getNextTypeLoc()));  } -  diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index a4cb66be04b3..640912ad6b39 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -33,6 +33,12 @@ AnalysisContextManager::~AnalysisContextManager() {      delete I->second;  } +void AnalysisContextManager::clear() { +  for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I) +    delete I->second; +  Contexts.clear(); +} +  Stmt *AnalysisContext::getBody() {    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))      return FD->getBody(); @@ -103,6 +109,21 @@ void ScopeContext::Profile(llvm::FoldingSetNodeID &ID, AnalysisContext *ctx,    ID.AddPointer(s);  } +LocationContextManager::~LocationContextManager() { +  clear(); +} + +void LocationContextManager::clear() { +  for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(), +       E = Contexts.end(); I != E; ) {     +    LocationContext *LC = &*I; +    ++I; +    delete LC; +  } +   +  Contexts.clear(); +} +  StackFrameContext*  LocationContextManager::getStackFrame(AnalysisContext *ctx,                                        const LocationContext *parent, diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp index af300f36fa72..aa2d0ab5a763 100644 --- a/lib/Analysis/BasicObjCFoundationChecks.cpp +++ b/lib/Analysis/BasicObjCFoundationChecks.cpp @@ -45,9 +45,9 @@ static const ObjCInterfaceType* GetReceiverType(const ObjCMessageExpr* ME) {  }  static const char* GetReceiverNameType(const ObjCMessageExpr* ME) { -  const ObjCInterfaceType *ReceiverType = GetReceiverType(ME); -  return ReceiverType ? ReceiverType->getDecl()->getIdentifier()->getName() -                      : NULL; +  if (const ObjCInterfaceType *ReceiverType = GetReceiverType(ME)) +    return ReceiverType->getDecl()->getIdentifier()->getNameStart(); +  return NULL;  }  namespace { @@ -62,7 +62,7 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {    BugReporter& BR;    ASTContext &Ctx; -  bool isNSString(const ObjCInterfaceType *T, const char* suffix); +  bool isNSString(const ObjCInterfaceType *T, llvm::StringRef suffix);    bool AuditNSString(ExplodedNode* N, const ObjCMessageExpr* ME);    void Warn(ExplodedNode* N, const Expr* E, const std::string& s); @@ -114,18 +114,8 @@ bool BasicObjCFoundationChecks::Audit(ExplodedNode* N,    if (!ReceiverType)      return false; -  const char* name = ReceiverType->getDecl()->getIdentifier()->getName(); - -  if (!name) -    return false; - -  if (name[0] != 'N' || name[1] != 'S') -    return false; - -  name += 2; - -  // FIXME: Make all of this faster. -  if (isNSString(ReceiverType, name)) +  if (isNSString(ReceiverType, +                 ReceiverType->getDecl()->getIdentifier()->getName()))      return AuditNSString(N, ME);    return false; @@ -158,8 +148,8 @@ bool BasicObjCFoundationChecks::CheckNilArg(ExplodedNode* N, unsigned Arg) {  //===----------------------------------------------------------------------===//  bool BasicObjCFoundationChecks::isNSString(const ObjCInterfaceType *T, -                                           const char* suffix) { -  return !strcmp("String", suffix) || !strcmp("MutableString", suffix); +                                           llvm::StringRef ClassName) { +  return ClassName == "NSString" || ClassName == "NSMutableString";  }  bool BasicObjCFoundationChecks::AuditNSString(ExplodedNode* N, diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index a4f451f36490..d81d83c7bfa2 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -49,7 +49,8 @@ public:                                   QualType T = QualType());    const GRState *InvalidateRegion(const GRState *state, const MemRegion *R, -                                  const Expr *E, unsigned Count); +                                  const Expr *E, unsigned Count, +                                  InvalidatedSymbols *IS);    const GRState *Bind(const GRState *state, Loc L, SVal V) {      return state->makeWithStore(BindInternal(state->getStore(), L, V)); @@ -623,12 +624,21 @@ StoreManager::BindingsHandler::~BindingsHandler() {}  const GRState *BasicStoreManager::InvalidateRegion(const GRState *state,                                                     const MemRegion *R,                                                     const Expr *E, -                                                   unsigned Count) { +                                                   unsigned Count, +                                                   InvalidatedSymbols *IS) {    R = R->getBaseRegion();    if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))        return state; +  if (IS) { +    BindingsTy B = GetBindings(state->getStore()); +    if (BindingsTy::data_type *Val = B.lookup(R)) { +      if (SymbolRef Sym = Val->getAsSymbol()) +        IS->insert(Sym); +    } +  } +    QualType T = cast<TypedRegion>(R)->getValueType(R->getContext());    SVal V = ValMgr.getConjuredSymbolVal(R, E, T, Count);    return Bind(state, loc::MemRegionVal(R), V); diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp index 7b1d50cb3aee..31417597f798 100644 --- a/lib/Analysis/CFG.cpp +++ b/lib/Analysis/CFG.cpp @@ -22,6 +22,7 @@  #include "llvm/Support/Format.h"  #include "llvm/ADT/DenseMap.h"  #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/OwningPtr.h"  using namespace clang; @@ -51,7 +52,7 @@ static SourceLocation GetEndLoc(Decl* D) {  ///  class VISIBILITY_HIDDEN CFGBuilder {    ASTContext *Context; -  CFG* cfg; +  llvm::OwningPtr<CFG> cfg;    CFGBlock* Block;    CFGBlock* Succ; @@ -79,8 +80,6 @@ public:                            ContinueTargetBlock(NULL), BreakTargetBlock(NULL),                            SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL) {} -  ~CFGBuilder() { delete cfg; } -    // buildCFG - Used by external clients to construct the CFG.    CFG* buildCFG(Stmt *Statement, ASTContext *C); @@ -195,7 +194,7 @@ static VariableArrayType* FindVA(Type* t) {  ///  NULL.  CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {    Context = C; -  assert(cfg); +  assert(cfg.get());    if (!Statement)      return NULL; @@ -210,7 +209,8 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {    // Visit the statements and create the CFG.    CFGBlock* B = addStmt(Statement); -  if (!B) B = Succ; +  if (!B) +    B = Succ;    if (B) {      // Finalize the last constructed block.  This usually involves reversing the @@ -254,17 +254,7 @@ CFG* CFGBuilder::buildCFG(Stmt* Statement, ASTContext* C) {    // Create an empty entry block that has no predecessors.    cfg->setEntry(createBlock()); -  if (badCFG) { -    delete cfg; -    cfg = NULL; -    return NULL; -  } - -  // NULL out cfg so that repeated calls to the builder will fail and that the -  // ownership of the constructed CFG is passed to the caller. -  CFG* t = cfg; -  cfg = NULL; -  return t; +  return badCFG ? NULL : cfg.take();  }  /// createBlock - Used to lazily create blocks that are connected diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index eb1265dda7ea..c629ad1d9612 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -81,7 +81,7 @@ static NamingConvention deriveNamingConvention(Selector S) {    if (!II)      return NoConvention; -  const char *s = II->getName(); +  const char *s = II->getNameStart();    // A method/function name may contain a prefix.  We don't know it is there,    // however, until we encounter the first '_'. @@ -93,12 +93,14 @@ static NamingConvention deriveNamingConvention(Selector S) {      // Skip '_'.      if (*s == '_') {        if (InPossiblePrefix) { +        // If we already have a convention, return it.  Otherwise, skip +        // the prefix as if it wasn't there. +        if (C != NoConvention) +          break; +                  InPossiblePrefix = false;          AtBeginning = true; -        // Discard whatever 'convention' we -        // had already derived since it occurs -        // in the prefix. -        C = NoConvention; +        assert(C == NoConvention);        }        ++s;        continue; @@ -208,41 +210,16 @@ static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) {  // Type querying functions.  //===----------------------------------------------------------------------===// -static bool hasPrefix(const char* s, const char* prefix) { -  if (!prefix) -    return true; - -  char c = *s; -  char cP = *prefix; - -  while (c != '\0' && cP != '\0') { -    if (c != cP) break; -    c = *(++s); -    cP = *(++prefix); -  } - -  return cP == '\0'; -} - -static bool hasSuffix(const char* s, const char* suffix) { -  const char* loc = strstr(s, suffix); -  return loc && strcmp(suffix, loc) == 0; -} -  static bool isRefType(QualType RetTy, const char* prefix,                        ASTContext* Ctx = 0, const char* name = 0) {    // Recursively walk the typedef stack, allowing typedefs of reference types. -  while (1) { -    if (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) { -      const char* TDName = TD->getDecl()->getIdentifier()->getName(); -      if (hasPrefix(TDName, prefix) && hasSuffix(TDName, "Ref")) -        return true; +  while (TypedefType* TD = dyn_cast<TypedefType>(RetTy.getTypePtr())) { +    llvm::StringRef TDName = TD->getDecl()->getIdentifier()->getName(); +    if (TDName.startswith(prefix) && TDName.endswith("Ref")) +      return true; -      RetTy = TD->getDecl()->getUnderlyingType(); -      continue; -    } -    break; +    RetTy = TD->getDecl()->getUnderlyingType();    }    if (!Ctx || !name) @@ -254,7 +231,7 @@ static bool isRefType(QualType RetTy, const char* prefix,      return false;    // Does the name start with the prefix? -  return hasPrefix(name, prefix); +  return llvm::StringRef(name).startswith(prefix);  }  //===----------------------------------------------------------------------===// @@ -956,7 +933,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {      // [PR 3337] Use 'getAs<FunctionType>' to strip away any typedefs on the      // function's type.      const FunctionType* FT = FD->getType()->getAs<FunctionType>(); -    const char* FName = FD->getIdentifier()->getName(); +    const char* FName = FD->getIdentifier()->getNameStart();      // Strip away preceding '_'.  Doing this here will effect all the checks      // down below. @@ -1009,7 +986,7 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {            // Part of <rdar://problem/6961230>. (IOKit)            // This should be addressed using a API table.            ScratchArgs = AF.Add(ScratchArgs, 2, DecRef); -          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing); +          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,DoNothing);          }          break; @@ -1432,16 +1409,19 @@ void RetainSummaryManager::InitializeClassMethodSummaries() {    addNSObjectClsMethSummary(GetUnarySelector("allocWithZone", Ctx), Summ);    // Create the [NSAssertionHandler currentHander] summary. -  addClsMethSummary(&Ctx.Idents.get("NSAssertionHandler"), -                GetNullarySelector("currentHandler", Ctx), +  addClassMethSummary("NSAssertionHandler", "currentHandler",                  getPersistentSummary(RetEffect::MakeNotOwned(RetEffect::ObjC)));    // Create the [NSAutoreleasePool addObject:] summary.    ScratchArgs = AF.Add(ScratchArgs, 0, Autorelease); -  addClsMethSummary(&Ctx.Idents.get("NSAutoreleasePool"), -                    GetUnarySelector("addObject", Ctx), -                    getPersistentSummary(RetEffect::MakeNoRet(), -                                         DoNothing, Autorelease)); +  addClassMethSummary("NSAutoreleasePool", "addObject", +                      getPersistentSummary(RetEffect::MakeNoRet(), +                                           DoNothing, Autorelease)); + +  // Create a summary for [NSCursor dragCopyCursor]. +  addClassMethSummary("NSCursor", "dragCopyCursor", +                      getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, +                                           DoNothing));    // Create the summaries for [NSObject performSelector...].  We treat    // these as 'stop tracking' for the arguments because they are often @@ -2856,14 +2836,13 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst,            // FIXME: What about layers of ElementRegions?          } -        // Is the invalidated variable something that we were tracking? -        SymbolRef Sym = state->getSValAsScalarOrLoc(R).getAsLocSymbol(); - -        // Remove any existing reference-count binding. -        if (Sym) -          state = state->remove<RefBindings>(Sym); - -        state = StoreMgr.InvalidateRegion(state, R, *I, Count); +        StoreManager::InvalidatedSymbols IS; +        state = StoreMgr.InvalidateRegion(state, R, *I, Count, &IS); +        for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(), +             E = IS.end(); I!=E; ++I) { +          // Remove any existing reference-count binding. +          state = state->remove<RefBindings>(*I); +        }        }        else {          // Nuke all other arguments passed by reference. diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 5079acef54b4..ea0255ded8a9 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -207,7 +207,7 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {    if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {      // Precondition: the first argument of 'main' is an integer guaranteed      //  to be > 0. -    if (strcmp(FD->getIdentifier()->getName(), "main") == 0 && +    if (FD->getIdentifier()->getName() == "main" &&          FD->getNumParams() > 0) {        const ParmVarDecl *PD = FD->getParamDecl(0);        QualType T = PD->getType(); @@ -1445,10 +1445,9 @@ static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,      // HACK: Some functions are not marked noreturn, and don't return.      //  Here are a few hardwired ones.  If this takes too long, we can      //  potentially cache these results. -    const char* s = FD->getIdentifier()->getName(); -    unsigned n = strlen(s); +    const char* s = FD->getIdentifier()->getNameStart(); -    switch (n) { +    switch (FD->getIdentifier()->getLength()) {      default:        break; @@ -2788,66 +2787,55 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,        SVal RightV = state->getSVal(RHS);        BinaryOperator::Opcode Op = B->getOpcode(); -      switch (Op) { -        case BinaryOperator::Assign: { - -          // EXPERIMENTAL: "Conjured" symbols. -          // FIXME: Handle structs. -          QualType T = RHS->getType(); - -          if ((RightV.isUnknown() || -               !getConstraintManager().canReasonAbout(RightV)) -              && (Loc::IsLocType(T) || -                  (T->isScalarType() && T->isIntegerType()))) { -            unsigned Count = Builder->getCurrentBlockCount(); -            RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count); -          } -          // Simulate the effects of a "store":  bind the value of the RHS -          // to the L-Value represented by the LHS. -          EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV), -                    LeftV, RightV); -          continue; +      if (Op == BinaryOperator::Assign) { +        // EXPERIMENTAL: "Conjured" symbols. +        // FIXME: Handle structs. +        QualType T = RHS->getType(); +         +        if ((RightV.isUnknown()||!getConstraintManager().canReasonAbout(RightV)) +            && (Loc::IsLocType(T) || (T->isScalarType()&&T->isIntegerType()))) { +          unsigned Count = Builder->getCurrentBlockCount(); +          RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);          } - -          // FALL-THROUGH. - -        default: { - -          if (B->isAssignmentOp()) -            break; - -          // Process non-assignments except commas or short-circuited -          // logical expressions (LAnd and LOr). -          SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType()); - -          if (Result.isUnknown()) { -            if (OldSt != state) { -              // Generate a new node if we have already created a new state. -              MakeNode(Dst, B, *I2, state); -            } -            else -              Dst.Add(*I2); - -            continue; +         +        // Simulate the effects of a "store":  bind the value of the RHS +        // to the L-Value represented by the LHS. +        EvalStore(Dst, B, LHS, *I2, state->BindExpr(B, RightV), LeftV, RightV); +        continue; +      } +       +      if (!B->isAssignmentOp()) { +        // Process non-assignments except commas or short-circuited +        // logical expressions (LAnd and LOr). +        SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType()); +         +        if (Result.isUnknown()) { +          if (OldSt != state) { +            // Generate a new node if we have already created a new state. +            MakeNode(Dst, B, *I2, state);            } - -          state = state->BindExpr(B, Result); - -          if (Result.isUndef()) { -            // The operands were *not* undefined, but the result is undefined. -            // This is a special node that should be flagged as an error. -            if (ExplodedNode *UndefNode = Builder->generateNode(B, state, *I2)){ -              UndefNode->markAsSink(); -              UndefResults.insert(UndefNode); -            } -            continue; +          else +            Dst.Add(*I2); +           +          continue; +        } +         +        state = state->BindExpr(B, Result); +         +        if (Result.isUndef()) { +          // The operands were *not* undefined, but the result is undefined. +          // This is a special node that should be flagged as an error. +          if (ExplodedNode *UndefNode = Builder->generateNode(B, state, *I2)){ +            UndefNode->markAsSink(); +            UndefResults.insert(UndefNode);            } - -          // Otherwise, create a new node. -          MakeNode(Dst, B, *I2, state);            continue;          } +         +        // Otherwise, create a new node. +        MakeNode(Dst, B, *I2, state); +        continue;        }        assert (B->isCompoundAssignmentOp()); @@ -2875,7 +2863,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B,        for (ExplodedNodeSet::iterator I3=Tmp3.begin(), E3=Tmp3.end(); I3!=E3;             ++I3) { -          state = GetState(*I3);          SVal V = state->getSVal(LHS); diff --git a/lib/Analysis/GRExprEngineInternalChecks.cpp b/lib/Analysis/GRExprEngineInternalChecks.cpp index cc1ec4b77e48..da24192c9d5a 100644 --- a/lib/Analysis/GRExprEngineInternalChecks.cpp +++ b/lib/Analysis/GRExprEngineInternalChecks.cpp @@ -742,11 +742,11 @@ void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {    }  } -class VISIBILITY_HIDDEN CheckBadDiv : public CheckerVisitor<CheckBadDiv> { +class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {    DivZero *BT;  public: -  CheckBadDiv() : BT(0) {} -  ~CheckBadDiv() {} +  CheckDivZero() : BT(0) {} +  ~CheckDivZero() {}    const void *getTag() {      static int x; @@ -756,8 +756,8 @@ public:    void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);  }; -void CheckBadDiv::PreVisitBinaryOperator(CheckerContext &C, -                                         const BinaryOperator *B) { +void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C, +                                          const BinaryOperator *B) {    BinaryOperator::Opcode Op = B->getOpcode();    if (Op != BinaryOperator::Div &&        Op != BinaryOperator::Rem && @@ -792,7 +792,8 @@ void CheckBadDiv::PreVisitBinaryOperator(CheckerContext &C,      return;    } -  // If we get here, then the denom should not be zero. +  // If we get here, then the denom should not be zero. We abandon the implicit +  // zero denom case for now.    if (stateNotZero != C.getState())      C.addTransition(C.GenerateNode(B, stateNotZero));  } @@ -828,5 +829,5 @@ void GRExprEngine::RegisterInternalChecks() {    registerCheck(new CheckAttrNonNull());    registerCheck(new CheckUndefinedArg());    registerCheck(new CheckBadCall()); -  registerCheck(new CheckBadDiv()); +  registerCheck(new CheckDivZero());  } diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index 4d96c8f8f401..ae78d1f35ff6 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/lib/Analysis/LiveVariables.cpp @@ -21,9 +21,7 @@  #include "llvm/ADT/SmallPtrSet.h"  #include "llvm/ADT/SmallVector.h"  #include "llvm/Support/Compiler.h" - -#include <string.h> -#include <stdio.h> +#include "llvm/Support/raw_ostream.h"  using namespace clang; @@ -341,20 +339,19 @@ void LiveVariables::dumpLiveness(const ValTy& V, SourceManager& SM) const {    for (AnalysisDataTy::decl_iterator I = AD.begin_decl(),                                       E = AD.end_decl(); I!=E; ++I)      if (V.getDeclBit(I->second)) { -      fprintf(stderr, "  %s <", I->first->getIdentifier()->getName()); +      llvm::errs() << "  " << I->first->getIdentifier()->getName() << " <";        I->first->getLocation().dump(SM); -      fprintf(stderr, ">\n"); +      llvm::errs() << ">\n";      }  }  void LiveVariables::dumpBlockLiveness(SourceManager& M) const {    for (BlockDataMapTy::iterator I = getBlockDataMap().begin(),         E = getBlockDataMap().end(); I!=E; ++I) { -    fprintf(stderr, "\n[ B%d (live variables at block exit) ]\n", -            I->first->getBlockID()); - +    llvm::errs() << "\n[ B" << I->first->getBlockID() +                 << " (live variables at block exit) ]\n";      dumpLiveness(I->second,M);    } -  fprintf(stderr,"\n"); +  llvm::errs() << "\n";  } diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index 9456ab64542c..780772a6f129 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -262,7 +262,8 @@ public:    //===-------------------------------------------------------------------===//    const GRState *InvalidateRegion(const GRState *state, const MemRegion *R, -                                  const Expr *E, unsigned Count); +                                  const Expr *E, unsigned Count, +                                  InvalidatedSymbols *IS);  private:    void RemoveSubRegionBindings(RegionBindings &B, const MemRegion *R, @@ -455,7 +456,8 @@ void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,  const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,                                                      const MemRegion *R,                                                      const Expr *Ex, -                                                    unsigned Count) { +                                                    unsigned Count, +                                                    InvalidatedSymbols *IS) {    ASTContext& Ctx = StateMgr.getContext();    // Strip away casts. @@ -490,9 +492,21 @@ const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,      if (Optional<SVal> V = getDirectBinding(B, R)) {        if (const MemRegion *RV = V->getAsRegion())          WorkList.push_back(RV); +       +      // A symbol?  Mark it touched by the invalidation. +      if (IS) { +        if (SymbolRef Sym = V->getAsSymbol()) +          IS->insert(Sym); +      }      } -    // Handle region. +    // Symbolic region?  Mark that symbol touched by the invalidation. +    if (IS) { +      if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) +        IS->insert(SR->getSymbol()); +    } + +    // Handle the region itself.      if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R) ||          isa<ObjCObjectRegion>(R)) {        // Invalidate the region by setting its default value to @@ -1230,8 +1244,8 @@ SVal RegionStoreManager::RetrieveObjCIvar(const GRState* state,    const MemRegion *superR = R->getSuperRegion(); -  // Check if the super region has a binding. -  if (Optional<SVal> V = getDirectBinding(B, superR)) { +  // Check if the super region has a default binding. +  if (Optional<SVal> V = getDefaultBinding(B, superR)) {      if (SymbolRef parentSym = V->getAsSymbol())        return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R); @@ -1376,7 +1390,7 @@ const GRState *RegionStoreManager::Bind(const GRState *state, Loc L, SVal V) {          // For now, just invalidate the fields of the struct/union/class.          // FIXME: Precisely handle the fields of the record.          if (superTy->isRecordType()) -          return InvalidateRegion(state, superR, NULL, 0); +          return InvalidateRegion(state, superR, NULL, 0, NULL);        }      }    } @@ -1588,36 +1602,13 @@ RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,  //===----------------------------------------------------------------------===//  // State pruning.  //===----------------------------------------------------------------------===// - -namespace { -class VISIBILITY_HIDDEN RBDNode -  : public std::pair<const GRState*, const MemRegion *> { -public: -  RBDNode(const GRState *st, const MemRegion *r) -    : std::pair<const GRState*, const MemRegion*>(st, r) {} -   -  const GRState *getState() const { return first; } -  const MemRegion *getRegion() const { return second; } -}; - -enum VisitFlag { NotVisited = 0, VisitedFromSubRegion, VisitedFromSuperRegion }; - -class RBDItem : public RBDNode { -private: -  const VisitFlag VF; -   -public: -  RBDItem(const GRState *st, const MemRegion *r, VisitFlag vf) -    : RBDNode(st, r), VF(vf) {} - -  VisitFlag getVisitFlag() const { return VF; } -}; -} // end anonymous namespace  void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,                                              SymbolReaper& SymReaper,                             llvm::SmallVectorImpl<const MemRegion*>& RegionRoots)  { +  typedef std::pair<const GRState*, const MemRegion *> RBDNode; +    Store store = state.getStore();    RegionBindings B = GetRegionBindings(store); @@ -1638,27 +1629,26 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,    // Process the "intermediate" roots to find if they are referenced by    // real roots. -  llvm::SmallVector<RBDItem, 10> WorkList; -  llvm::DenseMap<const MemRegion*,unsigned> IntermediateVisited; +  llvm::SmallVector<RBDNode, 10> WorkList; +  llvm::DenseSet<const MemRegion*> IntermediateVisited;    while (!IntermediateRoots.empty()) {      const MemRegion* R = IntermediateRoots.back();      IntermediateRoots.pop_back(); -    unsigned &visited = IntermediateVisited[R]; -    if (visited) +    if (IntermediateVisited.count(R))        continue; -    visited = 1; +    IntermediateVisited.insert(R);      if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {        if (SymReaper.isLive(Loc, VR->getDecl())) -        WorkList.push_back(RBDItem(&state, VR, VisitedFromSuperRegion)); +        WorkList.push_back(std::make_pair(&state, VR));        continue;      }      if (const SymbolicRegion* SR = dyn_cast<SymbolicRegion>(R)) {        if (SymReaper.isLive(SR->getSymbol())) -        WorkList.push_back(RBDItem(&state, SR, VisitedFromSuperRegion)); +        WorkList.push_back(std::make_pair(&state, SR));        continue;      } @@ -1671,54 +1661,40 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,    // Enqueue the RegionRoots onto WorkList.    for (llvm::SmallVectorImpl<const MemRegion*>::iterator I=RegionRoots.begin(),         E=RegionRoots.end(); I!=E; ++I) { -    WorkList.push_back(RBDItem(&state, *I, VisitedFromSuperRegion)); +    WorkList.push_back(std::make_pair(&state, *I));    }    RegionRoots.clear(); -  // Process the worklist. -  typedef llvm::DenseMap<std::pair<const GRState*, const MemRegion*>, VisitFlag> -          VisitMap; -     -  VisitMap Visited; +  llvm::DenseSet<RBDNode> Visited;    while (!WorkList.empty()) { -    RBDItem N = WorkList.back(); +    RBDNode N = WorkList.back();      WorkList.pop_back();      // Have we visited this node before? -    VisitFlag &VF = Visited[N]; -    if (VF >= N.getVisitFlag()) +    if (Visited.count(N))        continue; +    Visited.insert(N); + +    const MemRegion *R = N.second; +    const GRState *state_N = N.first; -    const MemRegion *R = N.getRegion(); -    const GRState *state_N = N.getState(); -     -    // Enqueue subregions? -    if (N.getVisitFlag() == VisitedFromSuperRegion) { -      RegionStoreSubRegionMap *M; -       -      if (&state == state_N) -        M = SubRegions.get(); -      else { -        RegionStoreSubRegionMap *& SM = SC[state_N]; -        if (!SM) -          SM = getRegionStoreSubRegionMap(state_N->getStore()); -        M = SM; -      } +    // Enqueue subregions. +    RegionStoreSubRegionMap *M; -      RegionStoreSubRegionMap::iterator I, E; -      for (llvm::tie(I, E) = M->begin_end(R); I != E; ++I) -        WorkList.push_back(RBDItem(state_N, *I, VisitedFromSuperRegion)); -    } - -    // At this point, if we have already visited this region before, we are -    // done.  -    if (VF != NotVisited) { -      VF = N.getVisitFlag(); -      continue; +    if (&state == state_N) +      M = SubRegions.get(); +    else { +      RegionStoreSubRegionMap *& SM = SC[state_N]; +      if (!SM) +        SM = getRegionStoreSubRegionMap(state_N->getStore()); +      M = SM;      } -    VF = N.getVisitFlag(); +    RegionStoreSubRegionMap::iterator I, E; +    for (llvm::tie(I, E) = M->begin_end(R); I != E; ++I) +      WorkList.push_back(std::make_pair(state_N, *I)); +      // Enqueue the super region.      if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {        const MemRegion *superR = SR->getSuperRegion(); @@ -1726,12 +1702,9 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,          // If 'R' is a field or an element, we want to keep the bindings          // for the other fields and elements around.  The reason is that          // pointer arithmetic can get us to the other fields or elements. -        // FIXME: add an assertion that this is always true. -        VisitFlag NewVisit = -          isa<FieldRegion>(R) || isa<ElementRegion>(R) || isa<ObjCIvarRegion>(R) -          ? VisitedFromSuperRegion : VisitedFromSubRegion; -         -        WorkList.push_back(RBDItem(state_N, superR, NewVisit)); +        assert(isa<FieldRegion>(R) || isa<ElementRegion>(R)  +               || isa<ObjCIvarRegion>(R)); +        WorkList.push_back(std::make_pair(state_N, superR));        }      } @@ -1752,8 +1725,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,              dyn_cast<nonloc::LazyCompoundVal>(V.getPointer())) {          const LazyCompoundValData *D = LCV->getCVData(); -        WorkList.push_back(RBDItem(D->getState(), D->getRegion(), -                                   VisitedFromSuperRegion)); +        WorkList.push_back(std::make_pair(D->getState(), D->getRegion()));        }        else {          // Update the set of live symbols. @@ -1763,7 +1735,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,          // If V is a region, then add it to the worklist.          if (const MemRegion *RX = V->getAsRegion()) -          WorkList.push_back(RBDItem(state_N, RX, VisitedFromSuperRegion)); +          WorkList.push_back(std::make_pair(state_N, RX));        }      }    } @@ -1774,7 +1746,7 @@ void RegionStoreManager::RemoveDeadBindings(GRState &state, Stmt* Loc,    for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I) {      const MemRegion* R = I.getKey();      // If this region live?  Is so, none of its symbols are dead. -    if (Visited.find(std::make_pair(&state, R)) != Visited.end()) +    if (Visited.count(std::make_pair(&state, R)))        continue;      // Remove this dead region from the store. @@ -1820,7 +1792,7 @@ GRState const *RegionStoreManager::EnterStackFrame(GRState const *state,  void RegionStoreManager::print(Store store, llvm::raw_ostream& OS,                                 const char* nl, const char *sep) {    RegionBindings B = GetRegionBindings(store); -  OS << "Store (direct bindings):" << nl; +  OS << "Store (direct and default bindings):" << nl;    for (RegionBindings::iterator I = B.begin(), E = B.end(); I != E; ++I)      OS << ' ' << I.getKey() << " : " << I.getData() << nl; diff --git a/lib/Analysis/SimpleSValuator.cpp b/lib/Analysis/SimpleSValuator.cpp index 636ce15c3326..4487aa9d3028 100644 --- a/lib/Analysis/SimpleSValuator.cpp +++ b/lib/Analysis/SimpleSValuator.cpp @@ -346,16 +346,29 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state,        nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);        SymbolRef Sym = slhs->getSymbol(); -      // Does the symbol simplify to a constant? +      // Does the symbol simplify to a constant?  If so, "fold" the constant +      // by setting 'lhs' to a ConcreteInt and try again.        if (Sym->getType(ValMgr.getContext())->isIntegerType())          if (const llvm::APSInt *Constant = state->getSymVal(Sym)) { -          // What should we convert it to? -          if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){ -            BasicValueFactory &BVF = ValMgr.getBasicValueFactory(); -            lhs = nonloc::ConcreteInt(BVF.Convert(rhs_I->getValue(), -                                                  *Constant)); +          // The symbol evaluates to a constant. If necessary, promote the +          // folded constant (LHS) to the result type. +          BasicValueFactory &BVF = ValMgr.getBasicValueFactory(); +          const llvm::APSInt &lhs_I = BVF.Convert(resultTy, *Constant); +          lhs = nonloc::ConcreteInt(lhs_I); +           +          // Also promote the RHS (if necessary). + +          // For shifts, it necessary promote the RHS to the result type. +          if (BinaryOperator::isShiftOp(op))              continue; +           +          // Other operators: do an implicit conversion.  This shouldn't be +          // necessary once we support truncation/extension of symbolic values. +          if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){ +            rhs = nonloc::ConcreteInt(BVF.Convert(resultTy, rhs_I->getValue()));            } +           +          continue;          }        if (isa<nonloc::ConcreteInt>(rhs)) { diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index 4a29997a2ccc..fbc731311653 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -25,6 +25,7 @@  #include "clang/Basic/SourceLocation.h"  #include "llvm/ADT/SmallVector.h"  #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/raw_ostream.h"  #include <vector>  #include <map>  #include <cstring> @@ -82,9 +83,14 @@ static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {  #ifndef NDEBUG    static bool IsFirst = true;    if (IsFirst) { -    for (unsigned i = 1; i != NumDiagEntries; ++i) +    for (unsigned i = 1; i != NumDiagEntries; ++i) { +      assert(StaticDiagInfo[i-1].DiagID != StaticDiagInfo[i].DiagID && +             "Diag ID conflict, the enums at the start of clang::diag (in " +             "Diagnostic.h) probably need to be increased"); +        assert(StaticDiagInfo[i-1] < StaticDiagInfo[i] &&               "Improperly sorted diag info"); +    }      IsFirst = false;    }  #endif @@ -184,6 +190,8 @@ namespace clang {  static void DummyArgToStringFn(Diagnostic::ArgumentKind AK, intptr_t QT,                                 const char *Modifier, unsigned ML,                                 const char *Argument, unsigned ArgLen, +                               const Diagnostic::ArgumentValue *PrevArgs, +                               unsigned NumPrevArgs,                                 llvm::SmallVectorImpl<char> &Output,                                 void *Cookie) {    const char *Str = "<can't format argument>"; @@ -222,6 +230,8 @@ Diagnostic::~Diagnostic() {  void Diagnostic::pushMappings() { +  // Avoids undefined behavior when the stack has to resize. +  DiagMappingsStack.reserve(DiagMappingsStack.size() + 1);    DiagMappingsStack.push_back(DiagMappingsStack.back());  } @@ -679,6 +689,12 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {    const char *DiagStr = getDiags()->getDescription(getID());    const char *DiagEnd = DiagStr+strlen(DiagStr); +  /// FormattedArgs - Keep track of all of the arguments formatted by +  /// ConvertArgToString and pass them into subsequent calls to +  /// ConvertArgToString, allowing the implementation to avoid redundancies in +  /// obvious cases. +  llvm::SmallVector<Diagnostic::ArgumentValue, 8> FormattedArgs; +      while (DiagStr != DiagEnd) {      if (DiagStr[0] != '%') {        // Append non-%0 substrings to Str if we have one. @@ -726,7 +742,9 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {      assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");      unsigned ArgNo = *DiagStr++ - '0'; -    switch (getArgKind(ArgNo)) { +    Diagnostic::ArgumentKind Kind = getArgKind(ArgNo); +     +    switch (Kind) {      // ---- STRINGS ----      case Diagnostic::ak_std_string: {        const std::string &S = getArgStdStr(ArgNo); @@ -757,9 +775,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {          HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);        } else {          assert(ModifierLen == 0 && "Unknown integer modifier"); -        // FIXME: Optimize -        std::string S = llvm::itostr(Val); -        OutStr.append(S.begin(), S.end()); +        llvm::raw_svector_ostream(OutStr) << Val;        }        break;      } @@ -774,10 +790,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {          HandlePluralModifier((unsigned)Val, Argument, ArgumentLen, OutStr);        } else {          assert(ModifierLen == 0 && "Unknown integer modifier"); - -        // FIXME: Optimize -        std::string S = llvm::utostr_32(Val); -        OutStr.append(S.begin(), S.end()); +        llvm::raw_svector_ostream(OutStr) << Val;        }        break;      } @@ -793,9 +806,7 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {          continue;        } -      OutStr.push_back('\''); -      OutStr.append(II->getName(), II->getName() + II->getLength()); -      OutStr.push_back('\''); +      llvm::raw_svector_ostream(OutStr) << '\'' << II->getName() << '\'';        break;      }      case Diagnostic::ak_qualtype: @@ -803,11 +814,23 @@ FormatDiagnostic(llvm::SmallVectorImpl<char> &OutStr) const {      case Diagnostic::ak_nameddecl:      case Diagnostic::ak_nestednamespec:      case Diagnostic::ak_declcontext: -      getDiags()->ConvertArgToString(getArgKind(ArgNo), getRawArg(ArgNo), +      getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),                                       Modifier, ModifierLen, -                                     Argument, ArgumentLen, OutStr); +                                     Argument, ArgumentLen, +                                     FormattedArgs.data(), FormattedArgs.size(), +                                     OutStr);        break;      } +     +    // Remember this argument info for subsequent formatting operations.  Turn +    // std::strings into a null terminated string to make it be the same case as +    // all the other ones. +    if (Kind != Diagnostic::ak_std_string) +      FormattedArgs.push_back(std::make_pair(Kind, getRawArg(ArgNo))); +    else +      FormattedArgs.push_back(std::make_pair(Diagnostic::ak_c_string, +                                        (intptr_t)getArgStdStr(ArgNo).c_str())); +        }  } diff --git a/lib/Basic/FileManager.cpp b/lib/Basic/FileManager.cpp index df86f9d04702..ee4309de937b 100644 --- a/lib/Basic/FileManager.cpp +++ b/lib/Basic/FileManager.cpp @@ -149,6 +149,41 @@ FileManager::~FileManager() {    delete &UniqueFiles;  } +void FileManager::addStatCache(StatSysCallCache *statCache, bool AtBeginning) { +  assert(statCache && "No stat cache provided?"); +  if (AtBeginning || StatCache.get() == 0) { +    statCache->setNextStatCache(StatCache.take()); +    StatCache.reset(statCache); +    return; +  } +   +  StatSysCallCache *LastCache = StatCache.get(); +  while (LastCache->getNextStatCache()) +    LastCache = LastCache->getNextStatCache(); +   +  LastCache->setNextStatCache(statCache); +} + +void FileManager::removeStatCache(StatSysCallCache *statCache) { +  if (!statCache) +    return; +   +  if (StatCache.get() == statCache) { +    // This is the first stat cache. +    StatCache.reset(StatCache->takeNextStatCache()); +    return; +  } +   +  // Find the stat cache in the list. +  StatSysCallCache *PrevCache = StatCache.get(); +  while (PrevCache && PrevCache->getNextStatCache() != statCache) +    PrevCache = PrevCache->getNextStatCache(); +  if (PrevCache) +    PrevCache->setNextStatCache(statCache->getNextStatCache()); +  else +    assert(false && "Stat cache not found for removal"); +} +  /// getDirectory - Lookup, cache, and verify the specified directory.  This  /// returns null if the directory doesn't exist.  /// @@ -290,8 +325,8 @@ void FileManager::PrintStats() const {  }  int MemorizeStatCalls::stat(const char *path, struct stat *buf) { -  int result = ::stat(path, buf); - +  int result = StatSysCallCache::stat(path, buf); +      if (result != 0) {      // Cache failed 'stat' results.      struct stat empty; diff --git a/lib/Basic/IdentifierTable.cpp b/lib/Basic/IdentifierTable.cpp index 93c260fdbe17..16aa0c54846a 100644 --- a/lib/Basic/IdentifierTable.cpp +++ b/lib/Basic/IdentifierTable.cpp @@ -16,6 +16,7 @@  #include "clang/Basic/LangOptions.h"  #include "llvm/ADT/FoldingSet.h"  #include "llvm/ADT/DenseMap.h" +#include "llvm/Support/raw_ostream.h"  #include <cstdio>  using namespace clang; @@ -153,7 +154,7 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {    unsigned Len = getLength();    if (Len < 2) return tok::pp_not_keyword; -  const char *Name = getName(); +  const char *Name = getNameStart();    switch (HASH(Len, Name[0], Name[2])) {    default: return tok::pp_not_keyword;    CASE( 2, 'i', '\0', if); @@ -301,24 +302,15 @@ IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {  }  std::string MultiKeywordSelector::getName() const { -  std::string Result; -  unsigned Length = 0; +  llvm::SmallString<256> Str; +  llvm::raw_svector_ostream OS(Str);    for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {      if (*I) -      Length += (*I)->getLength(); -    ++Length;  // : +      OS << (*I)->getName(); +    OS << ':';    } -  Result.reserve(Length); - -  for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) { -    if (*I) -      Result.insert(Result.end(), (*I)->getName(), -                    (*I)->getName()+(*I)->getLength()); -    Result.push_back(':'); -  } - -  return Result; +  return OS.str();  }  std::string Selector::getAsString() const { @@ -332,9 +324,10 @@ std::string Selector::getAsString() const {      if (getNumArgs() == 0)        return II->getName(); -    std::string Res = II ? II->getName() : ""; -    Res += ":"; -    return Res; +    if (!II) +      return ":"; + +    return II->getName().str() + ":";    }    // We have a multiple keyword selector (no embedded flags). diff --git a/lib/Basic/TargetInfo.cpp b/lib/Basic/TargetInfo.cpp index 9cd12493e7a4..8f3c777c2004 100644 --- a/lib/Basic/TargetInfo.cpp +++ b/lib/Basic/TargetInfo.cpp @@ -43,6 +43,7 @@ TargetInfo::TargetInfo(const std::string &T) : Triple(T) {    UIntMaxType = UnsignedLongLong;    IntPtrType = SignedLong;    WCharType = SignedInt; +  WIntType = SignedInt;    Char16Type = UnsignedShort;    Char32Type = UnsignedInt;    Int64Type = SignedLongLong; @@ -73,6 +74,57 @@ const char *TargetInfo::getTypeName(IntType T) {    }  } +/// getTypeConstantSuffix - Return the constant suffix for the specified +/// integer type enum. For example, SignedLong -> "L". +const char *TargetInfo::getTypeConstantSuffix(IntType T) { +  switch (T) { +  default: assert(0 && "not an integer!"); +  case SignedShort: +  case SignedInt:        return ""; +  case SignedLong:       return "L"; +  case SignedLongLong:   return "LL"; +  case UnsignedShort: +  case UnsignedInt:      return "U"; +  case UnsignedLong:     return "UL"; +  case UnsignedLongLong: return "ULL"; +  } +} + +/// getTypeWidth - Return the width (in bits) of the specified integer type  +/// enum. For example, SignedInt -> getIntWidth(). +unsigned TargetInfo::getTypeWidth(IntType T) const { +  switch (T) { +  default: assert(0 && "not an integer!"); +  case SignedShort:      return getShortWidth(); +  case UnsignedShort:    return getShortWidth(); +  case SignedInt:        return getIntWidth(); +  case UnsignedInt:      return getIntWidth(); +  case SignedLong:       return getLongWidth(); +  case UnsignedLong:     return getLongWidth(); +  case SignedLongLong:   return getLongLongWidth(); +  case UnsignedLongLong: return getLongLongWidth(); +  }; +} + +/// getTypeSigned - Return whether an integer types is signed. Returns true if +/// the type is signed; false otherwise. +bool TargetInfo::getTypeSigned(IntType T) const { +  switch (T) { +  default: assert(0 && "not an integer!"); +  case SignedShort: +  case SignedInt: +  case SignedLong: +  case SignedLongLong:    +    return true; +  case UnsignedShort: +  case UnsignedInt: +  case UnsignedLong: +  case UnsignedLongLong:  +    return false; +  }; +} + +  //===----------------------------------------------------------------------===// diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp index 1d4d1235c963..66d6824b6f29 100644 --- a/lib/Basic/Targets.cpp +++ b/lib/Basic/Targets.cpp @@ -320,6 +320,27 @@ public:      : OSTargetInfo<Target>(triple) {}  }; +// AuroraUX target +template<typename Target> +class AuroraUXTargetInfo : public OSTargetInfo<Target> { +protected: +  virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple, +                                std::vector<char> &Defs) const { +    DefineStd(Defs, "sun", Opts); +    DefineStd(Defs, "unix", Opts); +    Define(Defs, "__ELF__"); +    Define(Defs, "__svr4__"); +    Define(Defs, "__SVR4"); +  } +public: +  AuroraUXTargetInfo(const std::string& triple) +    : OSTargetInfo<Target>(triple) { +    this->UserLabelPrefix = ""; +    this->WCharType = this->SignedLong; +    // FIXME: WIntType should be SignedLong +  } +}; +  // Solaris target  template<typename Target>  class SolarisTargetInfo : public OSTargetInfo<Target> { @@ -1456,6 +1477,14 @@ void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,  } // end anonymous namespace.  namespace { +class AuroraUXSparcV8TargetInfo : public AuroraUXTargetInfo<SparcV8TargetInfo> { +public: +  AuroraUXSparcV8TargetInfo(const std::string& triple) : +      AuroraUXTargetInfo<SparcV8TargetInfo>(triple) { +    SizeType = UnsignedInt; +    PtrDiffType = SignedInt; +  } +};  class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> {  public:    SolarisSparcV8TargetInfo(const std::string& triple) : @@ -1573,8 +1602,8 @@ namespace {      }      virtual bool validateAsmConstraint(const char *&Name,                                         TargetInfo::ConstraintInfo &info) const { -      // FIXME: implement -      return true; +      // No target constraints for now. +      return false;      }      virtual const char *getClobbers() const {        // FIXME: Is this really right? @@ -1846,6 +1875,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {      return new PPC64TargetInfo(T);    case llvm::Triple::sparc: +    if (os == llvm::Triple::AuroraUX) +      return new AuroraUXSparcV8TargetInfo(T);      if (os == llvm::Triple::Solaris)        return new SolarisSparcV8TargetInfo(T);      return new SparcV8TargetInfo(T); @@ -1858,6 +1889,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {    case llvm::Triple::x86:      switch (os) { +    case llvm::Triple::AuroraUX: +      return new AuroraUXTargetInfo<X86_32TargetInfo>(T);      case llvm::Triple::Darwin:        return new DarwinI386TargetInfo(T);      case llvm::Triple::Linux: @@ -1884,6 +1917,8 @@ TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) {    case llvm::Triple::x86_64:      switch (os) { +    case llvm::Triple::AuroraUX: +      return new AuroraUXTargetInfo<X86_64TargetInfo>(T);      case llvm::Triple::Darwin:        return new DarwinX86_64TargetInfo(T);      case llvm::Triple::Linux: diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp index 736425e01276..682cf5da1e72 100644 --- a/lib/CodeGen/CGBlocks.cpp +++ b/lib/CodeGen/CGBlocks.cpp @@ -73,29 +73,60 @@ llvm::Constant *BlockModule::getNSConcreteStackBlock() {    return NSConcreteStackBlock;  } -static void CollectBlockDeclRefInfo(const Stmt *S, -                                    CodeGenFunction::BlockInfo &Info) { +static void CollectBlockDeclRefInfo( +  const Stmt *S, CodeGenFunction::BlockInfo &Info, +  llvm::SmallSet<const DeclContext *, 16> &InnerContexts) {    for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end();         I != E; ++I)      if (*I) -      CollectBlockDeclRefInfo(*I, Info); +      CollectBlockDeclRefInfo(*I, Info, InnerContexts); -  if (const BlockDeclRefExpr *DE = dyn_cast<BlockDeclRefExpr>(S)) { +  // We want to ensure we walk down into block literals so we can find +  // all nested BlockDeclRefExprs. +  if (const BlockExpr *BE = dyn_cast<BlockExpr>(S)) { +    InnerContexts.insert(cast<DeclContext>(BE->getBlockDecl())); +    CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts); +  } + +  if (const BlockDeclRefExpr *BDRE = dyn_cast<BlockDeclRefExpr>(S)) {      // FIXME: Handle enums. -    if (isa<FunctionDecl>(DE->getDecl())) +    if (isa<FunctionDecl>(BDRE->getDecl()))        return; -    if (DE->isByRef()) -      Info.ByRefDeclRefs.push_back(DE); -    else -      Info.ByCopyDeclRefs.push_back(DE); +    // Only Decls that escape are added. +    if (!InnerContexts.count(BDRE->getDecl()->getDeclContext())) +      Info.DeclRefs.push_back(BDRE);    }  }  /// CanBlockBeGlobal - Given a BlockInfo struct, determines if a block can be  /// declared as a global variable instead of on the stack.  static bool CanBlockBeGlobal(const CodeGenFunction::BlockInfo &Info) { -  return Info.ByRefDeclRefs.empty() && Info.ByCopyDeclRefs.empty(); +  return Info.DeclRefs.empty(); +} + +/// AllocateAllBlockDeclRefs - Preallocate all nested BlockDeclRefExprs to +/// ensure we can generate the debug information for the parameter for the block +/// invoke function. +static void AllocateAllBlockDeclRefs(const CodeGenFunction::BlockInfo &Info, +                                     CodeGenFunction *CGF) { +  // Always allocate self, as it is often handy in the debugger, even if there +  // is no codegen in the block that uses it.  This is also useful to always do +  // this as if we didn't, we'd have to figure out all code that uses a self +  // pointer, including implicit uses. +  if (const ObjCMethodDecl *OMD +      = dyn_cast_or_null<ObjCMethodDecl>(CGF->CurFuncDecl)) { +    ImplicitParamDecl *SelfDecl = OMD->getSelfDecl(); +    BlockDeclRefExpr *BDRE = new (CGF->getContext()) +      BlockDeclRefExpr(SelfDecl, +                       SelfDecl->getType(), SourceLocation(), false); +    CGF->AllocateBlockDecl(BDRE); +  } + +  // FIXME: Also always forward the this pointer in C++ as well. + +  for (size_t i = 0; i < Info.DeclRefs.size(); ++i) +    CGF->AllocateBlockDecl(Info.DeclRefs[i]);  }  // FIXME: Push most into CGM, passing down a few bits, like current function @@ -104,7 +135,9 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {    std::string Name = CurFn->getName();    CodeGenFunction::BlockInfo Info(0, Name.c_str()); -  CollectBlockDeclRefInfo(BE->getBody(), Info); +  llvm::SmallSet<const DeclContext *, 16> InnerContexts; +  InnerContexts.insert(BE->getBlockDecl()); +  CollectBlockDeclRefInfo(BE->getBody(), Info, InnerContexts);    // Check if the block can be global.    // FIXME: This test doesn't work for nested blocks yet.  Longer term, I'd like @@ -159,7 +192,8 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {      if (subBlockDeclRefDecls.size() == 0) {        // __descriptor -      Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize, 0, 0); +      Elts[4] = BuildDescriptorBlockDecl(subBlockHasCopyDispose, subBlockSize, +                                         0, 0);        // Optimize to being a global block.        Elts[0] = CGM.getNSConcreteGlobalBlock(); @@ -269,7 +303,7 @@ llvm::Value *CodeGenFunction::BuildBlockLiteralTmp(const BlockExpr *BE) {              llvm::Value *BlockLiteral = LoadBlockStruct();              Loc = Builder.CreateGEP(BlockLiteral, -                                    llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), +                       llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),                                                             offset),                                      "block.literal");              Ty = llvm::PointerType::get(Ty, 0); @@ -391,10 +425,6 @@ const llvm::Type *BlockModule::getGenericExtendedBlockLiteralType() {    return GenericExtendedBlockLiteralType;  } -bool BlockFunction::BlockRequiresCopying(QualType Ty) { -  return CGM.BlockRequiresCopying(Ty); -} -  RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {    const BlockPointerType *BPT =      E->getCallee()->getType()->getAs<BlockPointerType>(); @@ -447,24 +477,34 @@ RValue CodeGenFunction::EmitBlockCallExpr(const CallExpr* E) {    return EmitCall(FnInfo, Func, Args);  } -llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { +uint64_t CodeGenFunction::AllocateBlockDecl(const BlockDeclRefExpr *E) {    const ValueDecl *VD = E->getDecl(); -      uint64_t &offset = BlockDecls[VD]; -    // See if we have already allocated an offset for this variable. -  if (offset == 0) { -    // Don't run the expensive check, unless we have to. -    if (!BlockHasCopyDispose && BlockRequiresCopying(E->getType())) +  if (offset) +    return offset; + +  // Don't run the expensive check, unless we have to. +  if (!BlockHasCopyDispose) +    if (E->isByRef() +        || BlockRequiresCopying(E->getType()))        BlockHasCopyDispose = true; -    // if not, allocate one now. -    offset = getBlockOffset(E); -  } + +  // if not, allocate one now. +  offset = getBlockOffset(E); + +  return offset; +} + +llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const BlockDeclRefExpr *E) { +  const ValueDecl *VD = E->getDecl(); +  uint64_t offset = AllocateBlockDecl(E); +      llvm::Value *BlockLiteral = LoadBlockStruct();    llvm::Value *V = Builder.CreateGEP(BlockLiteral, -                                  llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext), +                       llvm::ConstantInt::get(llvm::Type::getInt64Ty(VMContext),                                                           offset),                                       "block.literal");    if (E->isByRef()) { @@ -576,7 +616,10 @@ BlockModule::GetAddrOfGlobalBlock(const BlockExpr *BE, const char * n) {  }  llvm::Value *CodeGenFunction::LoadBlockStruct() { -  return Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], "self"); +  llvm::Value *V = Builder.CreateLoad(LocalDeclMap[getBlockStructDecl()], +                                      "self"); +  // For now, we codegen based upon byte offsets. +  return Builder.CreateBitCast(V, PtrToInt8Ty);  }  llvm::Function * @@ -605,14 +648,8 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,        LocalDeclMap[VD] = i->second;    } -  // FIXME: We need to rearrange the code for copy/dispose so we have this -  // sooner, so we can calculate offsets correctly. -  if (!BlockHasCopyDispose) -    BlockOffset = CGM.getTargetData() -      .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8; -  else -    BlockOffset = CGM.getTargetData() -      .getTypeStoreSizeInBits(CGM.getGenericExtendedBlockLiteralType()) / 8; +  BlockOffset = CGM.getTargetData() +    .getTypeStoreSizeInBits(CGM.getGenericBlockLiteralType()) / 8;    BlockAlign = getContext().getTypeAlign(getContext().VoidPtrTy) / 8;    const FunctionType *BlockFunctionType = BExpr->getFunctionType(); @@ -630,13 +667,22 @@ CodeGenFunction::GenerateBlockFunction(const BlockExpr *BExpr,    FunctionArgList Args; +  CurFuncDecl = OuterFuncDecl; +    const BlockDecl *BD = BExpr->getBlockDecl(); +  IdentifierInfo *II = &CGM.getContext().Idents.get(".block_descriptor"); + +  // Allocate all BlockDeclRefDecls, so we can calculate the right ParmTy below. +  AllocateAllBlockDeclRefs(Info, this); + +  QualType ParmTy = getContext().getBlockParmType(BlockHasCopyDispose, +                                                  BlockDeclRefDecls);    // FIXME: This leaks    ImplicitParamDecl *SelfDecl =      ImplicitParamDecl::Create(getContext(), 0, -                              SourceLocation(), 0, -                              getContext().getPointerType(getContext().VoidTy)); +                              SourceLocation(), II, +                              ParmTy);    Args.push_back(std::make_pair(SelfDecl, SelfDecl->getType()));    BlockStructDecl = SelfDecl; @@ -758,11 +804,13 @@ GenerateCopyHelperFunction(bool BlockHasCopyDispose, const llvm::StructType *T,    FunctionArgList Args;    // FIXME: This leaks    ImplicitParamDecl *Dst = -    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, +    ImplicitParamDecl::Create(getContext(), 0, +                              SourceLocation(), 0,                                getContext().getPointerType(getContext().VoidTy));    Args.push_back(std::make_pair(Dst, Dst->getType()));    ImplicitParamDecl *Src = -    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, +    ImplicitParamDecl::Create(getContext(), 0, +                              SourceLocation(), 0,                                getContext().getPointerType(getContext().VoidTy));    Args.push_back(std::make_pair(Src, Src->getType())); @@ -843,7 +891,8 @@ GenerateDestroyHelperFunction(bool BlockHasCopyDispose,    FunctionArgList Args;    // FIXME: This leaks    ImplicitParamDecl *Src = -    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, +    ImplicitParamDecl::Create(getContext(), 0, +                              SourceLocation(), 0,                                getContext().getPointerType(getContext().VoidTy));    Args.push_back(std::make_pair(Src, Src->getType())); @@ -922,13 +971,15 @@ GeneratebyrefCopyHelperFunction(const llvm::Type *T, int flag) {    FunctionArgList Args;    // FIXME: This leaks    ImplicitParamDecl *Dst = -    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, +    ImplicitParamDecl::Create(getContext(), 0, +                              SourceLocation(), 0,                                getContext().getPointerType(getContext().VoidTy));    Args.push_back(std::make_pair(Dst, Dst->getType()));    // FIXME: This leaks    ImplicitParamDecl *Src = -    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, +    ImplicitParamDecl::Create(getContext(), 0, +                              SourceLocation(), 0,                                getContext().getPointerType(getContext().VoidTy));    Args.push_back(std::make_pair(Src, Src->getType())); @@ -991,7 +1042,8 @@ BlockFunction::GeneratebyrefDestroyHelperFunction(const llvm::Type *T,    FunctionArgList Args;    // FIXME: This leaks    ImplicitParamDecl *Src = -    ImplicitParamDecl::Create(getContext(), 0, SourceLocation(), 0, +    ImplicitParamDecl::Create(getContext(), 0, +                              SourceLocation(), 0,                                getContext().getPointerType(getContext().VoidTy));    Args.push_back(std::make_pair(Src, Src->getType())); diff --git a/lib/CodeGen/CGBlocks.h b/lib/CodeGen/CGBlocks.h index 3a860c0d3c36..3ab4efb71bee 100644 --- a/lib/CodeGen/CGBlocks.h +++ b/lib/CodeGen/CGBlocks.h @@ -115,15 +115,8 @@ public:      PtrToInt8Ty = llvm::Type::getInt8PtrTy(M.getContext());    } -  bool BlockRequiresCopying(QualType Ty) { -    if (Ty->isBlockPointerType()) -      return true; -    if (getContext().isObjCNSObjectType(Ty)) -      return true; -    if (Ty->isObjCObjectPointerType()) -      return true; -    return false; -  } +  bool BlockRequiresCopying(QualType Ty) +    { return getContext().BlockRequiresCopying(Ty); }  };  class BlockFunction : public BlockBase { @@ -165,11 +158,7 @@ public:      /// ByCopyDeclRefs - Variables from parent scopes that have been imported      /// into this block. -    llvm::SmallVector<const BlockDeclRefExpr *, 8> ByCopyDeclRefs; - -    // ByRefDeclRefs - __block variables from parent scopes that have been -    // imported into this block. -    llvm::SmallVector<const BlockDeclRefExpr *, 8> ByRefDeclRefs; +    llvm::SmallVector<const BlockDeclRefExpr *, 8> DeclRefs;      BlockInfo(const llvm::Type *blt, const char *n)        : BlockLiteralTy(blt), Name(n) { @@ -228,7 +217,8 @@ public:    llvm::Value *getBlockObjectDispose();    void BuildBlockRelease(llvm::Value *DeclPtr, int flag = BLOCK_FIELD_IS_BYREF); -  bool BlockRequiresCopying(QualType Ty); +  bool BlockRequiresCopying(QualType Ty) +    { return getContext().BlockRequiresCopying(Ty); }  };  }  // end namespace CodeGen diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 3960cf51868f..cfa669dc4b6e 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/lib/CodeGen/CGCXX.cpp @@ -590,12 +590,15 @@ void  CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,                                        const CXXConstructExpr *E) {    assert(Dest && "Must have a destination!"); - -  const CXXRecordDecl *RD = -  cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); -  if (RD->hasTrivialConstructor()) +  const CXXConstructorDecl *CD = E->getConstructor(); +  // For a copy constructor, even if it is trivial, must fall thru so +  // its argument is code-gen'ed. +  if (!CD->isCopyConstructor(getContext())) { +    const CXXRecordDecl *RD = +      cast<CXXRecordDecl>(E->getType()->getAs<RecordType>()->getDecl()); +    if (RD->hasTrivialConstructor())      return; - +  }    // Code gen optimization to eliminate copy constructor and return    // its first argument instead.    if (getContext().getLangOptions().ElideConstructors && E->isElidable()) { @@ -604,7 +607,7 @@ CodeGenFunction::EmitCXXConstructExpr(llvm::Value *Dest,      return;    }    // Call the constructor. -  EmitCXXConstructorCall(E->getConstructor(), Ctor_Complete, Dest, +  EmitCXXConstructorCall(CD, Ctor_Complete, Dest,                           E->arg_begin(), E->arg_end());  } diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index bad166f01ef5..78655168e857 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -639,9 +639,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,        // If this structure was expanded into multiple arguments then        // we need to create a temporary and reconstruct it from the        // arguments. -      std::string Name = Arg->getNameAsString();        llvm::Value *Temp = CreateTempAlloca(ConvertTypeForMem(Ty), -                                           (Name + ".addr").c_str()); +                                           Arg->getName() + ".addr");        // FIXME: What are the right qualifiers here?        llvm::Function::arg_iterator End =          ExpandTypeFromArgs(Ty, LValue::MakeAddr(Temp, Qualifiers()), AI); @@ -650,7 +649,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI,        // Name the arguments used in expansion and increment AI.        unsigned Index = 0;        for (; AI != End; ++AI, ++Index) -        AI->setName(Name + "." + llvm::Twine(Index)); +        AI->setName(Arg->getName() + "." + llvm::Twine(Index));        continue;      } diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 4c624205b4ca..1b01e1537b42 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -173,10 +173,14 @@ llvm::DIType CGDebugInfo::CreateType(const BuiltinType *BT,    uint64_t Align = M->getContext().getTypeAlign(BT);    uint64_t Offset = 0; -  return DebugFactory.CreateBasicType(Unit, -                                  BT->getName(M->getContext().getLangOptions()), -                                      Unit, 0, Size, Align, -                                      Offset, /*flags*/ 0, Encoding); +  llvm::DIType DbgTy =  +    DebugFactory.CreateBasicType(Unit, +                                 BT->getName(M->getContext().getLangOptions()), +                                 Unit, 0, Size, Align, +                                 Offset, /*flags*/ 0, Encoding); + +  TypeCache[QualType(BT, 0).getAsOpaquePtr()] = DbgTy.getNode(); +  return DbgTy;  }  llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty, @@ -190,9 +194,12 @@ llvm::DIType CGDebugInfo::CreateType(const ComplexType *Ty,    uint64_t Align = M->getContext().getTypeAlign(Ty);    uint64_t Offset = 0; -  return DebugFactory.CreateBasicType(Unit, "complex", -                                      Unit, 0, Size, Align, -                                      Offset, /*flags*/ 0, Encoding); +  llvm::DIType DbgTy =  +    DebugFactory.CreateBasicType(Unit, "complex", +                                 Unit, 0, Size, Align, +                                 Offset, /*flags*/ 0, Encoding); +  TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode(); +  return DbgTy;  }  /// CreateCVRType - Get the qualified type from the cache or create @@ -226,8 +233,11 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DICompileUnit U    // No need to fill in the Name, Line, Size, Alignment, Offset in case of    // CVR derived types. -  return DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(), -                                        0, 0, 0, 0, 0, FromTy); +  llvm::DIType DbgTy = +    DebugFactory.CreateDerivedType(Tag, Unit, "", llvm::DICompileUnit(), +                                   0, 0, 0, 0, 0, FromTy); +  TypeCache[Ty.getAsOpaquePtr()] = DbgTy.getNode(); +  return DbgTy;  }  llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty, @@ -238,9 +248,12 @@ llvm::DIType CGDebugInfo::CreateType(const ObjCObjectPointerType *Ty,    uint64_t Size = M->getContext().getTypeSize(Ty);    uint64_t Align = M->getContext().getTypeAlign(Ty); -  return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, -                                        "", llvm::DICompileUnit(), -                                        0, Size, Align, 0, 0, EltTy); +  llvm::DIType DbgTy = +    DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, +                                   "", llvm::DICompileUnit(), +                                   0, Size, Align, 0, 0, EltTy); +  TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode(); +  return DbgTy;  }  llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty, @@ -251,9 +264,10 @@ llvm::DIType CGDebugInfo::CreateType(const PointerType *Ty,    uint64_t Size = M->getContext().getTypeSize(Ty);    uint64_t Align = M->getContext().getTypeAlign(Ty); -  return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, -                                        "", llvm::DICompileUnit(), -                                        0, Size, Align, 0, 0, EltTy); +  return +    DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_pointer_type, Unit, +                                   "", llvm::DICompileUnit(), +                                   0, Size, Align, 0, 0, EltTy);  }  llvm::DIType CGDebugInfo::CreateType(const BlockPointerType *Ty, @@ -401,8 +415,11 @@ llvm::DIType CGDebugInfo::CreateType(const TypedefType *Ty,    PresumedLoc PLoc = SM.getPresumedLoc(DefLoc);    unsigned Line = PLoc.isInvalid() ? 0 : PLoc.getLine(); -  return DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit, -                                        TyName, DefUnit, Line, 0, 0, 0, 0, Src); +  llvm::DIType DbgTy =  +    DebugFactory.CreateDerivedType(llvm::dwarf::DW_TAG_typedef, Unit, +                                   TyName, DefUnit, Line, 0, 0, 0, 0, Src); +  TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode(); +  return DbgTy;  }  llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty, @@ -424,10 +441,13 @@ llvm::DIType CGDebugInfo::CreateType(const FunctionType *Ty,    llvm::DIArray EltTypeArray =      DebugFactory.GetOrCreateArray(EltTys.data(), EltTys.size()); -  return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, -                                          Unit, "", llvm::DICompileUnit(), -                                          0, 0, 0, 0, 0, -                                          llvm::DIType(), EltTypeArray); +  llvm::DIType DbgTy = +    DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_subroutine_type, +                                     Unit, "", llvm::DICompileUnit(), +                                     0, 0, 0, 0, 0, +                                     llvm::DIType(), EltTypeArray); +  TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode(); +  return DbgTy;  }  /// CreateType - get structure or union type. @@ -713,10 +733,14 @@ llvm::DIType CGDebugInfo::CreateType(const EnumType *Ty,      Align = M->getContext().getTypeAlign(Ty);    } -  return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type, -                                          Unit, EnumName, DefUnit, Line, -                                          Size, Align, 0, 0, -                                          llvm::DIType(), EltArray); +  llvm::DIType DbgTy =  +    DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_enumeration_type, +                                     Unit, EnumName, DefUnit, Line, +                                     Size, Align, 0, 0, +                                     llvm::DIType(), EltArray); +   +  TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode(); +  return DbgTy;  }  llvm::DIType CGDebugInfo::CreateType(const TagType *Ty, @@ -767,11 +791,15 @@ llvm::DIType CGDebugInfo::CreateType(const ArrayType *Ty,    llvm::DIArray SubscriptArray =      DebugFactory.GetOrCreateArray(Subscripts.data(), Subscripts.size()); -  return DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type, -                                          Unit, "", llvm::DICompileUnit(), -                                          0, Size, Align, 0, 0, -                                          getOrCreateType(EltTy, Unit), -                                          SubscriptArray); +  llvm::DIType DbgTy =  +    DebugFactory.CreateCompositeType(llvm::dwarf::DW_TAG_array_type, +                                     Unit, "", llvm::DICompileUnit(), +                                     0, Size, Align, 0, 0, +                                     getOrCreateType(EltTy, Unit), +                                     SubscriptArray); +   +  TypeCache[QualType(Ty, 0).getAsOpaquePtr()] = DbgTy.getNode(); +  return DbgTy;  } @@ -793,7 +821,6 @@ llvm::DIType CGDebugInfo::getOrCreateType(QualType Ty,    // Otherwise create the type.    llvm::DIType Res = CreateTypeNode(Ty, Unit); -  TypeCache.insert(std::make_pair(Ty.getAsOpaquePtr(), Res.getNode()));    return Res;  } @@ -846,8 +873,6 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,                             Unit);    case Type::ConstantArray: -  case Type::ConstantArrayWithExpr: -  case Type::ConstantArrayWithoutExpr:    case Type::VariableArray:    case Type::IncompleteArray:      return CreateType(cast<ArrayType>(Ty), Unit); @@ -863,7 +888,7 @@ llvm::DIType CGDebugInfo::CreateTypeNode(QualType Ty,  /// EmitFunctionStart - Constructs the debug code for entering a function -  /// "llvm.dbg.func.start.". -void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType, +void CGDebugInfo::EmitFunctionStart(const char *Name, QualType FnType,                                      llvm::Function *Fn,                                      CGBuilderTy &Builder) {    const char *LinkageName = Name; @@ -881,7 +906,7 @@ void CGDebugInfo::EmitFunctionStart(const char *Name, QualType ReturnType,    llvm::DISubprogram SP =      DebugFactory.CreateSubprogram(Unit, Name, Name, LinkageName, Unit, LineNo, -                                  getOrCreateType(ReturnType, Unit), +                                  getOrCreateType(FnType, Unit),                                    Fn->hasInternalLinkage(), true/*definition*/);  #ifndef ATTACH_DEBUG_INFO_TO_AN_INSN @@ -1366,7 +1391,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,    }    DebugFactory.CreateGlobalVariable(getContext(Decl, Unit),  -                                    Name, Name, "", Unit, LineNo, +                                    Name, Name, Name, Unit, LineNo,                                      getOrCreateType(T, Unit),                                      Var->hasInternalLinkage(),                                      true/*definition*/, Var); @@ -1396,7 +1421,7 @@ void CGDebugInfo::EmitGlobalVariable(llvm::GlobalVariable *Var,                                             ArrayType::Normal, 0);    } -  DebugFactory.CreateGlobalVariable(Unit, Name, Name, "", Unit, LineNo, +  DebugFactory.CreateGlobalVariable(Unit, Name, Name, Name, Unit, LineNo,                                      getOrCreateType(T, Unit),                                      Var->hasInternalLinkage(),                                      true/*definition*/, Var); diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h index 0a617b999240..2e44e09d2590 100644 --- a/lib/CodeGen/CGDebugInfo.h +++ b/lib/CodeGen/CGDebugInfo.h @@ -88,7 +88,7 @@ public:    /// EmitFunctionStart - Emit a call to llvm.dbg.function.start to indicate    /// start of a new function. -  void EmitFunctionStart(const char *Name, QualType ReturnType, +  void EmitFunctionStart(const char *Name, QualType FnType,                           llvm::Function *Fn, CGBuilderTy &Builder);    /// EmitRegionStart - Emit a call to llvm.dbg.region.start to indicate start diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 7feff83dee6b..1728c67292b7 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -37,6 +37,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) {    case Decl::Enum:      // enum X;    case Decl::EnumConstant: // enum ? { X = ? }    case Decl::CXXRecord: // struct/union/class X; [C++] +  case Decl::UsingDirective: // using X; [C++]      // None of these decls require codegen support.      return; @@ -275,8 +276,8 @@ const llvm::Type *CodeGenFunction::BuildByRefType(const ValueDecl *D) {      unsigned NumPaddingBytes = AlignedOffsetInBytes - CurrentOffsetInBytes;      if (NumPaddingBytes > 0) {        const llvm::Type *Ty = llvm::Type::getInt8Ty(VMContext); -      // FIXME: We need a sema error for alignment larger than the minimum of the -      // maximal stack alignmint and the alignment of malloc on the system. +      // FIXME: We need a sema error for alignment larger than the minimum of +      // the maximal stack alignmint and the alignment of malloc on the system.        if (NumPaddingBytes > 1)          Ty = llvm::ArrayType::get(Ty, NumPaddingBytes); diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index 01a057f67455..bb487f6e3fdf 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -28,9 +28,9 @@ using namespace CodeGen;  /// CreateTempAlloca - This creates a alloca and inserts it into the entry  /// block.  llvm::AllocaInst *CodeGenFunction::CreateTempAlloca(const llvm::Type *Ty, -                                                    const char *Name) { +                                                    const llvm::Twine &Name) {    if (!Builder.isNamePreserving()) -    Name = ""; +    return new llvm::AllocaInst(Ty, 0, "", AllocaInsertPt);    return new llvm::AllocaInst(Ty, 0, Name, AllocaInsertPt);  } @@ -78,24 +78,18 @@ RValue CodeGenFunction::EmitAnyExprToTemp(const Expr *E,  RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,                                                     QualType DestType,                                                     bool IsInitializer) { +  bool ShouldDestroyTemporaries = false; +  unsigned OldNumLiveTemporaries = 0; +      if (const CXXExprWithTemporaries *TE = dyn_cast<CXXExprWithTemporaries>(E)) { -    // If we shouldn't destroy the temporaries, just emit the -    // child expression. -    if (!TE->shouldDestroyTemporaries()) -      return EmitReferenceBindingToExpr(TE->getSubExpr(), DestType, -                                        IsInitializer); -     -    // Keep track of the current cleanup stack depth. -    unsigned OldNumLiveTemporaries = LiveTemporaries.size(); -     -    RValue RV = EmitReferenceBindingToExpr(TE->getSubExpr(), DestType, -                                           IsInitializer); -     -    // Pop temporaries. -    while (LiveTemporaries.size() > OldNumLiveTemporaries) -      PopCXXTemporary(); +    ShouldDestroyTemporaries = TE->shouldDestroyTemporaries(); + +    if (ShouldDestroyTemporaries) { +      // Keep track of the current cleanup stack depth. +      OldNumLiveTemporaries = LiveTemporaries.size(); +    } -    return RV; +    E = TE->getSubExpr();    }    RValue Val; @@ -105,6 +99,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,      if (LV.isSimple())        return RValue::get(LV.getAddress());      Val = EmitLoadOfLValue(LV, E->getType()); +     +    if (ShouldDestroyTemporaries) { +      // Pop temporaries. +      while (LiveTemporaries.size() > OldNumLiveTemporaries) +        PopCXXTemporary(); +    }          } else {      const CXXRecordDecl *BaseClassDecl = 0;      const CXXRecordDecl *DerivedClassDecl = 0; @@ -124,6 +124,12 @@ RValue CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,      Val = EmitAnyExprToTemp(E, /*IsAggLocVolatile=*/false,                              IsInitializer); +    if (ShouldDestroyTemporaries) { +      // Pop temporaries. +      while (LiveTemporaries.size() > OldNumLiveTemporaries) +        PopCXXTemporary(); +    }       +          if (IsInitializer) {        // We might have to destroy the temporary variable.        if (const RecordType *RT = E->getType()->getAs<RecordType>()) { @@ -297,6 +303,8 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {    case Expr::CXXReinterpretCastExprClass:    case Expr::CXXConstCastExprClass:      return EmitCastLValue(cast<CastExpr>(E)); +  case Expr::CXXZeroInitValueExprClass: +    return EmitNullInitializationLValue(cast<CXXZeroInitValueExpr>(E));    }  } @@ -858,6 +866,9 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {      llvm::Value *V = LocalDeclMap[IPD];      assert(V && "BlockVarDecl not entered in LocalDeclMap?");      return LValue::MakeAddr(V, MakeQualifiers(E->getType())); +  } else if (const QualifiedDeclRefExpr *QDRExpr =  +             dyn_cast<QualifiedDeclRefExpr>(E)) { +    return EmitPointerToDataMemberLValue(QDRExpr);    }    assert(0 && "Unimp declref");    //an invalid LValue, but the assert will @@ -1307,6 +1318,18 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) {    }  } +LValue CodeGenFunction::EmitNullInitializationLValue( +                                              const CXXZeroInitValueExpr *E) { +  QualType Ty = E->getType(); +  const llvm::Type *LTy = ConvertTypeForMem(Ty); +  llvm::AllocaInst *Alloc = CreateTempAlloca(LTy); +  unsigned Align = getContext().getTypeAlign(Ty)/8; +  Alloc->setAlignment(Align); +  LValue lvalue = LValue::MakeAddr(Alloc, Qualifiers()); +  EmitMemSetToZero(lvalue.getAddress(), Ty); +  return lvalue; +} +  //===--------------------------------------------------------------------===//  //                             Expression Emission  //===--------------------------------------------------------------------===// @@ -1356,11 +1379,24 @@ LValue CodeGenFunction::EmitBinaryOperatorLValue(const BinaryOperator *E) {      return EmitLValue(E->getRHS());    } +  if (E->getOpcode() == BinaryOperator::PtrMemD) +    return EmitPointerToDataMemberBinaryExpr(E); +      // Can only get l-value for binary operator expressions which are a    // simple assignment of aggregate type.    if (E->getOpcode() != BinaryOperator::Assign)      return EmitUnsupportedLValue(E, "binary l-value expression"); +  if (!hasAggregateLLVMType(E->getType())) { +    // Emit the LHS as an l-value. +    LValue LV = EmitLValue(E->getLHS()); +     +    llvm::Value *RHS = EmitScalarExpr(E->getRHS()); +    EmitStoreOfScalar(RHS, LV.getAddress(), LV.isVolatileQualified(),  +                      E->getType()); +    return LV; +  } +      llvm::Value *Temp = CreateTempAlloca(ConvertType(E->getType()));    EmitAggExpr(E, Temp, false);    // FIXME: Are these qualifiers correct? @@ -1483,6 +1519,25 @@ LValue CodeGenFunction::EmitStmtExprLValue(const StmtExpr *E) {  } +LValue CodeGenFunction::EmitPointerToDataMemberLValue( +                                              const QualifiedDeclRefExpr *E) { +  const FieldDecl *Field = cast<FieldDecl>(E->getDecl()); +  const CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(Field->getDeclContext()); +  QualType NNSpecTy =  +    getContext().getCanonicalType( +      getContext().getTypeDeclType(const_cast<CXXRecordDecl*>(ClassDecl))); +  NNSpecTy = getContext().getPointerType(NNSpecTy); +  llvm::Value *V = llvm::Constant::getNullValue(ConvertType(NNSpecTy)); +  LValue MemExpLV = EmitLValueForField(V, const_cast<FieldDecl*>(Field),  +                                       /*isUnion*/false, /*Qualifiers*/0); +  const llvm::Type* ResultType = ConvertType( +                                             getContext().getPointerDiffType()); +  V = Builder.CreatePtrToInt(MemExpLV.getAddress(), ResultType,  +                             "datamember"); +  LValue LV = LValue::MakeAddr(V, MakeQualifiers(E->getType())); +  return LV; +} +  RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,                                   CallExpr::const_arg_iterator ArgBeg,                                   CallExpr::const_arg_iterator ArgEnd, @@ -1492,11 +1547,13 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,    assert(CalleeType->isFunctionPointerType() &&           "Call must have function pointer type!"); -  QualType FnType = CalleeType->getAs<PointerType>()->getPointeeType(); -  QualType ResultType = FnType->getAs<FunctionType>()->getResultType(); +  CalleeType = getContext().getCanonicalType(CalleeType); + +  QualType FnType = cast<PointerType>(CalleeType)->getPointeeType(); +  QualType ResultType = cast<FunctionType>(FnType)->getResultType();    CallArgList Args; -  EmitCallArgs(Args, FnType->getAs<FunctionProtoType>(), ArgBeg, ArgEnd); +  EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);    // FIXME: We should not need to do this, it should be part of the function    // type. @@ -1508,3 +1565,25 @@ RValue CodeGenFunction::EmitCall(llvm::Value *Callee, QualType CalleeType,                                                   CallingConvention),                    Callee, Args, TargetDecl);  } + +LValue CodeGenFunction::EmitPointerToDataMemberBinaryExpr( +                                                    const BinaryOperator *E) { +  llvm::Value *BaseV = EmitLValue(E->getLHS()).getAddress(); +  const llvm::Type *i8Ty = llvm::Type::getInt8PtrTy(getLLVMContext()); +  BaseV = Builder.CreateBitCast(BaseV, i8Ty); +  LValue RHSLV = EmitLValue(E->getRHS()); +  llvm::Value *OffsetV =  +    EmitLoadOfLValue(RHSLV, E->getRHS()->getType()).getScalarVal(); +  const llvm::Type* ResultType = ConvertType(getContext().getPointerDiffType()); +  OffsetV = Builder.CreateBitCast(OffsetV, ResultType); +  llvm::Value *AddV = Builder.CreateInBoundsGEP(BaseV, OffsetV, "add.ptr"); +  QualType Ty = E->getRHS()->getType(); +  const MemberPointerType *MemPtrType = Ty->getAs<MemberPointerType>(); +  Ty = MemPtrType->getPointeeType(); +  const llvm::Type* PType =  +  ConvertType(getContext().getPointerType(Ty)); +  AddV = Builder.CreateBitCast(AddV, PType); +  LValue LV = LValue::MakeAddr(AddV, MakeQualifiers(Ty)); +  return LV; +} + diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 0866ff893c4e..f47b6ab3c8cc 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -92,6 +92,7 @@ public:    void VisitCallExpr(const CallExpr *E);    void VisitStmtExpr(const StmtExpr *E);    void VisitBinaryOperator(const BinaryOperator *BO); +  void VisitPointerToDataMemberBinaryOperator(const BinaryOperator *BO);    void VisitBinAssign(const BinaryOperator *E);    void VisitBinComma(const BinaryOperator *E);    void VisitUnaryAddrOf(const UnaryOperator *E); @@ -112,6 +113,7 @@ public:    void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E);    void VisitCXXConstructExpr(const CXXConstructExpr *E);    void VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E); +  void VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E);    void VisitVAArgExpr(VAArgExpr *E); @@ -214,6 +216,12 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {      break;    } +  case CastExpr::CK_BitCast: { +    // This must be a member function pointer cast. +    Visit(E->getSubExpr()); +    break; +  } +    case CastExpr::CK_BaseToDerivedMemberPointer: {      QualType SrcType = E->getSubExpr()->getType(); @@ -285,6 +293,7 @@ void AggExprEmitter::VisitBinComma(const BinaryOperator *E) {  void AggExprEmitter::VisitUnaryAddrOf(const UnaryOperator *E) {    // We have a member function pointer.    const MemberPointerType *MPT = E->getType()->getAs<MemberPointerType>(); +  (void) MPT;    assert(MPT->getPointeeType()->isFunctionProtoType() &&           "Unexpected member pointer type!"); @@ -320,7 +329,16 @@ void AggExprEmitter::VisitStmtExpr(const StmtExpr *E) {  }  void AggExprEmitter::VisitBinaryOperator(const BinaryOperator *E) { -  CGF.ErrorUnsupported(E, "aggregate binary expression"); +  if (E->getOpcode() == BinaryOperator::PtrMemD) +    VisitPointerToDataMemberBinaryOperator(E); +  else +    CGF.ErrorUnsupported(E, "aggregate binary expression"); +} + +void AggExprEmitter::VisitPointerToDataMemberBinaryOperator( +                                                    const BinaryOperator *E) { +  LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(E); +  EmitFinalDestCopy(E, LV);  }  void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { @@ -438,6 +456,11 @@ void AggExprEmitter::VisitCXXExprWithTemporaries(CXXExprWithTemporaries *E) {    CGF.EmitCXXExprWithTemporaries(E, DestPtr, VolatileDest, IsInitializer);  } +void AggExprEmitter::VisitCXXZeroInitValueExpr(CXXZeroInitValueExpr *E) { +  LValue lvalue = LValue::MakeAddr(DestPtr, Qualifiers()); +  EmitNullInitializationToLValue(lvalue, E->getType()); +} +  void AggExprEmitter::EmitInitializationToLValue(Expr* E, LValue LV) {    // FIXME: Ignore result?    // FIXME: Are initializers affected by volatile? diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index 7f540c3c0688..fc3748c8e3c8 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -542,7 +542,11 @@ public:          return CS;        }                } -         + +    case CastExpr::CK_BitCast:  +      // This must be a member function pointer cast. +      return Visit(E->getSubExpr()); +      default: {        // FIXME: This should be handled by the CK_NoOp cast kind.        // Explicit and implicit no-op casts diff --git a/lib/CodeGen/CGExprScalar.cpp b/lib/CodeGen/CGExprScalar.cpp index cc81256032af..69604f9aaaee 100644 --- a/lib/CodeGen/CGExprScalar.cpp +++ b/lib/CodeGen/CGExprScalar.cpp @@ -106,6 +106,7 @@ public:      return 0;    }    Value *VisitExpr(Expr *S); +      Value *VisitParenExpr(ParenExpr *PE) { return Visit(PE->getSubExpr()); }    // Leaves. @@ -181,48 +182,7 @@ public:    Value *VisitPredefinedExpr(Expr *E) { return EmitLValue(E).getAddress(); } -  Value *VisitInitListExpr(InitListExpr *E) { -    bool Ignore = TestAndClearIgnoreResultAssign(); -    (void)Ignore; -    assert (Ignore == false && "init list ignored"); -    unsigned NumInitElements = E->getNumInits(); - -    if (E->hadArrayRangeDesignator()) { -      CGF.ErrorUnsupported(E, "GNU array range designator extension"); -    } - -    const llvm::VectorType *VType = -      dyn_cast<llvm::VectorType>(ConvertType(E->getType())); - -    // We have a scalar in braces. Just use the first element. -    if (!VType) -      return Visit(E->getInit(0)); - -    unsigned NumVectorElements = VType->getNumElements(); -    const llvm::Type *ElementType = VType->getElementType(); - -    // Emit individual vector element stores. -    llvm::Value *V = llvm::UndefValue::get(VType); - -    // Emit initializers -    unsigned i; -    for (i = 0; i < NumInitElements; ++i) { -      Value *NewV = Visit(E->getInit(i)); -      Value *Idx = -        llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i); -      V = Builder.CreateInsertElement(V, NewV, Idx); -    } - -    // Emit remaining default initializers -    for (/* Do not initialize i*/; i < NumVectorElements; ++i) { -      Value *Idx = -        llvm::ConstantInt::get(llvm::Type::getInt32Ty(CGF.getLLVMContext()), i); -      llvm::Value *NewV = llvm::Constant::getNullValue(ElementType); -      V = Builder.CreateInsertElement(V, NewV, Idx); -    } - -    return V; -  } +  Value *VisitInitListExpr(InitListExpr *E);    Value *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {      return llvm::Constant::getNullValue(ConvertType(E->getType())); @@ -404,7 +364,7 @@ public:  /// EmitConversionToBool - Convert the specified expression value to a  /// boolean (i1) truth value.  This is equivalent to "Val != 0".  Value *ScalarExprEmitter::EmitConversionToBool(Value *Src, QualType SrcType) { -  assert(SrcType->isCanonical() && "EmitScalarConversion strips typedefs"); +  assert(SrcType.isCanonical() && "EmitScalarConversion strips typedefs");    if (SrcType->isRealFloatingType()) {      // Compare against 0.0 for fp scalars. @@ -577,6 +537,13 @@ EmitComplexToScalarConversion(CodeGenFunction::ComplexPairTy Src,  //===----------------------------------------------------------------------===//  Value *ScalarExprEmitter::VisitExpr(Expr *E) { +  if (const BinaryOperator *BExpr = dyn_cast<BinaryOperator>(E)) +    if (BExpr->getOpcode() == BinaryOperator::PtrMemD) { +      LValue LV = CGF.EmitPointerToDataMemberBinaryExpr(BExpr); +      Value *InVal = CGF.EmitLoadOfLValue(LV, E->getType()).getScalarVal(); +      return InVal; +    } +      CGF.ErrorUnsupported(E, "scalar expression");    if (E->getType()->isVoidType())      return 0; @@ -616,6 +583,174 @@ Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) {    return Builder.CreateExtractElement(Base, Idx, "vecext");  } +static llvm::Constant *getMaskElt(llvm::ShuffleVectorInst *SVI, unsigned Idx, +                                  unsigned Off, const llvm::Type *I32Ty) { +  int MV = SVI->getMaskValue(Idx); +  if (MV == -1)  +    return llvm::UndefValue::get(I32Ty); +  return llvm::ConstantInt::get(I32Ty, Off+MV); +} + +Value *ScalarExprEmitter::VisitInitListExpr(InitListExpr *E) { +  bool Ignore = TestAndClearIgnoreResultAssign(); +  (void)Ignore; +  assert (Ignore == false && "init list ignored"); +  unsigned NumInitElements = E->getNumInits(); +   +  if (E->hadArrayRangeDesignator()) +    CGF.ErrorUnsupported(E, "GNU array range designator extension"); +   +  const llvm::VectorType *VType = +    dyn_cast<llvm::VectorType>(ConvertType(E->getType())); +   +  // We have a scalar in braces. Just use the first element. +  if (!VType) +    return Visit(E->getInit(0)); +   +  unsigned ResElts = VType->getNumElements(); +  const llvm::Type *I32Ty = llvm::Type::getInt32Ty(CGF.getLLVMContext()); +   +  // Loop over initializers collecting the Value for each, and remembering  +  // whether the source was swizzle (ExtVectorElementExpr).  This will allow +  // us to fold the shuffle for the swizzle into the shuffle for the vector +  // initializer, since LLVM optimizers generally do not want to touch +  // shuffles. +  unsigned CurIdx = 0; +  bool VIsUndefShuffle = false; +  llvm::Value *V = llvm::UndefValue::get(VType); +  for (unsigned i = 0; i != NumInitElements; ++i) { +    Expr *IE = E->getInit(i); +    Value *Init = Visit(IE); +    llvm::SmallVector<llvm::Constant*, 16> Args; +     +    const llvm::VectorType *VVT = dyn_cast<llvm::VectorType>(Init->getType()); +     +    // Handle scalar elements.  If the scalar initializer is actually one +    // element of a different vector of the same width, use shuffle instead of  +    // extract+insert. +    if (!VVT) { +      if (isa<ExtVectorElementExpr>(IE)) { +        llvm::ExtractElementInst *EI = cast<llvm::ExtractElementInst>(Init); + +        if (EI->getVectorOperandType()->getNumElements() == ResElts) { +          llvm::ConstantInt *C = cast<llvm::ConstantInt>(EI->getIndexOperand()); +          Value *LHS = 0, *RHS = 0; +          if (CurIdx == 0) { +            // insert into undef -> shuffle (src, undef) +            Args.push_back(C); +            for (unsigned j = 1; j != ResElts; ++j) +              Args.push_back(llvm::UndefValue::get(I32Ty)); + +            LHS = EI->getVectorOperand(); +            RHS = V; +            VIsUndefShuffle = true; +          } else if (VIsUndefShuffle) { +            // insert into undefshuffle && size match -> shuffle (v, src) +            llvm::ShuffleVectorInst *SVV = cast<llvm::ShuffleVectorInst>(V); +            for (unsigned j = 0; j != CurIdx; ++j) +              Args.push_back(getMaskElt(SVV, j, 0, I32Ty)); +            Args.push_back(llvm::ConstantInt::get(I32Ty,  +                                                  ResElts + C->getZExtValue())); +            for (unsigned j = CurIdx + 1; j != ResElts; ++j) +              Args.push_back(llvm::UndefValue::get(I32Ty)); +             +            LHS = cast<llvm::ShuffleVectorInst>(V)->getOperand(0); +            RHS = EI->getVectorOperand(); +            VIsUndefShuffle = false; +          } +          if (!Args.empty()) { +            llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts); +            V = Builder.CreateShuffleVector(LHS, RHS, Mask); +            ++CurIdx; +            continue; +          } +        } +      } +      Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx); +      V = Builder.CreateInsertElement(V, Init, Idx, "vecinit"); +      VIsUndefShuffle = false; +      ++CurIdx; +      continue; +    } +     +    unsigned InitElts = VVT->getNumElements(); + +    // If the initializer is an ExtVecEltExpr (a swizzle), and the swizzle's  +    // input is the same width as the vector being constructed, generate an +    // optimized shuffle of the swizzle input into the result. +    if (isa<ExtVectorElementExpr>(IE)) { +      llvm::ShuffleVectorInst *SVI = cast<llvm::ShuffleVectorInst>(Init); +      Value *SVOp = SVI->getOperand(0); +      const llvm::VectorType *OpTy = cast<llvm::VectorType>(SVOp->getType()); +       +      if (OpTy->getNumElements() == ResElts) { +        unsigned Offset = (CurIdx == 0) ? 0 : ResElts; +         +        for (unsigned j = 0; j != CurIdx; ++j) { +          // If the current vector initializer is a shuffle with undef, merge +          // this shuffle directly into it. +          if (VIsUndefShuffle) { +            Args.push_back(getMaskElt(cast<llvm::ShuffleVectorInst>(V), j, 0, +                                      I32Ty)); +          } else { +            Args.push_back(llvm::ConstantInt::get(I32Ty, j)); +          } +        } +        for (unsigned j = 0, je = InitElts; j != je; ++j) +          Args.push_back(getMaskElt(SVI, j, Offset, I32Ty)); +        for (unsigned j = CurIdx + InitElts; j != ResElts; ++j) +          Args.push_back(llvm::UndefValue::get(I32Ty)); + +        if (VIsUndefShuffle) +          V = cast<llvm::ShuffleVectorInst>(V)->getOperand(0); + +        Init = SVOp; +      } +    } + +    // Extend init to result vector length, and then shuffle its contribution +    // to the vector initializer into V. +    if (Args.empty()) { +      for (unsigned j = 0; j != InitElts; ++j) +        Args.push_back(llvm::ConstantInt::get(I32Ty, j)); +      for (unsigned j = InitElts; j != ResElts; ++j) +        Args.push_back(llvm::UndefValue::get(I32Ty)); +      llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts); +      Init = Builder.CreateShuffleVector(Init, llvm::UndefValue::get(VVT), +                                         Mask, "vecext"); + +      Args.clear(); +      for (unsigned j = 0; j != CurIdx; ++j) +        Args.push_back(llvm::ConstantInt::get(I32Ty, j)); +      for (unsigned j = 0; j != InitElts; ++j) +        Args.push_back(llvm::ConstantInt::get(I32Ty, j+ResElts)); +      for (unsigned j = CurIdx + InitElts; j != ResElts; ++j) +        Args.push_back(llvm::UndefValue::get(I32Ty)); +    } + +    // If V is undef, make sure it ends up on the RHS of the shuffle to aid +    // merging subsequent shuffles into this one. +    if (CurIdx == 0) +      std::swap(V, Init); +    llvm::Constant *Mask = llvm::ConstantVector::get(&Args[0], ResElts); +    V = Builder.CreateShuffleVector(V, Init, Mask, "vecinit"); +    VIsUndefShuffle = isa<llvm::UndefValue>(Init); +    CurIdx += InitElts; +  } +   +  // FIXME: evaluate codegen vs. shuffling against constant null vector. +  // Emit remaining default initializers. +  const llvm::Type *EltTy = VType->getElementType(); +   +  // Emit remaining default initializers +  for (/* Do not initialize i*/; CurIdx < ResElts; ++CurIdx) { +    Value *Idx = llvm::ConstantInt::get(I32Ty, CurIdx); +    llvm::Value *Init = llvm::Constant::getNullValue(EltTy); +    V = Builder.CreateInsertElement(V, Init, Idx, "vecinit"); +  } +  return V; +} +  // VisitCastExpr - Emit code for an explicit or implicit cast.  Implicit casts  // have to handle a more broad range of conversions than explicit casts, as they  // handle things like function to ptr-to-function decay etc. @@ -700,7 +835,16 @@ Value *ScalarExprEmitter::EmitCastExpr(const CastExpr *CE) {    case CastExpr::CK_IntegralToPointer: {      Value *Src = Visit(const_cast<Expr*>(E)); -    return Builder.CreateIntToPtr(Src, ConvertType(DestTy)); +     +    // First, convert to the correct width so that we control the kind of +    // extension. +    const llvm::Type *MiddleTy = +      llvm::IntegerType::get(VMContext, CGF.LLVMPointerWidth); +    bool InputSigned = E->getType()->isSignedIntegerType(); +    llvm::Value* IntResult = +      Builder.CreateIntCast(Src, MiddleTy, InputSigned, "conv"); +     +    return Builder.CreateIntToPtr(IntResult, ConvertType(DestTy));    }    case CastExpr::CK_PointerToIntegral: { @@ -1379,18 +1523,20 @@ Value *ScalarExprEmitter::VisitBinAssign(const BinaryOperator *E) {  }  Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) { +  const llvm::Type *ResTy = ConvertType(E->getType()); +      // If we have 0 && RHS, see if we can elide RHS, if so, just return 0.    // If we have 1 && X, just emit X without inserting the control flow.    if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {      if (Cond == 1) { // If we have 1 && X, just emit X.        Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); -      // ZExt result to int. -      return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "land.ext"); +      // ZExt result to int or bool. +      return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "land.ext");      } -    // 0 && RHS: If it is safe, just elide the RHS, and return 0. +    // 0 && RHS: If it is safe, just elide the RHS, and return 0/false.      if (!CGF.ContainsLabel(E->getRHS())) -      return llvm::Constant::getNullValue(CGF.LLVMIntTy); +      return llvm::Constant::getNullValue(ResTy);    }    llvm::BasicBlock *ContBlock = CGF.createBasicBlock("land.end"); @@ -1423,22 +1569,24 @@ Value *ScalarExprEmitter::VisitBinLAnd(const BinaryOperator *E) {    PN->addIncoming(RHSCond, RHSBlock);    // ZExt result to int. -  return Builder.CreateZExt(PN, CGF.LLVMIntTy, "land.ext"); +  return Builder.CreateZExtOrBitCast(PN, ResTy, "land.ext");  }  Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) { +  const llvm::Type *ResTy = ConvertType(E->getType()); +      // If we have 1 || RHS, see if we can elide RHS, if so, just return 1.    // If we have 0 || X, just emit X without inserting the control flow.    if (int Cond = CGF.ConstantFoldsToSimpleInteger(E->getLHS())) {      if (Cond == -1) { // If we have 0 || X, just emit X.        Value *RHSCond = CGF.EvaluateExprAsBool(E->getRHS()); -      // ZExt result to int. -      return Builder.CreateZExt(RHSCond, CGF.LLVMIntTy, "lor.ext"); +      // ZExt result to int or bool. +      return Builder.CreateZExtOrBitCast(RHSCond, ResTy, "lor.ext");      } -    // 1 || RHS: If it is safe, just elide the RHS, and return 1. +    // 1 || RHS: If it is safe, just elide the RHS, and return 1/true.      if (!CGF.ContainsLabel(E->getRHS())) -      return llvm::ConstantInt::get(CGF.LLVMIntTy, 1); +      return llvm::ConstantInt::get(ResTy, 1);    }    llvm::BasicBlock *ContBlock = CGF.createBasicBlock("lor.end"); @@ -1474,7 +1622,7 @@ Value *ScalarExprEmitter::VisitBinLOr(const BinaryOperator *E) {    PN->addIncoming(RHSCond, RHSBlock);    // ZExt result to int. -  return Builder.CreateZExt(PN, CGF.LLVMIntTy, "lor.ext"); +  return Builder.CreateZExtOrBitCast(PN, ResTy, "lor.ext");  }  Value *ScalarExprEmitter::VisitBinComma(const BinaryOperator *E) { diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 4485ed5aee75..9b2f4a1faee7 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -850,7 +850,7 @@ protected:    /// \param[out] NameOut - The return value.    void GetNameForMethod(const ObjCMethodDecl *OMD,                          const ObjCContainerDecl *CD, -                        std::string &NameOut); +                        llvm::SmallVectorImpl<char> &NameOut);    /// GetMethodVarName - Return a unique constant for the given    /// selector's name. The return value has type char *. @@ -900,7 +900,7 @@ protected:    /// EmitPropertyList - Emit the given property list. The return    /// value has type PropertyListPtrTy. -  llvm::Constant *EmitPropertyList(const std::string &Name, +  llvm::Constant *EmitPropertyList(llvm::Twine Name,                                     const Decl *Container,                                     const ObjCContainerDecl *OCD,                                     const ObjCCommonTypesHelper &ObjCTypes); @@ -924,7 +924,7 @@ protected:    /// \param Align - The alignment for the variable, or 0.    /// \param AddToUsed - Whether the variable should be added to    /// "llvm.used". -  llvm::GlobalVariable *CreateMetadataVar(const std::string &Name, +  llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,                                            llvm::Constant *Init,                                            const char *Section,                                            unsigned Align, @@ -1025,7 +1025,7 @@ private:    /// EmitMethodList - Emit the method list for the given    /// implementation. The return value has type MethodListPtrTy. -  llvm::Constant *EmitMethodList(const std::string &Name, +  llvm::Constant *EmitMethodList(llvm::Twine Name,                                   const char *Section,                                   const ConstantVector &Methods); @@ -1040,7 +1040,7 @@ private:    ///  - begin, end: The method list to output.    ///    /// The return value has type MethodDescriptionListPtrTy. -  llvm::Constant *EmitMethodDescList(const std::string &Name, +  llvm::Constant *EmitMethodDescList(llvm::Twine Name,                                       const char *Section,                                       const ConstantVector &Methods); @@ -1066,7 +1066,7 @@ private:    /// EmitProtocolList - Generate the list of referenced    /// protocols. The return value has type ProtocolListPtrTy. -  llvm::Constant *EmitProtocolList(const std::string &Name, +  llvm::Constant *EmitProtocolList(llvm::Twine Name,                                     ObjCProtocolDecl::protocol_iterator begin,                                     ObjCProtocolDecl::protocol_iterator end); @@ -1197,7 +1197,7 @@ private:    /// EmitMethodList - Emit the method list for the given    /// implementation. The return value has type MethodListnfABITy. -  llvm::Constant *EmitMethodList(const std::string &Name, +  llvm::Constant *EmitMethodList(llvm::Twine Name,                                   const char *Section,                                   const ConstantVector &Methods);    /// EmitIvarList - Emit the ivar list for the given @@ -1224,7 +1224,7 @@ private:    /// EmitProtocolList - Generate the list of referenced    /// protocols. The return value has type ProtocolListPtrTy. -  llvm::Constant *EmitProtocolList(const std::string &Name, +  llvm::Constant *EmitProtocolList(llvm::Twine Name,                                     ObjCProtocolDecl::protocol_iterator begin,                                     ObjCProtocolDecl::protocol_iterator end); @@ -1616,8 +1616,6 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {    // resolved. Investigate. Its also wasteful to look this up over and over.    LazySymbols.insert(&CGM.getContext().Idents.get("Protocol")); -  const char *ProtocolName = PD->getNameAsCString(); -    // Construct method lists.    std::vector<llvm::Constant*> InstanceMethods, ClassMethods;    std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; @@ -1647,17 +1645,15 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {    Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);    Values[1] = GetClassName(PD->getIdentifier());    Values[2] = -    EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getNameAsString(), +    EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),                       PD->protocol_begin(),                       PD->protocol_end());    Values[3] = -    EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" -                       + PD->getNameAsString(), +    EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),                         "__OBJC,__cat_inst_meth,regular,no_dead_strip",                         InstanceMethods);    Values[4] = -    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" -                       + PD->getNameAsString(), +    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),                         "__OBJC,__cat_cls_meth,regular,no_dead_strip",                         ClassMethods);    llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy, @@ -1672,7 +1668,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {        new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,                                 llvm::GlobalValue::InternalLinkage,                                 Init, -                               std::string("\01L_OBJC_PROTOCOL_")+ProtocolName); +                               "\01L_OBJC_PROTOCOL_" + PD->getName());      Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");      Entry->setAlignment(4);      // FIXME: Is this necessary? Why only for protocol? @@ -1694,7 +1690,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {        new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,                                 llvm::GlobalValue::ExternalLinkage,                                 0, -                               "\01L_OBJC_PROTOCOL_" + PD->getNameAsString()); +                               "\01L_OBJC_PROTOCOL_" + PD->getName());      Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");      Entry->setAlignment(4);      // FIXME: Is this necessary? Why only for protocol? @@ -1722,16 +1718,14 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,    Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);    Values[1] =      EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" -                       + PD->getNameAsString(), +                       + PD->getName(),                         "__OBJC,__cat_inst_meth,regular,no_dead_strip",                         OptInstanceMethods);    Values[2] = -    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" -                       + PD->getNameAsString(), +    EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),                         "__OBJC,__cat_cls_meth,regular,no_dead_strip",                         OptClassMethods); -  Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + -                               PD->getNameAsString(), +  Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),                                 0, PD, ObjCTypes);    // Return null if no extension bits are used. @@ -1743,7 +1737,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,      llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);    // No special section, but goes in llvm.used -  return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getNameAsString(), +  return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),                             Init,                             0, 0, true);  } @@ -1756,7 +1750,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,    };  */  llvm::Constant * -CGObjCMac::EmitProtocolList(const std::string &Name, +CGObjCMac::EmitProtocolList(llvm::Twine Name,                              ObjCProtocolDecl::protocol_iterator begin,                              ObjCProtocolDecl::protocol_iterator end) {    std::vector<llvm::Constant*> ProtocolRefs; @@ -1800,7 +1794,7 @@ CGObjCMac::EmitProtocolList(const std::string &Name,    struct _objc_property[prop_count];    };  */ -llvm::Constant *CGObjCCommonMac::EmitPropertyList(const std::string &Name, +llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,                                         const Decl *Container,                                         const ObjCContainerDecl *OCD,                                         const ObjCCommonTypesHelper &ObjCTypes) { @@ -1854,7 +1848,7 @@ CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {                                     Desc);  } -llvm::Constant *CGObjCMac::EmitMethodDescList(const std::string &Name, +llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,                                                const char *Section,                                                const ConstantVector &Methods) {    // Return null for empty list. @@ -1894,8 +1888,10 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {    const ObjCInterfaceDecl *Interface = OCD->getClassInterface();    const ObjCCategoryDecl *Category =      Interface->FindCategoryDeclaration(OCD->getIdentifier()); -  std::string ExtName(Interface->getNameAsString() + "_" + -                      OCD->getNameAsString()); + +  llvm::SmallString<256> ExtName; +  llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_' +                                     << OCD->getName();    std::vector<llvm::Constant*> InstanceMethods, ClassMethods;    for (ObjCCategoryImplDecl::instmeth_iterator @@ -1914,17 +1910,16 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {    Values[1] = GetClassName(Interface->getIdentifier());    LazySymbols.insert(Interface->getIdentifier());    Values[2] = -    EmitMethodList(std::string("\01L_OBJC_CATEGORY_INSTANCE_METHODS_") + -                   ExtName, +    EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),                     "__OBJC,__cat_inst_meth,regular,no_dead_strip",                     InstanceMethods);    Values[3] = -    EmitMethodList(std::string("\01L_OBJC_CATEGORY_CLASS_METHODS_") + ExtName, +    EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),                     "__OBJC,__cat_cls_meth,regular,no_dead_strip",                     ClassMethods);    if (Category) {      Values[4] = -      EmitProtocolList(std::string("\01L_OBJC_CATEGORY_PROTOCOLS_") + ExtName, +      EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),                         Category->protocol_begin(),                         Category->protocol_end());    } else { @@ -1934,7 +1929,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {    // If there is no category @interface then there can be no properties.    if (Category) { -    Values[6] = EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_")+ExtName, +    Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),                                   OCD, Category, ObjCTypes);    } else {      Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); @@ -1944,7 +1939,7 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {                                                     Values);    llvm::GlobalVariable *GV = -    CreateMetadataVar(std::string("\01L_OBJC_CATEGORY_")+ExtName, Init, +    CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,                        "__OBJC,__category,regular,no_dead_strip",                        4, true);    DefinedCategories.push_back(GV); @@ -1988,7 +1983,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {    ObjCInterfaceDecl *Interface =      const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());    llvm::Constant *Protocols = -    EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getNameAsString(), +    EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),                       Interface->protocol_begin(),                       Interface->protocol_end());    unsigned Flags = eClassFlags_Factory; @@ -2046,7 +2041,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {    Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);    Values[ 6] = EmitIvarList(ID, false);    Values[ 7] = -    EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getNameAsString(), +    EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),                     "__OBJC,__inst_meth,regular,no_dead_strip",                     InstanceMethods);    // cache is always NULL. @@ -2058,7 +2053,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {                                                     Values);    llvm::GlobalVariable *GV = -    CreateMetadataVar(std::string("\01L_OBJC_CLASS_")+ClassName, Init, +    CreateMetadataVar("\01L_OBJC_CLASS_" + ClassName, Init,                        "__OBJC,__class,regular,no_dead_strip",                        4, true);    DefinedClasses.push_back(GV); @@ -2174,7 +2169,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {    std::vector<llvm::Constant*> Values(3);    Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);    Values[1] = BuildIvarLayout(ID, false); -  Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(), +  Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),                                 ID, ID->getClassInterface(), ObjCTypes);    // Return null if no extension bits are used. @@ -2183,7 +2178,7 @@ CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {    llvm::Constant *Init =      llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values); -  return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getNameAsString(), +  return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),                             Init, "__OBJC,__class_ext,regular,no_dead_strip",                             4, true);  } @@ -2243,12 +2238,11 @@ llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,    llvm::GlobalVariable *GV;    if (ForClass) -    GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getNameAsString(), +    GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),                             Init, "__OBJC,__class_vars,regular,no_dead_strip",                             4, true);    else -    GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" -                           + ID->getNameAsString(), +    GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),                             Init, "__OBJC,__instance_vars,regular,no_dead_strip",                             4, true);    return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy); @@ -2286,7 +2280,7 @@ llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {    return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);  } -llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name, +llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,                                            const char *Section,                                            const ConstantVector &Methods) {    // Return null for empty list. @@ -2308,7 +2302,7 @@ llvm::Constant *CGObjCMac::EmitMethodList(const std::string &Name,  llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,                                                  const ObjCContainerDecl *CD) { -  std::string Name; +  llvm::SmallString<256> Name;    GetNameForMethod(OMD, CD, Name);    CodeGenTypes &Types = CGM.getTypes(); @@ -2317,7 +2311,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,    llvm::Function *Method =      llvm::Function::Create(MethodTy,                             llvm::GlobalValue::InternalLinkage, -                           Name, +                           Name.str(),                             &CGM.getModule());    MethodDefinitions.insert(std::make_pair(OMD, Method)); @@ -2325,7 +2319,7 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,  }  llvm::GlobalVariable * -CGObjCCommonMac::CreateMetadataVar(const std::string &Name, +CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,                                     llvm::Constant *Init,                                     const char *Section,                                     unsigned Align, @@ -2985,7 +2979,8 @@ llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {    if (!Entry)      Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", -                          llvm::ConstantArray::get(VMContext, Ident->getName()), +                          llvm::ConstantArray::get(VMContext, +                                                   Ident->getNameStart()),                                "__TEXT,__cstring,cstring_literals",                                1, true); @@ -3434,7 +3429,8 @@ llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {    if (!Entry)      Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_", -                          llvm::ConstantArray::get(VMContext, Ident->getName()), +                          llvm::ConstantArray::get(VMContext, +                                                   Ident->getNameStart()),                                "__TEXT,__cstring,cstring_literals",                                1, true); @@ -3453,21 +3449,15 @@ CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,  void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,                                         const ObjCContainerDecl *CD, -                                       std::string &NameOut) { -  NameOut = '\01'; -  NameOut += (D->isInstanceMethod() ? '-' : '+'); -  NameOut += '['; +                                       llvm::SmallVectorImpl<char> &Name) { +  llvm::raw_svector_ostream OS(Name);    assert (CD && "Missing container decl in GetNameForMethod"); -  NameOut += CD->getNameAsString(); +  OS << '\01' << (D->isInstanceMethod() ? '-' : '+') +     << '[' << CD->getName();    if (const ObjCCategoryImplDecl *CID = -      dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) { -    NameOut += '('; -    NameOut += CID->getNameAsString(); -    NameOut+= ')'; -  } -  NameOut += ' '; -  NameOut += D->getSelector().getAsString(); -  NameOut += ']'; +      dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext())) +    OS << '(' << CID->getNameAsString() << ')'; +  OS << ' ' << D->getSelector().getAsString() << ']';  }  void CGObjCMac::FinishModule() { @@ -4256,7 +4246,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(    const ObjCInterfaceDecl *OID = ID->getClassInterface();    assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");    Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" -                                + OID->getNameAsString(), +                                + OID->getName(),                                  OID->protocol_begin(),                                  OID->protocol_end()); @@ -4269,9 +4259,8 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(    if (flags & CLS_META)      Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);    else -    Values[ 9] = -      EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getNameAsString(), -                       ID, ID->getClassInterface(), ObjCTypes); +    Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), +                                  ID, ID->getClassInterface(), ObjCTypes);    llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,                                                     Values);    llvm::GlobalVariable *CLASS_RO_GV = @@ -4532,16 +4521,16 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {    const ObjCCategoryDecl *Category =      Interface->FindCategoryDeclaration(OCD->getIdentifier());    if (Category) { -    std::string ExtName(Interface->getNameAsString() + "_$_" + -                        OCD->getNameAsString()); +    llvm::SmallString<256> ExtName; +    llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_" +                                       << OCD->getName();      Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_" -                                 + Interface->getNameAsString() + "_$_" -                                 + Category->getNameAsString(), +                                 + Interface->getName() + "_$_" +                                 + Category->getName(),                                   Category->protocol_begin(),                                   Category->protocol_end()); -    Values[5] = -      EmitPropertyList(std::string("\01l_OBJC_$_PROP_LIST_") + ExtName, -                       OCD, Category, ObjCTypes); +    Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), +                                 OCD, Category, ObjCTypes);    } else {      Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);      Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); @@ -4593,10 +4582,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(  ///   struct _objc_method method_list[method_count];  /// }  /// -llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList( -  const std::string &Name, -  const char *Section, -  const ConstantVector &Methods) { +llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name, +                                                       const char *Section, +                                                const ConstantVector &Methods) {    // Return null for empty list.    if (Methods.empty())      return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy); @@ -4742,7 +4730,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(      new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,                               llvm::GlobalValue::InternalLinkage,                               Init, -                             Prefix + OID->getNameAsString()); +                             Prefix + OID->getName());    GV->setAlignment(      CGM.getTargetData().getPrefTypeAlignment(Init->getType()));    GV->setSection("__DATA, __objc_const"); @@ -4763,7 +4751,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(        new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,                                 llvm::GlobalValue::ExternalLinkage,                                 0, -                               "\01l_OBJC_PROTOCOL_$_" + PD->getNameAsString()); +                               "\01l_OBJC_PROTOCOL_$_" + PD->getName());      Entry->setSection("__DATA,__datacoal_nt,coalesced");    } @@ -4795,8 +4783,6 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(    if (Entry && Entry->hasInitializer())      return Entry; -  const char *ProtocolName = PD->getNameAsCString(); -    // Construct method lists.    std::vector<llvm::Constant*> InstanceMethods, ClassMethods;    std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods; @@ -4826,28 +4812,27 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(    // isa is NULL    Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);    Values[1] = GetClassName(PD->getIdentifier()); -  Values[2] = EmitProtocolList( -    "\01l_OBJC_$_PROTOCOL_REFS_" + PD->getNameAsString(), -    PD->protocol_begin(), -    PD->protocol_end()); +  Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(), +                               PD->protocol_begin(), +                               PD->protocol_end());    Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_" -                             + PD->getNameAsString(), +                             + PD->getName(),                               "__DATA, __objc_const",                               InstanceMethods);    Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_" -                             + PD->getNameAsString(), +                             + PD->getName(),                               "__DATA, __objc_const",                               ClassMethods);    Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_" -                             + PD->getNameAsString(), +                             + PD->getName(),                               "__DATA, __objc_const",                               OptInstanceMethods);    Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_" -                             + PD->getNameAsString(), +                             + PD->getName(),                               "__DATA, __objc_const",                               OptClassMethods); -  Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getNameAsString(), +  Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),                                 0, PD, ObjCTypes);    uint32_t Size =      CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); @@ -4862,10 +4847,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(      Entry->setInitializer(Init);    } else {      Entry = -      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, -                               llvm::GlobalValue::WeakAnyLinkage, -                               Init, -                               std::string("\01l_OBJC_PROTOCOL_$_")+ProtocolName); +      new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, +                               false, llvm::GlobalValue::WeakAnyLinkage, Init, +                               "\01l_OBJC_PROTOCOL_$_" + PD->getName());      Entry->setAlignment(        CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABITy));      Entry->setSection("__DATA,__datacoal_nt,coalesced"); @@ -4875,13 +4859,10 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(    // Use this protocol meta-data to build protocol list table in section    // __DATA, __objc_protolist -  llvm::GlobalVariable *PTGV = new llvm::GlobalVariable( -    CGM.getModule(), -    ObjCTypes.ProtocolnfABIPtrTy, false, -    llvm::GlobalValue::WeakAnyLinkage, -    Entry, -    std::string("\01l_OBJC_LABEL_PROTOCOL_$_") -    +ProtocolName); +  llvm::GlobalVariable *PTGV = +    new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, +                             false, llvm::GlobalValue::WeakAnyLinkage, Entry, +                             "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());    PTGV->setAlignment(      CGM.getTargetData().getPrefTypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));    PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); @@ -4899,9 +4880,9 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(  /// @endcode  ///  llvm::Constant * -CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name, -                                         ObjCProtocolDecl::protocol_iterator begin, -                                         ObjCProtocolDecl::protocol_iterator end) { +CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name, +                                      ObjCProtocolDecl::protocol_iterator begin, +                                      ObjCProtocolDecl::protocol_iterator end) {    std::vector<llvm::Constant*> ProtocolRefs;    // Just return null for empty protocol lists @@ -4909,10 +4890,12 @@ CGObjCNonFragileABIMac::EmitProtocolList(const std::string &Name,      return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);    // FIXME: We shouldn't need to do this lookup here, should we? -  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true); +  llvm::SmallString<256> TmpName; +  Name.toVector(TmpName); +  llvm::GlobalVariable *GV = +    CGM.getModule().getGlobalVariable(TmpName.str(), true);    if (GV) -    return llvm::ConstantExpr::getBitCast(GV, -                                          ObjCTypes.ProtocolListnfABIPtrTy); +    return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);    for (; begin != end; ++begin)      ProtocolRefs.push_back(GetProtocolRef(*begin));  // Implemented??? @@ -5683,7 +5666,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,          new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,                                   llvm::GlobalValue::ExternalLinkage,                                   0, -                                 (std::string("OBJC_EHTYPE_$_") + +                                 ("OBJC_EHTYPE_$_" +                                    ID->getIdentifier()->getName()));    } @@ -5715,7 +5698,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,      Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,                                       llvm::GlobalValue::WeakAnyLinkage,                                       Init, -                                     (std::string("OBJC_EHTYPE_$_") + +                                     ("OBJC_EHTYPE_$_" +                                        ID->getIdentifier()->getName()));    } diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 6e73db359af1..9df0e1abd547 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -119,6 +119,43 @@ public:    Index_t VBlookup(CXXRecordDecl *D, CXXRecordDecl *B); +  Index_t getNVOffset_1(const CXXRecordDecl *D, const CXXRecordDecl *B, +    Index_t Offset = 0) { + +    if (B == D) +      return Offset; + +    const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(D); +    for (CXXRecordDecl::base_class_const_iterator i = D->bases_begin(), +           e = D->bases_end(); i != e; ++i) { +      const CXXRecordDecl *Base = +        cast<CXXRecordDecl>(i->getType()->getAs<RecordType>()->getDecl()); +      int64_t BaseOffset = 0; +      if (!i->isVirtual()) +        BaseOffset = Offset + Layout.getBaseClassOffset(Base); +      int64_t o = getNVOffset_1(Base, B, BaseOffset); +      if (o >= 0) +        return o; +    } + +    return -1; +  } + +  /// getNVOffset - Returns the non-virtual offset for the given (B) base of the +  /// derived class D. +  Index_t getNVOffset(QualType qB, QualType qD) { +    qD = qD->getAs<PointerType>()->getPointeeType(); +    qB = qB->getAs<PointerType>()->getPointeeType(); +    CXXRecordDecl *D = cast<CXXRecordDecl>(qD->getAs<RecordType>()->getDecl()); +    CXXRecordDecl *B = cast<CXXRecordDecl>(qB->getAs<RecordType>()->getDecl()); +    int64_t o = getNVOffset_1(D, B); +    if (o >= 0) +      return o; + +    assert(false && "FIXME: non-virtual base not found"); +    return 0; +  } +    /// getVbaseOffset - Returns the index into the vtable for the virtual base    /// offset for the given (B) virtual base of the derived class D.    Index_t getVbaseOffset(QualType qB, QualType qD) { @@ -138,8 +175,10 @@ public:    }    bool OverrideMethod(const CXXMethodDecl *MD, llvm::Constant *m, -                      bool MorallyVirtual, Index_t Offset) { +                      bool MorallyVirtual, Index_t OverrideOffset, +                      Index_t Offset) {      typedef CXXMethodDecl::method_iterator meth_iter; +    // FIXME: Should OverrideOffset's be Offset?      // FIXME: Don't like the nested loops.  For very large inheritance      // heirarchies we could have a table on the side with the final overridder @@ -166,11 +205,12 @@ public:          CallOffset ReturnOffset = std::make_pair(0, 0);          if (oret != ret) {            // FIXME: calculate offsets for covariance -          Index_t nv = 0;            if (CovariantThunks.count(OMD)) {              oret = CovariantThunks[OMD].second;              CovariantThunks.erase(OMD);            } +          // FIXME: Double check oret +          Index_t nv = getNVOffset(oret, ret)/8;            ReturnOffset = std::make_pair(nv, getVbaseOffset(oret, ret));          }          Index[MD] = i; @@ -180,17 +220,16 @@ public:          if (MorallyVirtual) {            Index_t &idx = VCall[OMD];            if (idx == 0) { -            VCallOffset[MD] = Offset/8; +            VCallOffset[MD] = OverrideOffset/8;              idx = VCalls.size()+1;              VCalls.push_back(0);            } else {              VCallOffset[MD] = VCallOffset[OMD]; -            VCalls[idx-1] = -VCallOffset[OMD] + Offset/8; +            VCalls[idx-1] = -VCallOffset[OMD] + OverrideOffset/8;            }            VCall[MD] = idx;            CallOffset ThisOffset; -          // FIXME: calculate non-virtual offset -          ThisOffset = std::make_pair(0 /* -CurrentVBaseOffset/8 + Offset/8 */, +          ThisOffset = std::make_pair(CurrentVBaseOffset/8 - Offset/8,                                        -((idx+extra+2)*LLVMPointerWidth/8));            // FIXME: Do we always have to build a covariant thunk to save oret,            // which is the containing virtual base class? @@ -204,8 +243,8 @@ public:          }          // FIXME: finish off -        int64_t O = VCallOffset[OMD] - Offset/8; -        // int64_t O = CurrentVBaseOffset/8 - Offset/8; +        int64_t O = VCallOffset[OMD] - OverrideOffset/8; +        // int64_t O = CurrentVBaseOffset/8 - OverrideOffset/8;          if (O || ReturnOffset.first || ReturnOffset.second) {            CallOffset ThisOffset = std::make_pair(O, 0); @@ -248,11 +287,11 @@ public:      CovariantThunks.clear();    } -  void OverrideMethods(Path_t *Path, bool MorallyVirtual) { +  void OverrideMethods(Path_t *Path, bool MorallyVirtual, int64_t Offset) {      for (Path_t::reverse_iterator i = Path->rbegin(),             e = Path->rend(); i != e; ++i) {        const CXXRecordDecl *RD = i->first; -      int64_t Offset = i->second; +      int64_t OverrideOffset = i->second;        for (method_iter mi = RD->method_begin(), me = RD->method_end(); mi != me;             ++mi) {          if (!mi->isVirtual()) @@ -272,7 +311,7 @@ public:            m = wrap(CGM.GetAddrOfFunction(MD, Ty));          } -        OverrideMethod(MD, m, MorallyVirtual, Offset); +        OverrideMethod(MD, m, MorallyVirtual, OverrideOffset, Offset);        }      }    } @@ -291,7 +330,7 @@ public:      }      // If we can find a previously allocated slot for this, reuse it. -    if (OverrideMethod(MD, m, MorallyVirtual, Offset)) +    if (OverrideMethod(MD, m, MorallyVirtual, Offset, Offset))        return;      // else allocate a new slot. @@ -344,7 +383,7 @@ public:      llvm::Constant *e = 0;      D(VCalls.insert(VCalls.begin(), 673));      D(VCalls.push_back(672)); -    methods.insert(methods.begin() + InsertionPoint, VCalls.size()/*+2*/, e); +    methods.insert(methods.begin() + InsertionPoint, VCalls.size(), e);      // The vcalls come first...      for (std::vector<Index_t>::reverse_iterator i = VCalls.rbegin(),             e = VCalls.rend(); @@ -380,7 +419,9 @@ public:      int VCallInsertionPoint = methods.size();      if (!DeferVCalls) {        insertVCalls(VCallInsertionPoint); -    } +    } else +      // FIXME: just for extra, or for all uses of VCalls.size post this? +      extra = -VCalls.size();      if (ForVirtualBase) {        D(methods.push_back(wrap(668))); @@ -463,7 +504,7 @@ public:      AddMethods(RD, MorallyVirtual, Offset);      if (Path) -      OverrideMethods(Path, MorallyVirtual); +      OverrideMethods(Path, MorallyVirtual, Offset);      return end(RD, offsets, Layout, PrimaryBase, PrimaryBaseWasVirtual,                 MorallyVirtual, Offset, ForVirtualBase, Path); diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 5206f447f8d0..ba93e5d0ebc8 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -167,18 +167,20 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,    Builder.SetInsertPoint(EntryBB); +  QualType FnType = getContext().getFunctionType(RetTy, 0, 0, false, 0); +    // Emit subprogram debug descriptor.    // FIXME: The cast here is a huge hack.    if (CGDebugInfo *DI = getDebugInfo()) {      DI->setLocation(StartLoc);      if (isa<FunctionDecl>(D)) { -      DI->EmitFunctionStart(CGM.getMangledName(GD), RetTy, CurFn, Builder); +      DI->EmitFunctionStart(CGM.getMangledName(GD), FnType, CurFn, Builder);      } else {        // Just use LLVM function name.        // FIXME: Remove unnecessary conversion to std::string when API settles.        DI->EmitFunctionStart(std::string(Fn->getName()).c_str(), -                            RetTy, CurFn, Builder); +                            FnType, CurFn, Builder);      }    } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 722d002c19f5..639e683f0369 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -34,6 +34,7 @@ namespace llvm {    class LLVMContext;    class Module;    class SwitchInst; +  class Twine;    class Value;  } @@ -355,6 +356,7 @@ public:    void BlockForwardSelf();    llvm::Value *LoadBlockStruct(); +  uint64_t AllocateBlockDecl(const BlockDeclRefExpr *E);    llvm::Value *GetAddrOfBlockDecl(const BlockDeclRefExpr *E);    const llvm::Type *BuildByRefType(const ValueDecl *D); @@ -508,7 +510,7 @@ public:    /// CreateTempAlloca - This creates a alloca and inserts it into the entry    /// block.    llvm::AllocaInst *CreateTempAlloca(const llvm::Type *Ty, -                                     const char *Name = "tmp"); +                                     const llvm::Twine &Name = "tmp");    /// EvaluateExprAsBool - Perform the usual unary conversions on the specified    /// expression and compare the result against zero, returning an Int1Ty value. @@ -816,7 +818,9 @@ public:    LValue EmitCompoundLiteralLValue(const CompoundLiteralExpr *E);    LValue EmitConditionalOperatorLValue(const ConditionalOperator *E);    LValue EmitCastLValue(const CastExpr *E); - +  LValue EmitNullInitializationLValue(const CXXZeroInitValueExpr *E); +  LValue EmitPointerToDataMemberLValue(const QualifiedDeclRefExpr *E); +      llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface,                                const ObjCIvarDecl *Ivar);    LValue EmitLValueForField(llvm::Value* Base, FieldDecl* Field, @@ -841,7 +845,8 @@ public:    LValue EmitObjCKVCRefLValue(const ObjCImplicitSetterGetterRefExpr *E);    LValue EmitObjCSuperExprLValue(const ObjCSuperExpr *E);    LValue EmitStmtExprLValue(const StmtExpr *E); - +  LValue EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E); +      //===--------------------------------------------------------------------===//    //                         Scalar Expression Emission    //===--------------------------------------------------------------------===// diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp index 4763b7fc1ee2..ea84829b78a5 100644 --- a/lib/CodeGen/CodeGenModule.cpp +++ b/lib/CodeGen/CodeGenModule.cpp @@ -825,7 +825,7 @@ llvm::Constant *  CodeGenModule::CreateRuntimeFunction(const llvm::FunctionType *FTy,                                       const char *Name) {    // Convert Name to be a uniqued string from the IdentifierInfo table. -  Name = getContext().Idents.get(Name).getName(); +  Name = getContext().Idents.get(Name).getNameStart();    return GetOrCreateLLVMFunction(Name, FTy, GlobalDecl());  } @@ -911,7 +911,7 @@ llvm::Constant *  CodeGenModule::CreateRuntimeVariable(const llvm::Type *Ty,                                       const char *Name) {    // Convert Name to be a uniqued string from the IdentifierInfo table. -  Name = getContext().Idents.get(Name).getName(); +  Name = getContext().Idents.get(Name).getNameStart();    return GetOrCreateLLVMGlobal(Name, llvm::PointerType::getUnqual(Ty), 0);  } @@ -1254,7 +1254,7 @@ void CodeGenModule::EmitAliasDefinition(const ValueDecl *D) {    // Unique the name through the identifier table.    const char *AliaseeName = AA->getAliasee().c_str(); -  AliaseeName = getContext().Idents.get(AliaseeName).getName(); +  AliaseeName = getContext().Idents.get(AliaseeName).getNameStart();    // Create a reference to the named value.  This ensures that it is emitted    // if a deferred decl. @@ -1341,7 +1341,7 @@ llvm::Value *CodeGenModule::getBuiltinLibFunction(const FunctionDecl *FD,      cast<llvm::FunctionType>(getTypes().ConvertType(Type));    // Unique the name through the identifier table. -  Name = getContext().Idents.get(Name).getName(); +  Name = getContext().Idents.get(Name).getNameStart();    return GetOrCreateLLVMFunction(Name, Ty, GlobalDecl(FD));  } diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index fd772748dbda..2e6034bbcd97 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -248,7 +248,12 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) {      FD = PrimaryTemplate->getTemplatedDecl();    } -  mangleBareFunctionType(FD->getType()->getAs<FunctionType>(), MangleReturnType); +  // Do the canonicalization out here because parameter types can +  // undergo additional canonicalization (e.g. array decay). +  FunctionType *FT = cast<FunctionType>(Context.getASTContext() +                                          .getCanonicalType(FD->getType())); + +  mangleBareFunctionType(FT, MangleReturnType);  }  static bool isStdNamespace(const DeclContext *DC) { @@ -705,7 +710,7 @@ void CXXNameMangler::mangleType(QualType T) {    // Only operate on the canonical type!    T = Context.getASTContext().getCanonicalType(T); -  bool IsSubstitutable = !isa<BuiltinType>(T); +  bool IsSubstitutable = T.hasQualifiers() || !isa<BuiltinType>(T);    if (IsSubstitutable && mangleSubstitution(T))      return; @@ -1236,10 +1241,7 @@ static bool isCharSpecialization(QualType T, const char *Name) {    if (!isCharType(TemplateArgs[0].getAsType()))      return false; -  if (strcmp(SD->getIdentifier()->getName(), Name) != 0) -    return false; - -  return true; +  return SD->getIdentifier()->getName() == Name;  }  bool CXXNameMangler::mangleStandardSubstitution(const NamedDecl *ND) { diff --git a/lib/CodeGen/TargetABIInfo.cpp b/lib/CodeGen/TargetABIInfo.cpp index 59f579f7b17e..852bba4ef033 100644 --- a/lib/CodeGen/TargetABIInfo.cpp +++ b/lib/CodeGen/TargetABIInfo.cpp @@ -353,11 +353,17 @@ ABIArgInfo X86_32ABIInfo::classifyReturnType(QualType RetTy,      return ABIArgInfo::getDirect();    } else if (CodeGenFunction::hasAggregateLLVMType(RetTy)) { -    // Structures with flexible arrays are always indirect. -    if (const RecordType *RT = RetTy->getAsStructureType()) +    if (const RecordType *RT = RetTy->getAsStructureType()) { +      // Structures with either a non-trivial destructor or a non-trivial +      // copy constructor are always indirect. +      if (hasNonTrivialDestructorOrCopyConstructor(RT)) +        return ABIArgInfo::getIndirect(0, /*ByVal=*/false); +       +      // Structures with flexible arrays are always indirect.        if (RT->getDecl()->hasFlexibleArrayMember())          return ABIArgInfo::getIndirect(0); - +    } +          // If specified, structs and unions are always indirect.      if (!IsSmallStructInRegABI && !RetTy->isAnyComplexType())        return ABIArgInfo::getIndirect(0); @@ -1744,14 +1750,14 @@ const ABIInfo &CodeGenTypes::getABIInfo() const {      return *(TheABIInfo = new SystemZABIInfo());    case llvm::Triple::x86: -    if (Triple.getOS() == llvm::Triple::Darwin) -      return *(TheABIInfo = new X86_32ABIInfo(Context, true, true)); -      switch (Triple.getOS()) { +    case llvm::Triple::Darwin: +      return *(TheABIInfo = new X86_32ABIInfo(Context, true, true));      case llvm::Triple::Cygwin: -    case llvm::Triple::DragonFly:      case llvm::Triple::MinGW32:      case llvm::Triple::MinGW64: +    case llvm::Triple::AuroraUX: +    case llvm::Triple::DragonFly:      case llvm::Triple::FreeBSD:      case llvm::Triple::OpenBSD:        return *(TheABIInfo = new X86_32ABIInfo(Context, false, true)); diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp index a5a48adcf028..ae8119d33d64 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp @@ -38,7 +38,8 @@ Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple,    DarwinVersion[2] = _DarwinVersion[2];    llvm::raw_string_ostream(MacosxVersionMin) -    << "10." << DarwinVersion[0] - 4 << '.' << DarwinVersion[1]; +    << "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.' +    << DarwinVersion[1];    // FIXME: Lift default up.    IPhoneOSVersionMin = "3.0"; @@ -54,7 +55,6 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,    GCCVersion[2] = _GCCVersion[2];    // Set up the tool chain paths to match gcc. -    ToolChainDir = "i686-apple-darwin";    ToolChainDir += llvm::utostr(DarwinVersion[0]);    ToolChainDir += "/"; @@ -64,6 +64,26 @@ DarwinGCC::DarwinGCC(const HostInfo &Host, const llvm::Triple& Triple,    ToolChainDir += '.';    ToolChainDir += llvm::utostr(GCCVersion[2]); +  // Try the next major version if that tool chain dir is invalid. +  std::string Tmp = "/usr/lib/gcc/" + ToolChainDir; +  if (!llvm::sys::Path(Tmp).exists()) { +    std::string Next = "i686-apple-darwin"; +    Next += llvm::utostr(DarwinVersion[0] + 1); +    Next += "/"; +    Next += llvm::utostr(GCCVersion[0]); +    Next += '.'; +    Next += llvm::utostr(GCCVersion[1]); +    Next += '.'; +    Next += llvm::utostr(GCCVersion[2]); + +    // Use that if it exists, otherwise hope the user isn't linking. +    // +    // FIXME: Drop dependency on gcc's tool chain. +    Tmp = "/usr/lib/gcc/" + Next; +    if (llvm::sys::Path(Tmp).exists()) +      ToolChainDir = Next; +  } +    std::string Path;    if (getArchName() == "x86_64") {      Path = getHost().getDriver().Dir; @@ -676,6 +696,7 @@ AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple)    getFilePaths().push_back("/usr/lib");    getFilePaths().push_back("/usr/sfw/lib");    getFilePaths().push_back("/opt/gcc4/lib"); +  getFilePaths().push_back("/opt/gcc4/lib/gcc/i386-pc-solaris2.11/4.2.4");  } diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index fc91e4c43799..c9d0b266d1cc 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -142,10 +142,15 @@ void Clang::AddPreprocessingOptions(const Driver &D,        continue;      if (A->getOption().matches(options::OPT_include)) { +      // Use PCH if the user requested it, except for C++ (for now). +      bool UsePCH = D.CCCUsePCH; +      if (types::isCXX(Inputs[0].getType())) +        UsePCH = false; +        bool FoundPTH = false;        bool FoundPCH = false;        llvm::sys::Path P(A->getValue(Args)); -      if (D.CCCUsePCH) { +      if (UsePCH) {          P.appendSuffix("pch");          if (P.exists())            FoundPCH = true; @@ -164,8 +169,8 @@ void Clang::AddPreprocessingOptions(const Driver &D,        if (!FoundPCH && !FoundPTH) {          P.appendSuffix("gch");          if (P.exists()) { -          FoundPCH = D.CCCUsePCH; -          FoundPTH = !D.CCCUsePCH; +          FoundPCH = UsePCH; +          FoundPTH = !UsePCH;          }          else            P.eraseSuffix(); @@ -173,7 +178,7 @@ void Clang::AddPreprocessingOptions(const Driver &D,        if (FoundPCH || FoundPTH) {          A->claim(); -        if (D.CCCUsePCH) +        if (UsePCH)            CmdArgs.push_back("-include-pch");          else            CmdArgs.push_back("-include-pth"); @@ -528,7 +533,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,      else        CmdArgs.push_back("-E");    } else if (isa<PrecompileJobAction>(JA)) { -    if (D.CCCUsePCH) +    // Use PCH if the user requested it, except for C++ (for now). +    bool UsePCH = D.CCCUsePCH; +    if (types::isCXX(Inputs[0].getType())) +      UsePCH = false; + +    if (UsePCH)        CmdArgs.push_back("-emit-pch");      else        CmdArgs.push_back("-emit-pth"); @@ -759,7 +769,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,    // option.    if (Arg *Std = Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) {      if (Std->getOption().matches(options::OPT_ansi)) -      CmdArgs.push_back("-std=c89"); +      if (types::isCXX(InputType)) +          CmdArgs.push_back("-std=c++98"); +      else +          CmdArgs.push_back("-std=c89");      else        Std->render(Args, CmdArgs); @@ -2149,7 +2162,7 @@ void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA,    }    const char *Exec = -    Args.MakeArgString(getToolChain().GetProgramPath(C, "as")); +    Args.MakeArgString(getToolChain().GetProgramPath(C, "gas"));    Dest.addCommand(new Command(JA, Exec, CmdArgs));  } @@ -2164,18 +2177,19 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,    if ((!Args.hasArg(options::OPT_nostdlib)) &&       (!Args.hasArg(options::OPT_shared))) {      CmdArgs.push_back("-e"); -    CmdArgs.push_back("__start"); +    CmdArgs.push_back("_start");    }    if (Args.hasArg(options::OPT_static)) {      CmdArgs.push_back("-Bstatic"); +    CmdArgs.push_back("-dn");    } else { -    CmdArgs.push_back("--eh-frame-hdr"); +//    CmdArgs.push_back("--eh-frame-hdr");      CmdArgs.push_back("-Bdynamic");      if (Args.hasArg(options::OPT_shared)) {        CmdArgs.push_back("-shared");      } else { -      CmdArgs.push_back("-dynamic-linker"); +      CmdArgs.push_back("--dynamic-linker");        CmdArgs.push_back("/lib/ld.so.1"); // 64Bit Path /lib/amd64/ld.so.1      }    } @@ -2193,11 +2207,14 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,    if (!Args.hasArg(options::OPT_nostdlib) &&        !Args.hasArg(options::OPT_nostartfiles)) {      if (!Args.hasArg(options::OPT_shared)) { -      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt0.o"))); +      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crt1.o"))); +      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o")));        CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbegin.o")));      } else { -      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o"))); +      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crti.o"))); +//      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtbeginS.o")));      } +    CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtn.o")));    }    CmdArgs.push_back(MakeFormattedString(Args, @@ -2242,8 +2259,8 @@ void auroraux::Link::ConstructJob(Compilation &C, const JobAction &JA,        !Args.hasArg(options::OPT_nostartfiles)) {      if (!Args.hasArg(options::OPT_shared))        CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtend.o"))); -    else -      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o"))); +//    else +//      CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath(C, "crtendS.o")));    }    const char *Exec = diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index d3475b5236d9..c0415bf550f8 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -21,11 +21,20 @@  #include "clang/Basic/TargetInfo.h"  #include "clang/Basic/Diagnostic.h"  #include "llvm/Support/Compiler.h" +#include "llvm/System/Path.h"  using namespace clang; -ASTUnit::ASTUnit(Diagnostic &_Diags) : Diags(_Diags) { } -ASTUnit::~ASTUnit() { } +ASTUnit::ASTUnit(DiagnosticClient *diagClient) : tempFile(false) {       +  Diags.setClient(diagClient ? diagClient : new TextDiagnosticBuffer()); +} +ASTUnit::~ASTUnit() {  +  if (tempFile) +    llvm::sys::Path(getPCHFileName()).eraseFromDisk(); +   +  //  The ASTUnit object owns the DiagnosticClient. +  delete Diags.getClient(); +}  namespace { @@ -80,17 +89,18 @@ const std::string &ASTUnit::getOriginalSourceFileName() {    return dyn_cast<PCHReader>(Ctx->getExternalSource())->getOriginalSourceFile();  } -FileManager &ASTUnit::getFileManager() { -  return HeaderInfo->getFileMgr(); +const std::string &ASTUnit::getPCHFileName() { +  return dyn_cast<PCHReader>(Ctx->getExternalSource())->getFileName();  }  ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename, -                                  Diagnostic &Diags, -                                  FileManager &FileMgr, -                                  std::string *ErrMsg) { -  llvm::OwningPtr<ASTUnit> AST(new ASTUnit(Diags)); - -  AST->HeaderInfo.reset(new HeaderSearch(FileMgr)); +                                  std::string *ErrMsg, +                                  DiagnosticClient *diagClient, +                                  bool OnlyLocalDecls, +                                  bool UseBumpAllocator) { +  llvm::OwningPtr<ASTUnit> AST(new ASTUnit(diagClient)); +  AST->OnlyLocalDecls = OnlyLocalDecls; +  AST->HeaderInfo.reset(new HeaderSearch(AST->getFileManager()));    // Gather Info for preprocessor construction later on. @@ -103,7 +113,8 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,    llvm::OwningPtr<PCHReader> Reader;    llvm::OwningPtr<ExternalASTSource> Source; -  Reader.reset(new PCHReader(AST->getSourceManager(), FileMgr, AST->Diags)); +  Reader.reset(new PCHReader(AST->getSourceManager(), AST->getFileManager(), +                             AST->Diags));    Reader->setListener(new PCHInfoCollector(LangInfo, HeaderInfo, TargetTriple,                                             Predefines, Counter)); @@ -138,7 +149,7 @@ ASTUnit *ASTUnit::LoadFromPCHFile(const std::string &Filename,                                  PP.getIdentifierTable(),                                  PP.getSelectorTable(),                                  PP.getBuiltinInfo(), -                                /* FreeMemory = */ true, +                                /* FreeMemory = */ !UseBumpAllocator,                                  /* size_reserve = */0));    ASTContext &Context = *AST->Ctx.get(); diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp index 276599470b78..55f274005909 100644 --- a/lib/Frontend/AnalysisConsumer.cpp +++ b/lib/Frontend/AnalysisConsumer.cpp @@ -196,7 +196,7 @@ void AnalysisConsumer::HandleTopLevelSingleDecl(Decl *D) {      case Decl::Function: {        FunctionDecl* FD = cast<FunctionDecl>(D); -      if (Opts.AnalyzeSpecificFunction.size() > 0 && +      if (!Opts.AnalyzeSpecificFunction.empty() &&            Opts.AnalyzeSpecificFunction != FD->getIdentifier()->getName())          break; @@ -273,6 +273,9 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {        !Ctx->getSourceManager().isFromMainFile(D->getLocation()))      return; +  // Clear the AnalysisManager of old AnalysisContexts. +  Mgr->ClearContexts(); +      // Dispatch on the actions.    for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)      (*I)(*Mgr, D);   diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index e7fc5660ad20..339a1c466bc9 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -20,11 +20,12 @@  #include "clang/Basic/OnDiskHashTable.h"  #include "clang/Lex/Lexer.h"  #include "clang/Lex/Preprocessor.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h"  #include "llvm/Support/Compiler.h"  #include "llvm/Support/MemoryBuffer.h"  #include "llvm/Support/raw_ostream.h"  #include "llvm/System/Path.h" -#include "llvm/ADT/StringMap.h"  // FIXME: put this somewhere else?  #ifndef S_ISDIR @@ -69,7 +70,7 @@ public:    bool isFile() const { return Kind == IsFE; } -  const char* getCString() const { +  llvm::StringRef getString() const {      return Kind == IsFE ? FE->getName() : Path;    } @@ -113,14 +114,14 @@ public:    typedef const PTHEntry& data_type_ref;    static unsigned ComputeHash(PTHEntryKeyVariant V) { -    return BernsteinHash(V.getCString()); +    return llvm::HashString(V.getString());    }    static std::pair<unsigned,unsigned>    EmitKeyDataLength(llvm::raw_ostream& Out, PTHEntryKeyVariant V,                      const PTHEntry& E) { -    unsigned n = strlen(V.getCString()) + 1 + 1; +    unsigned n = V.getString().size() + 1 + 1;      ::Emit16(Out, n);      unsigned m = V.getRepresentationLength() + (V.isFile() ? 4 + 4 : 0); @@ -133,7 +134,7 @@ public:      // Emit the entry kind.      ::Emit8(Out, (unsigned) V.getKind());      // Emit the string. -    Out.write(V.getCString(), n - 1); +    Out.write(V.getString().data(), n - 1);    }    static void EmitData(llvm::raw_ostream& Out, PTHEntryKeyVariant V, @@ -516,7 +517,7 @@ public:    ~StatListener() {}    int stat(const char *path, struct stat *buf) { -    int result = ::stat(path, buf); +    int result = StatSysCallCache::stat(path, buf);      if (result != 0) // Failed 'stat'.        PM.insert(path, PTHEntry()); @@ -553,7 +554,8 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {    PTHWriter PW(*OS, PP);    // Install the 'stat' system call listener in the FileManager. -  PP.getFileManager().setStatCache(new StatListener(PW.getPM())); +  StatListener *StatCache = new StatListener(PW.getPM()); +  PP.getFileManager().addStatCache(StatCache, /*AtBeginning=*/true);    // Lex through the entire file.  This will populate SourceManager with    // all of the header information. @@ -562,7 +564,7 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) {    do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));    // Generate the PTH file. -  PP.getFileManager().setStatCache(0); +  PP.getFileManager().removeStatCache(StatCache);    PW.GeneratePTH(&MainFileName);  } @@ -584,12 +586,12 @@ public:    typedef data_type data_type_ref;    static unsigned ComputeHash(PTHIdKey* key) { -    return BernsteinHash(key->II->getName()); +    return llvm::HashString(key->II->getName());    }    static std::pair<unsigned,unsigned>    EmitKeyDataLength(llvm::raw_ostream& Out, const PTHIdKey* key, uint32_t) { -    unsigned n = strlen(key->II->getName()) + 1; +    unsigned n = key->II->getLength() + 1;      ::Emit16(Out, n);      return std::make_pair(n, sizeof(uint32_t));    } @@ -598,7 +600,7 @@ public:      // Record the location of the key data.  This is used when generating      // the mapping from persistent IDs to strings.      key->FileOffset = Out.tell(); -    Out.write(key->II->getName(), n); +    Out.write(key->II->getNameStart(), n);    }    static void EmitData(llvm::raw_ostream& Out, PTHIdKey*, uint32_t pID, diff --git a/lib/Frontend/GeneratePCH.cpp b/lib/Frontend/GeneratePCH.cpp index bc45cc422585..0e4f83ff09f5 100644 --- a/lib/Frontend/GeneratePCH.cpp +++ b/lib/Frontend/GeneratePCH.cpp @@ -53,7 +53,7 @@ PCHGenerator::PCHGenerator(const Preprocessor &PP,    // Install a stat() listener to keep track of all of the stat()    // calls.    StatCalls = new MemorizeStatCalls; -  PP.getFileManager().setStatCache(StatCalls); +  PP.getFileManager().addStatCache(StatCalls, /*AtBeginning=*/true);  }  void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index 822a5baf5972..25316bed9fb4 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -369,6 +369,12 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,                                        "x86_64-unknown-linux-gnu",                                        "x86_64-unknown-linux-gnu",                                        triple); +          // Gentoo x86 2009.1 stable +          AddGnuCPlusPlusIncludePaths( +             "/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4", +             "i686-pc-linux-gnu", +             "i686-pc-linux-gnu", +             triple);            // Gentoo x86 2009.0 stable            AddGnuCPlusPlusIncludePaths(               "/usr/lib/gcc/i686-pc-linux-gnu/4.3.2/include/g++-v4", @@ -386,6 +392,11 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,                                        "i486-pc-linux-gnu",                                        "i486-pc-linux-gnu",                                        triple); +          // Ubuntu 9.04 +          AddGnuCPlusPlusIncludePaths("/usr/include/c++/4.3", +                                      "i486-linux-gnu", +                                      "i486-linux-gnu", +                                      triple);            // Gentoo amd64 stable            AddGnuCPlusPlusIncludePaths(               "/usr/lib/gcc/x86_64-pc-linux-gnu/4.1.2/include/g++-v4", @@ -400,6 +411,8 @@ void InitHeaderSearch::AddDefaultSystemIncludePaths(const LangOptions &Lang,            AddPath("/usr/include/c++/4.2", System, true, false, false);            break;          case llvm::Triple::Solaris: +          // Solaris - Fall though.. +        case llvm::Triple::AuroraUX:            // AuroraUX            AddGnuCPlusPlusIncludePaths("/opt/gcc4/include/c++/4.2.4",                                        "i386-pc-solaris2.11", diff --git a/lib/Frontend/InitPreprocessor.cpp b/lib/Frontend/InitPreprocessor.cpp index 0f3b4b8236be..b1a0a5ee8d51 100644 --- a/lib/Frontend/InitPreprocessor.cpp +++ b/lib/Frontend/InitPreprocessor.cpp @@ -317,13 +317,22 @@ static void InitializePredefinedMacros(const TargetInfo &TI,      DefineBuiltinMacro(Buf, "_GNU_SOURCE=1");    } -  // Filter out some microsoft extensions when trying to parse in ms-compat -  // mode.    if (LangOpts.Microsoft) { +    // Filter out some microsoft extensions when trying to parse in ms-compat +    // mode.      DefineBuiltinMacro(Buf, "__int8=__INT8_TYPE__");      DefineBuiltinMacro(Buf, "__int16=__INT16_TYPE__");      DefineBuiltinMacro(Buf, "__int32=__INT32_TYPE__");      DefineBuiltinMacro(Buf, "__int64=__INT64_TYPE__"); +    // Work around some issues with Visual C++ headerws. +    if (LangOpts.CPlusPlus) { +      // Since we define wchar_t in C++ mode. +      DefineBuiltinMacro(Buf, "_WCHAR_T_DEFINED=1"); +      DefineBuiltinMacro(Buf, "_NATIVE_WCHAR_T_DEFINED=1"); +      // FIXME:  This should be temporary until we have a __pragma +      // solution, to avoid some errors flagged in VC++ headers. +      DefineBuiltinMacro(Buf, "_CRT_SECURE_CPP_OVERLOAD_SECURE_NAMES=0"); +    }    }    if (LangOpts.Optimize) @@ -365,8 +374,7 @@ static void InitializePredefinedMacros(const TargetInfo &TI,    DefineType("__INTPTR_TYPE__", TI.getIntPtrType(), Buf);    DefineType("__SIZE_TYPE__", TI.getSizeType(), Buf);    DefineType("__WCHAR_TYPE__", TI.getWCharType(), Buf); -  // FIXME: TargetInfo hookize __WINT_TYPE__. -  DefineBuiltinMacro(Buf, "__WINT_TYPE__=int"); +  DefineType("__WINT_TYPE__", TI.getWIntType(), Buf);    DefineFloatMacros(Buf, "FLT", &TI.getFloatFormat());    DefineFloatMacros(Buf, "DBL", &TI.getDoubleFormat()); diff --git a/lib/Frontend/PCHReader.cpp b/lib/Frontend/PCHReader.cpp index e61668dd3177..9c6059b1c7c0 100644 --- a/lib/Frontend/PCHReader.cpp +++ b/lib/Frontend/PCHReader.cpp @@ -18,6 +18,7 @@  #include "clang/AST/ASTContext.h"  #include "clang/AST/Expr.h"  #include "clang/AST/Type.h" +#include "clang/AST/TypeLocVisitor.h"  #include "clang/Lex/MacroInfo.h"  #include "clang/Lex/Preprocessor.h"  #include "clang/Lex/HeaderSearch.h" @@ -27,6 +28,7 @@  #include "clang/Basic/FileManager.h"  #include "clang/Basic/TargetInfo.h"  #include "clang/Basic/Version.h" +#include "llvm/ADT/StringExtras.h"  #include "llvm/Bitcode/BitstreamReader.h"  #include "llvm/Support/Compiler.h"  #include "llvm/Support/MemoryBuffer.h" @@ -335,8 +337,6 @@ void PCHValidator::ReadCounter(unsigned Value) {    PP.setCounterValue(Value);  } - -  //===----------------------------------------------------------------------===//  // PCH reader implementation  //===----------------------------------------------------------------------===// @@ -345,7 +345,7 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,                       const char *isysroot)    : Listener(new PCHValidator(PP, *this)), SourceMgr(PP.getSourceManager()),      FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), -    SemaObj(0), PP(&PP), Context(Context), Consumer(0), +    SemaObj(0), PP(&PP), Context(Context), StatCache(0), Consumer(0),      IdentifierTableData(0), IdentifierLookupTable(0),      IdentifierOffsets(0),      MethodPoolLookupTable(0), MethodPoolLookupTableData(0), @@ -362,7 +362,7 @@ PCHReader::PCHReader(Preprocessor &PP, ASTContext *Context,  PCHReader::PCHReader(SourceManager &SourceMgr, FileManager &FileMgr,                       Diagnostic &Diags, const char *isysroot)    : SourceMgr(SourceMgr), FileMgr(FileMgr), Diags(Diags), -    SemaObj(0), PP(0), Context(0), Consumer(0), +    SemaObj(0), PP(0), Context(0), StatCache(0), Consumer(0),      IdentifierTableData(0), IdentifierLookupTable(0),      IdentifierOffsets(0),      MethodPoolLookupTable(0), MethodPoolLookupTableData(0), @@ -383,7 +383,7 @@ Expr *PCHReader::ReadDeclExpr() {  }  Expr *PCHReader::ReadTypeExpr() { -  return dyn_cast_or_null<Expr>(ReadStmt(Stream)); +  return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));  } @@ -411,7 +411,7 @@ public:      unsigned R = 5381;      for (unsigned I = 0; I != N; ++I)        if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) -        R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R); +        R = llvm::HashString(II->getName(), R);      return R;    } @@ -521,7 +521,7 @@ public:    }    static unsigned ComputeHash(const internal_key_type& a) { -    return BernsteinHash(a.first, a.second); +    return llvm::HashString(llvm::StringRef(a.first, a.second));    }    // This hopefully will just get inlined and removed by the optimizer. @@ -731,7 +731,7 @@ class VISIBILITY_HIDDEN PCHStatLookupTrait {    typedef PCHStatData data_type;    static unsigned ComputeHash(const char *path) { -    return BernsteinHash(path); +    return llvm::HashString(path);    }    static internal_key_type GetInternalKey(const char *path) { return path; } @@ -794,7 +794,7 @@ public:      // If we don't get a hit in the PCH file just forward to 'stat'.      if (I == Cache->end()) {        ++NumStatMisses; -      return ::stat(path, buf); +      return StatSysCallCache::stat(path, buf);      }      ++NumStatHits; @@ -1158,15 +1158,7 @@ PCHReader::ReadPCHBlock() {      if (Code == llvm::bitc::ENTER_SUBBLOCK) {        switch (Stream.ReadSubBlockID()) { -      case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded) -      default:  // Skip unknown content. -        if (Stream.SkipBlock()) { -          Error("malformed block record in PCH file"); -          return Failure; -        } -        break; - -      case pch::DECLS_BLOCK_ID: +      case pch::DECLTYPES_BLOCK_ID:          // We lazily load the decls block, but we want to set up the          // DeclsCursor cursor to point into it.  Clone our current bitcode          // cursor to it, enter the block and read the abbrevs in that block. @@ -1174,7 +1166,7 @@ PCHReader::ReadPCHBlock() {          DeclsCursor = Stream;          if (Stream.SkipBlock() ||  // Skip with the main cursor.              // Read the abbrevs. -            ReadBlockAbbrevs(DeclsCursor, pch::DECLS_BLOCK_ID)) { +            ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {            Error("malformed block record in PCH file");            return Failure;          } @@ -1352,13 +1344,16 @@ PCHReader::ReadPCHBlock() {        }        break; -    case pch::STAT_CACHE: -      FileMgr.setStatCache( -                  new PCHStatCache((const unsigned char *)BlobStart + Record[0], -                                   (const unsigned char *)BlobStart, -                                   NumStatHits, NumStatMisses)); +    case pch::STAT_CACHE: { +      PCHStatCache *MyStatCache =  +        new PCHStatCache((const unsigned char *)BlobStart + Record[0], +                         (const unsigned char *)BlobStart, +                         NumStatHits, NumStatMisses); +      FileMgr.addStatCache(MyStatCache); +      StatCache = MyStatCache;        break; - +    } +              case pch::EXT_VECTOR_DECLS:        if (!ExtVectorDecls.empty()) {          Error("duplicate EXT_VECTOR_DECLS record in PCH file"); @@ -1466,7 +1461,8 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {          SourceMgr.ClearPreallocatedSLocEntries();          // Remove the stat cache. -        FileMgr.setStatCache(0); +        if (StatCache) +          FileMgr.removeStatCache((PCHStatCache*)StatCache);          return IgnorePCH;        } @@ -1509,7 +1505,7 @@ PCHReader::PCHReadResult PCHReader::ReadPCH(const std::string &FileName) {        IdentifierInfo *II = Identifiers[I];        // Look in the on-disk hash table for an entry for        PCHIdentifierLookupTrait Info(*this, II); -      std::pair<const char*, unsigned> Key(II->getName(), II->getLength()); +      std::pair<const char*, unsigned> Key(II->getNameStart(), II->getLength());        PCHIdentifierLookupTable::iterator Pos = IdTable->find(Key, &Info);        if (Pos == IdTable->end())          continue; @@ -1593,6 +1589,11 @@ void PCHReader::InitializeContext(ASTContext &Ctx) {    if (unsigned ObjCClassRedef        = SpecialTypes[pch::SPECIAL_TYPE_OBJC_CLASS_REDEFINITION])      Context->ObjCClassRedefinitionType = GetType(ObjCClassRedef); +  if (unsigned String = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_DESCRIPTOR]) +    Context->setBlockDescriptorType(GetType(String)); +  if (unsigned String +      = SpecialTypes[pch::SPECIAL_TYPE_BLOCK_EXTENDED_DESCRIPTOR]) +    Context->setBlockDescriptorExtendedType(GetType(String));  }  /// \brief Retrieve the name of the original source file name @@ -1770,15 +1771,15 @@ void PCHReader::ReadComments(std::vector<SourceRange> &Comments) {  QualType PCHReader::ReadTypeRecord(uint64_t Offset) {    // Keep track of where we are in the stream, then jump back there    // after reading this type. -  SavedStreamPosition SavedPosition(Stream); +  SavedStreamPosition SavedPosition(DeclsCursor);    // Note that we are loading a type record.    LoadingTypeOrDecl Loading(*this); -  Stream.JumpToBit(Offset); +  DeclsCursor.JumpToBit(Offset);    RecordData Record; -  unsigned Code = Stream.ReadCode(); -  switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) { +  unsigned Code = DeclsCursor.ReadCode(); +  switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {    case pch::TYPE_EXT_QUAL: {      assert(Record.size() == 2 &&             "Incorrect encoding of extended qualifier type"); @@ -1839,30 +1840,6 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {                                           ASM, IndexTypeQuals);    } -  case pch::TYPE_CONSTANT_ARRAY_WITH_EXPR: { -    QualType ElementType = GetType(Record[0]); -    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; -    unsigned IndexTypeQuals = Record[2]; -    SourceLocation LBLoc = SourceLocation::getFromRawEncoding(Record[3]); -    SourceLocation RBLoc = SourceLocation::getFromRawEncoding(Record[4]); -    unsigned Idx = 5; -    llvm::APInt Size = ReadAPInt(Record, Idx); -    return Context->getConstantArrayWithExprType(ElementType, -                                                 Size, ReadTypeExpr(), -                                                 ASM, IndexTypeQuals, -                                                 SourceRange(LBLoc, RBLoc)); -  } - -  case pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR: { -    QualType ElementType = GetType(Record[0]); -    ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; -    unsigned IndexTypeQuals = Record[2]; -    unsigned Idx = 3; -    llvm::APInt Size = ReadAPInt(Record, Idx); -    return Context->getConstantArrayWithoutExprType(ElementType, Size, -                                                    ASM, IndexTypeQuals); -  } -    case pch::TYPE_INCOMPLETE_ARRAY: {      QualType ElementType = GetType(Record[0]);      ArrayType::ArraySizeModifier ASM = (ArrayType::ArraySizeModifier)Record[1]; @@ -1987,20 +1964,184 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) {      return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos);    } -  case pch::TYPE_OBJC_PROTOCOL_LIST: { +  case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: {      unsigned Idx = 0; -    QualType OIT = GetType(Record[Idx++]); -    unsigned NumProtos = Record[Idx++]; -    llvm::SmallVector<ObjCProtocolDecl*, 4> Protos; -    for (unsigned I = 0; I != NumProtos; ++I) -      Protos.push_back(cast<ObjCProtocolDecl>(GetDecl(Record[Idx++]))); -    return Context->getObjCProtocolListType(OIT, Protos.data(), NumProtos); +    QualType Parm = GetType(Record[Idx++]); +    QualType Replacement = GetType(Record[Idx++]); +    return +      Context->getSubstTemplateTypeParmType(cast<TemplateTypeParmType>(Parm), +                                            Replacement);    }    }    // Suppress a GCC warning    return QualType();  } +namespace { + +class TypeLocReader : public TypeLocVisitor<TypeLocReader> { +  PCHReader &Reader; +  const PCHReader::RecordData &Record; +  unsigned &Idx; + +public: +  TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record, +                unsigned &Idx) +    : Reader(Reader), Record(Record), Idx(Idx) { } + +  // We want compile-time assurance that we've enumerated all of +  // these, so unfortunately we have to declare them first, then +  // define them out-of-line. +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ +  void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); +#include "clang/AST/TypeLocNodes.def" + +  void VisitFunctionTypeLoc(FunctionTypeLoc); +  void VisitArrayTypeLoc(ArrayTypeLoc); +}; + +} + +void TypeLocReader::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { +  // nothing to do +} +void TypeLocReader::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitComplexTypeLoc(ComplexTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitPointerTypeLoc(PointerTypeLoc TL) { +  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { +  TL.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { +  TL.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { +  TL.setAmpAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { +  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitArrayTypeLoc(ArrayTypeLoc TL) { +  TL.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  TL.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  if (Record[Idx++]) +    TL.setSizeExpr(Reader.ReadDeclExpr()); +  else +    TL.setSizeExpr(0); +} +void TypeLocReader::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { +  VisitArrayTypeLoc(TL); +} +void TypeLocReader::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { +  VisitArrayTypeLoc(TL); +} +void TypeLocReader::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { +  VisitArrayTypeLoc(TL); +} +void TypeLocReader::VisitDependentSizedArrayTypeLoc( +                                            DependentSizedArrayTypeLoc TL) { +  VisitArrayTypeLoc(TL); +} +void TypeLocReader::VisitDependentSizedExtVectorTypeLoc( +                                        DependentSizedExtVectorTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitFunctionTypeLoc(FunctionTypeLoc TL) { +  TL.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  TL.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { +    TL.setArg(i, cast_or_null<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); +  } +} +void TypeLocReader::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { +  VisitFunctionTypeLoc(TL); +} +void TypeLocReader::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { +  VisitFunctionTypeLoc(TL); +} +void TypeLocReader::VisitTypedefTypeLoc(TypedefTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitRecordTypeLoc(RecordTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitEnumTypeLoc(EnumTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitSubstTemplateTypeParmTypeLoc( +                                            SubstTemplateTypeParmTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitTemplateSpecializationTypeLoc( +                                           TemplateSpecializationTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { +  TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) +    TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++])); +} +void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { +  TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  TL.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  TL.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); +  TL.setHasBaseTypeAsWritten(Record[Idx++]); +  TL.setHasProtocolsAsWritten(Record[Idx++]); +  if (TL.hasProtocolsAsWritten()) +    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) +      TL.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++])); +} + +DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record, +                                             unsigned &Idx) { +  QualType InfoTy = GetType(Record[Idx++]); +  if (InfoTy.isNull()) +    return 0; + +  DeclaratorInfo *DInfo = getContext()->CreateDeclaratorInfo(InfoTy); +  TypeLocReader TLR(*this, Record, Idx); +  for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) +    TLR.Visit(TL); +  return DInfo; +}  QualType PCHReader::GetType(pch::TypeID ID) {    unsigned FastQuals = ID & Qualifiers::FastMask; @@ -2374,7 +2515,10 @@ IdentifierInfo *PCHReader::DecodeIdentifierInfo(unsigned ID) {      // All of the strings in the PCH file are preceded by a 16-bit      // length. Extract that 16-bit length to avoid having to execute      // strlen(). -    const char *StrLenPtr = Str - 2; +    // NOTE: 'StrLenPtr' is an 'unsigned char*' so that we load bytes as +    //  unsigned integers.  This is important to avoid integer overflow when +    //  we cast them to 'unsigned'. +    const unsigned char *StrLenPtr = (const unsigned char*) Str - 2;      unsigned StrLen = (((unsigned) StrLenPtr[0])                         | (((unsigned) StrLenPtr[1]) << 8)) - 1;      IdentifiersLoaded[ID - 1] diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index b6732561dff0..d1cb461640b7 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -18,7 +18,6 @@  #include "clang/AST/DeclVisitor.h"  #include "clang/AST/DeclGroup.h"  #include "clang/AST/Expr.h" -#include "clang/AST/TypeLocVisitor.h"  using namespace clang; @@ -86,6 +85,7 @@ void PCHDeclReader::VisitDecl(Decl *D) {    D->setImplicit(Record[Idx++]);    D->setUsed(Record[Idx++]);    D->setAccess((AccessSpecifier)Record[Idx++]); +  D->setPCHLevel(Record[Idx++] + 1);  }  void PCHDeclReader::VisitTranslationUnitDecl(TranslationUnitDecl *TU) { @@ -149,84 +149,11 @@ void PCHDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) {    ECD->setInitVal(Reader.ReadAPSInt(Record, Idx));  } -namespace { - -class TypeLocReader : public TypeLocVisitor<TypeLocReader> { -  PCHReader &Reader; -  const PCHReader::RecordData &Record; -  unsigned &Idx; - -public: -  TypeLocReader(PCHReader &Reader, const PCHReader::RecordData &Record, -                unsigned &Idx) -    : Reader(Reader), Record(Record), Idx(Idx) { } - -#define ABSTRACT_TYPELOC(CLASS) -#define TYPELOC(CLASS, PARENT) \ -    void Visit##CLASS(CLASS TyLoc); -#include "clang/AST/TypeLocNodes.def" - -  void VisitTypeLoc(TypeLoc TyLoc) { -    assert(0 && "A type loc wrapper was not handled!"); -  } -}; - -} - -void TypeLocReader::VisitQualifiedLoc(QualifiedLoc TyLoc) { -  // nothing to do -} -void TypeLocReader::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { -  TyLoc.setStartLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitTypedefLoc(TypedefLoc TyLoc) { -  TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) { -  TyLoc.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) { -  TyLoc.setLAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -  TyLoc.setRAngleLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -  for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i) -    TyLoc.setProtocolLoc(i, SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitPointerLoc(PointerLoc TyLoc) { -  TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitBlockPointerLoc(BlockPointerLoc TyLoc) { -  TyLoc.setCaretLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitMemberPointerLoc(MemberPointerLoc TyLoc) { -  TyLoc.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitReferenceLoc(ReferenceLoc TyLoc) { -  TyLoc.setAmpLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitFunctionLoc(FunctionLoc TyLoc) { -  TyLoc.setLParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -  TyLoc.setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -  for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i) -    TyLoc.setArg(i, cast<ParmVarDecl>(Reader.GetDecl(Record[Idx++]))); -} -void TypeLocReader::VisitArrayLoc(ArrayLoc TyLoc) { -  TyLoc.setLBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -  TyLoc.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -  if (Record[Idx++]) -    TyLoc.setSizeExpr(Reader.ReadDeclExpr()); -} -  void PCHDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) {    VisitValueDecl(DD); -  QualType InfoTy = Reader.GetType(Record[Idx++]); -  if (InfoTy.isNull()) -    return; - -  DeclaratorInfo *DInfo = Reader.getContext()->CreateDeclaratorInfo(InfoTy); -  TypeLocReader TLR(Reader, Record, Idx); -  for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) -    TLR.Visit(TL); -  DD->setDeclaratorInfo(DInfo); +  DeclaratorInfo *DInfo = Reader.GetDeclaratorInfo(Record, Idx); +  if (DInfo) +    DD->setDeclaratorInfo(DInfo);  }  void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 64a678ea450b..fb48df332121 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -19,6 +19,7 @@  #include "clang/AST/DeclContextInternals.h"  #include "clang/AST/Expr.h"  #include "clang/AST/Type.h" +#include "clang/AST/TypeLocVisitor.h"  #include "clang/Lex/MacroInfo.h"  #include "clang/Lex/Preprocessor.h"  #include "clang/Lex/HeaderSearch.h" @@ -30,6 +31,7 @@  #include "clang/Basic/Version.h"  #include "llvm/ADT/APFloat.h"  #include "llvm/ADT/APInt.h" +#include "llvm/ADT/StringExtras.h"  #include "llvm/Bitcode/BitstreamWriter.h"  #include "llvm/Support/Compiler.h"  #include "llvm/Support/MemoryBuffer.h" @@ -117,23 +119,6 @@ void PCHTypeWriter::VisitConstantArrayType(const ConstantArrayType *T) {    Code = pch::TYPE_CONSTANT_ARRAY;  } -void PCHTypeWriter -::VisitConstantArrayWithExprType(const ConstantArrayWithExprType *T) { -  VisitArrayType(T); -  Writer.AddSourceLocation(T->getLBracketLoc(), Record); -  Writer.AddSourceLocation(T->getRBracketLoc(), Record); -  Writer.AddAPInt(T->getSize(), Record); -  Writer.AddStmt(T->getSizeExpr()); -  Code = pch::TYPE_CONSTANT_ARRAY_WITH_EXPR; -} - -void PCHTypeWriter -::VisitConstantArrayWithoutExprType(const ConstantArrayWithoutExprType *T) { -  VisitArrayType(T); -  Writer.AddAPInt(T->getSize(), Record); -  Code = pch::TYPE_CONSTANT_ARRAY_WITHOUT_EXPR; -} -  void PCHTypeWriter::VisitIncompleteArrayType(const IncompleteArrayType *T) {    VisitArrayType(T);    Code = pch::TYPE_INCOMPLETE_ARRAY; @@ -225,6 +210,14 @@ void PCHTypeWriter::VisitElaboratedType(const ElaboratedType *T) {  }  void +PCHTypeWriter::VisitSubstTemplateTypeParmType( +                                        const SubstTemplateTypeParmType *T) { +  Writer.AddTypeRef(QualType(T->getReplacedParameter(), 0), Record); +  Writer.AddTypeRef(T->getReplacementType(), Record); +  Code = pch::TYPE_SUBST_TEMPLATE_TYPE_PARM; +} + +void  PCHTypeWriter::VisitTemplateSpecializationType(                                         const TemplateSpecializationType *T) {    // FIXME: Serialize this type (C++ only) @@ -255,13 +248,150 @@ PCHTypeWriter::VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {    Code = pch::TYPE_OBJC_OBJECT_POINTER;  } -void PCHTypeWriter::VisitObjCProtocolListType(const ObjCProtocolListType *T) { -  Writer.AddTypeRef(T->getBaseType(), Record); -  Record.push_back(T->getNumProtocols()); -  for (ObjCProtocolListType::qual_iterator I = T->qual_begin(), -       E = T->qual_end(); I != E; ++I) -    Writer.AddDeclRef(*I, Record); -  Code = pch::TYPE_OBJC_PROTOCOL_LIST; +namespace { + +class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { +  PCHWriter &Writer; +  PCHWriter::RecordData &Record; + +public: +  TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) +    : Writer(Writer), Record(Record) { } + +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ +    void Visit##CLASS##TypeLoc(CLASS##TypeLoc TyLoc); +#include "clang/AST/TypeLocNodes.def" + +  void VisitArrayTypeLoc(ArrayTypeLoc TyLoc); +  void VisitFunctionTypeLoc(FunctionTypeLoc TyLoc); +}; + +} + +void TypeLocWriter::VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { +  // nothing to do +} +void TypeLocWriter::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitFixedWidthIntTypeLoc(FixedWidthIntTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitComplexTypeLoc(ComplexTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitPointerTypeLoc(PointerTypeLoc TL) { +  Writer.AddSourceLocation(TL.getStarLoc(), Record); +} +void TypeLocWriter::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { +  Writer.AddSourceLocation(TL.getCaretLoc(), Record); +} +void TypeLocWriter::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { +  Writer.AddSourceLocation(TL.getAmpLoc(), Record); +} +void TypeLocWriter::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { +  Writer.AddSourceLocation(TL.getAmpAmpLoc(), Record); +} +void TypeLocWriter::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { +  Writer.AddSourceLocation(TL.getStarLoc(), Record); +} +void TypeLocWriter::VisitArrayTypeLoc(ArrayTypeLoc TL) { +  Writer.AddSourceLocation(TL.getLBracketLoc(), Record); +  Writer.AddSourceLocation(TL.getRBracketLoc(), Record); +  Record.push_back(TL.getSizeExpr() ? 1 : 0); +  if (TL.getSizeExpr()) +    Writer.AddStmt(TL.getSizeExpr()); +} +void TypeLocWriter::VisitConstantArrayTypeLoc(ConstantArrayTypeLoc TL) { +  VisitArrayTypeLoc(TL); +} +void TypeLocWriter::VisitIncompleteArrayTypeLoc(IncompleteArrayTypeLoc TL) { +  VisitArrayTypeLoc(TL); +} +void TypeLocWriter::VisitVariableArrayTypeLoc(VariableArrayTypeLoc TL) { +  VisitArrayTypeLoc(TL); +} +void TypeLocWriter::VisitDependentSizedArrayTypeLoc( +                                            DependentSizedArrayTypeLoc TL) { +  VisitArrayTypeLoc(TL); +} +void TypeLocWriter::VisitDependentSizedExtVectorTypeLoc( +                                        DependentSizedExtVectorTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitFunctionTypeLoc(FunctionTypeLoc TL) { +  Writer.AddSourceLocation(TL.getLParenLoc(), Record); +  Writer.AddSourceLocation(TL.getRParenLoc(), Record); +  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) +    Writer.AddDeclRef(TL.getArg(i), Record); +} +void TypeLocWriter::VisitFunctionProtoTypeLoc(FunctionProtoTypeLoc TL) { +  VisitFunctionTypeLoc(TL); +} +void TypeLocWriter::VisitFunctionNoProtoTypeLoc(FunctionNoProtoTypeLoc TL) { +  VisitFunctionTypeLoc(TL); +} +void TypeLocWriter::VisitTypedefTypeLoc(TypedefTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitDecltypeTypeLoc(DecltypeTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitRecordTypeLoc(RecordTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitEnumTypeLoc(EnumTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitTemplateTypeParmTypeLoc(TemplateTypeParmTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitSubstTemplateTypeParmTypeLoc( +                                            SubstTemplateTypeParmTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitTemplateSpecializationTypeLoc( +                                           TemplateSpecializationTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitQualifiedNameTypeLoc(QualifiedNameTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +} +void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { +  Writer.AddSourceLocation(TL.getNameLoc(), Record); +  Writer.AddSourceLocation(TL.getLAngleLoc(), Record); +  Writer.AddSourceLocation(TL.getRAngleLoc(), Record); +  for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) +    Writer.AddSourceLocation(TL.getProtocolLoc(i), Record); +} +void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { +  Writer.AddSourceLocation(TL.getStarLoc(), Record); +  Writer.AddSourceLocation(TL.getLAngleLoc(), Record); +  Writer.AddSourceLocation(TL.getRAngleLoc(), Record); +  Record.push_back(TL.hasBaseTypeAsWritten()); +  Record.push_back(TL.hasProtocolsAsWritten()); +  if (TL.hasProtocolsAsWritten()) +    for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) +      Writer.AddSourceLocation(TL.getProtocolLoc(i), Record);  }  //===----------------------------------------------------------------------===// @@ -411,8 +541,8 @@ void PCHWriter::WriteBlockInfoBlock() {    RECORD(PP_MACRO_FUNCTION_LIKE);    RECORD(PP_TOKEN); -  // Types block. -  BLOCK(TYPES_BLOCK); +  // Decls and Types block. +  BLOCK(DECLTYPES_BLOCK);    RECORD(TYPE_EXT_QUAL);    RECORD(TYPE_FIXED_WIDTH_INT);    RECORD(TYPE_COMPLEX); @@ -435,12 +565,6 @@ void PCHWriter::WriteBlockInfoBlock() {    RECORD(TYPE_ENUM);    RECORD(TYPE_OBJC_INTERFACE);    RECORD(TYPE_OBJC_OBJECT_POINTER); -  RECORD(TYPE_OBJC_PROTOCOL_LIST); -  // Statements and Exprs can occur in the Types block. -  AddStmtsExprs(Stream, Record); - -  // Decls block. -  BLOCK(DECLS_BLOCK);    RECORD(DECL_ATTR);    RECORD(DECL_TRANSLATION_UNIT);    RECORD(DECL_TYPEDEF); @@ -470,7 +594,7 @@ void PCHWriter::WriteBlockInfoBlock() {    RECORD(DECL_BLOCK);    RECORD(DECL_CONTEXT_LEXICAL);    RECORD(DECL_CONTEXT_VISIBLE); -  // Statements and Exprs can occur in the Decls block. +  // Statements and Exprs can occur in the Decls and Types block.    AddStmtsExprs(Stream, Record);  #undef RECORD  #undef BLOCK @@ -662,7 +786,7 @@ public:    typedef const data_type& data_type_ref;    static unsigned ComputeHash(const char *path) { -    return BernsteinHash(path); +    return llvm::HashString(path);    }    std::pair<unsigned,unsigned> @@ -878,10 +1002,10 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,    std::vector<uint32_t> SLocEntryOffsets;    RecordData PreloadSLocs;    SLocEntryOffsets.reserve(SourceMgr.sloc_entry_size() - 1); -  for (SourceManager::sloc_entry_iterator -         SLoc = SourceMgr.sloc_entry_begin() + 1, -         SLocEnd = SourceMgr.sloc_entry_end(); -       SLoc != SLocEnd; ++SLoc) { +  for (unsigned I = 1, N = SourceMgr.sloc_entry_size(); I != N; ++I) { +    // Get this source location entry. +    const SrcMgr::SLocEntry *SLoc = &SourceMgr.getSLocEntry(I); +          // Record the offset of this source-location entry.      SLocEntryOffsets.push_back(Stream.GetCurrentBitNo()); @@ -956,9 +1080,8 @@ void PCHWriter::WriteSourceManagerBlock(SourceManager &SourceMgr,        // Compute the token length for this macro expansion.        unsigned NextOffset = SourceMgr.getNextOffset(); -      SourceManager::sloc_entry_iterator NextSLoc = SLoc; -      if (++NextSLoc != SLocEnd) -        NextOffset = NextSLoc->getOffset(); +      if (I + 1 != N) +        NextOffset = SourceMgr.getSLocEntry(I + 1).getOffset();        Record.push_back(NextOffset - SLoc->getOffset() - 1);        Stream.EmitRecordWithAbbrev(SLocInstantiationAbbrv, Record);      } @@ -1019,6 +1142,7 @@ void PCHWriter::WritePreprocessor(const Preprocessor &PP) {    // Loop over all the macro definitions that are live at the end of the file,    // emitting each to the PP section. +  // FIXME: Make sure that this sees macros defined in included PCH files.    for (Preprocessor::macro_iterator I = PP.macro_begin(), E = PP.macro_end();         I != E; ++I) {      // FIXME: This emits macros in hash table order, we should do it in a stable @@ -1152,22 +1276,6 @@ void PCHWriter::WriteType(QualType T) {    FlushStmts();  } -/// \brief Write a block containing all of the types. -void PCHWriter::WriteTypesBlock(ASTContext &Context) { -  // Enter the types block. -  Stream.EnterSubblock(pch::TYPES_BLOCK_ID, 2); - -  // Emit all of the types that need to be emitted (so far). -  while (!TypesToEmit.empty()) { -    QualType T = TypesToEmit.front(); -    TypesToEmit.pop(); -    WriteType(T); -  } - -  // Exit the types block -  Stream.ExitBlock(); -} -  //===----------------------------------------------------------------------===//  // Declaration Serialization  //===----------------------------------------------------------------------===// @@ -1266,7 +1374,7 @@ public:      unsigned R = 5381;      for (unsigned I = 0; I != N; ++I)        if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(I)) -        R = clang::BernsteinHashPartial(II->getName(), II->getLength(), R); +        R = llvm::HashString(II->getName(), R);      return R;    } @@ -1475,13 +1583,13 @@ public:      : Writer(Writer), PP(PP) { }    static unsigned ComputeHash(const IdentifierInfo* II) { -    return clang::BernsteinHash(II->getName()); +    return llvm::HashString(II->getName());    }    std::pair<unsigned,unsigned>      EmitKeyDataLength(llvm::raw_ostream& Out, const IdentifierInfo* II,                        pch::IdentID ID) { -    unsigned KeyLen = strlen(II->getName()) + 1; +    unsigned KeyLen = II->getLength() + 1;      unsigned DataLen = 4; // 4 bytes for the persistent ID << 1      if (isInterestingIdentifier(II)) {        DataLen += 2; // 2 bytes for builtin ID, flags @@ -1506,7 +1614,7 @@ public:      // Record the location of the key data.  This is used when generating      // the mapping from persistent IDs to strings.      Writer.SetIdentifierOffset(II, Out.tell()); -    Out.write(II->getName(), KeyLen); +    Out.write(II->getNameStart(), KeyLen);    }    void EmitData(llvm::raw_ostream& Out, const IdentifierInfo* II, @@ -1810,7 +1918,7 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,    // The translation unit is the first declaration we'll emit.    DeclIDs[Context.getTranslationUnitDecl()] = 1; -  DeclsToEmit.push(Context.getTranslationUnitDecl()); +  DeclTypesToEmit.push(Context.getTranslationUnitDecl());    // Make sure that we emit IdentifierInfos (and any attached    // declarations) for builtins. @@ -1858,7 +1966,6 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,    if (StatCalls && !isysroot)      WriteStatCache(*StatCalls, isysroot);    WriteSourceManagerBlock(Context.getSourceManager(), PP, isysroot); -  WritePreprocessor(PP);    WriteComments(Context);    // Write the record of special types.    Record.clear(); @@ -1875,17 +1982,25 @@ void PCHWriter::WritePCH(Sema &SemaRef, MemorizeStatCalls *StatCalls,    AddTypeRef(Context.getsigjmp_bufType(), Record);    AddTypeRef(Context.ObjCIdRedefinitionType, Record);    AddTypeRef(Context.ObjCClassRedefinitionType, Record); +  AddTypeRef(Context.getRawBlockdescriptorType(), Record); +  AddTypeRef(Context.getRawBlockdescriptorExtendedType(), Record);    Stream.EmitRecord(pch::SPECIAL_TYPES, Record);    // Keep writing types and declarations until all types and    // declarations have been written. -  do { -    if (!DeclsToEmit.empty()) -      WriteDeclsBlock(Context); -    if (!TypesToEmit.empty()) -      WriteTypesBlock(Context); -  } while (!(DeclsToEmit.empty() && TypesToEmit.empty())); - +  Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3); +  WriteDeclsBlockAbbrevs(); +  while (!DeclTypesToEmit.empty()) { +    DeclOrType DOT = DeclTypesToEmit.front(); +    DeclTypesToEmit.pop(); +    if (DOT.isType()) +      WriteType(DOT.getType()); +    else +      WriteDecl(Context, DOT.getDecl()); +  } +  Stream.ExitBlock(); +   +  WritePreprocessor(PP);    WriteMethodPool(SemaRef);    WriteIdentifierTable(PP); @@ -1991,6 +2106,18 @@ void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {    Record.push_back(SID);  } +void PCHWriter::AddDeclaratorInfo(DeclaratorInfo *DInfo, RecordData &Record) { +  if (DInfo == 0) { +    AddTypeRef(QualType(), Record); +    return; +  } + +  AddTypeRef(DInfo->getType(), Record); +  TypeLocWriter TLW(*this, Record); +  for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) +    TLW.Visit(TL);   +} +  void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {    if (T.isNull()) {      Record.push_back(pch::PREDEF_TYPE_NULL_ID); @@ -2007,7 +2134,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {        // Assign it a new ID.  This is the only time we enqueue a        // qualified type, and it has no CV qualifiers.        ID = NextTypeID++; -      TypesToEmit.push(T); +      DeclTypesToEmit.push(T);      }      // Encode the type qualifiers in the type reference. @@ -2061,7 +2188,7 @@ void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {      // We haven't seen this type before. Assign it a new ID and put it      // into the queue of types to emit.      ID = NextTypeID++; -    TypesToEmit.push(T); +    DeclTypesToEmit.push(T);    }    // Encode the type qualifiers in the type reference. @@ -2079,7 +2206,7 @@ void PCHWriter::AddDeclRef(const Decl *D, RecordData &Record) {      // We haven't seen this declaration before. Give it a new ID and      // enqueue it in the list of declarations to emit.      ID = DeclIDs.size(); -    DeclsToEmit.push(const_cast<Decl *>(D)); +    DeclTypesToEmit.push(const_cast<Decl *>(D));    }    Record.push_back(ID); diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp index ef7c5ec4b1a6..fbd9929e49d7 100644 --- a/lib/Frontend/PCHWriterDecl.cpp +++ b/lib/Frontend/PCHWriterDecl.cpp @@ -14,7 +14,6 @@  #include "clang/Frontend/PCHWriter.h"  #include "clang/AST/DeclVisitor.h"  #include "clang/AST/Expr.h" -#include "clang/AST/TypeLocVisitor.h"  #include "llvm/Bitcode/BitstreamWriter.h"  #include <cstdio> @@ -88,6 +87,7 @@ void PCHDeclWriter::VisitDecl(Decl *D) {    Record.push_back(D->isImplicit());    Record.push_back(D->isUsed());    Record.push_back(D->getAccess()); +  Record.push_back(D->getPCHLevel());  }  void PCHDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { @@ -149,84 +149,10 @@ void PCHDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) {    Writer.AddAPSInt(D->getInitVal(), Record);    Code = pch::DECL_ENUM_CONSTANT;  } -namespace { - -class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> { -  PCHWriter &Writer; -  PCHWriter::RecordData &Record; - -public: -  TypeLocWriter(PCHWriter &Writer, PCHWriter::RecordData &Record) -    : Writer(Writer), Record(Record) { } - -#define ABSTRACT_TYPELOC(CLASS) -#define TYPELOC(CLASS, PARENT) \ -    void Visit##CLASS(CLASS TyLoc); -#include "clang/AST/TypeLocNodes.def" - -  void VisitTypeLoc(TypeLoc TyLoc) { -    assert(0 && "A type loc wrapper was not handled!"); -  } -}; - -} - -void TypeLocWriter::VisitQualifiedLoc(QualifiedLoc TyLoc) { -  // nothing to do here -} -void TypeLocWriter::VisitDefaultTypeSpecLoc(DefaultTypeSpecLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getStartLoc(), Record); -} -void TypeLocWriter::VisitTypedefLoc(TypedefLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getNameLoc(), Record); -} -void TypeLocWriter::VisitObjCInterfaceLoc(ObjCInterfaceLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getNameLoc(), Record); -} -void TypeLocWriter::VisitObjCProtocolListLoc(ObjCProtocolListLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getLAngleLoc(), Record); -  Writer.AddSourceLocation(TyLoc.getRAngleLoc(), Record); -  for (unsigned i = 0, e = TyLoc.getNumProtocols(); i != e; ++i) -    Writer.AddSourceLocation(TyLoc.getProtocolLoc(i), Record); -} -void TypeLocWriter::VisitPointerLoc(PointerLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getStarLoc(), Record); -} -void TypeLocWriter::VisitBlockPointerLoc(BlockPointerLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getCaretLoc(), Record); -} -void TypeLocWriter::VisitMemberPointerLoc(MemberPointerLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getStarLoc(), Record); -} -void TypeLocWriter::VisitReferenceLoc(ReferenceLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getAmpLoc(), Record); -} -void TypeLocWriter::VisitFunctionLoc(FunctionLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getLParenLoc(), Record); -  Writer.AddSourceLocation(TyLoc.getRParenLoc(), Record); -  for (unsigned i = 0, e = TyLoc.getNumArgs(); i != e; ++i) -    Writer.AddDeclRef(TyLoc.getArg(i), Record); -} -void TypeLocWriter::VisitArrayLoc(ArrayLoc TyLoc) { -  Writer.AddSourceLocation(TyLoc.getLBracketLoc(), Record); -  Writer.AddSourceLocation(TyLoc.getRBracketLoc(), Record); -  Record.push_back(TyLoc.getSizeExpr() ? 1 : 0); -  if (TyLoc.getSizeExpr()) -    Writer.AddStmt(TyLoc.getSizeExpr()); -}  void PCHDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) {    VisitValueDecl(D); -  DeclaratorInfo *DInfo = D->getDeclaratorInfo(); -  if (DInfo == 0) { -    Writer.AddTypeRef(QualType(), Record); -    return; -  } - -  Writer.AddTypeRef(DInfo->getTypeLoc().getSourceType(), Record); -  TypeLocWriter TLW(Writer, Record); -  for (TypeLoc TL = DInfo->getTypeLoc(); !TL.isNull(); TL = TL.getNextTypeLoc()) -    TLW.Visit(TL); +  Writer.AddDeclaratorInfo(D->getDeclaratorInfo(), Record);  }  void PCHDeclWriter::VisitFunctionDecl(FunctionDecl *D) { @@ -448,6 +374,7 @@ void PCHDeclWriter::VisitParmVarDecl(ParmVarDecl *D) {        !D->isImplicit() &&        !D->isUsed() &&        D->getAccess() == AS_none && +      D->getPCHLevel() == 0 &&        D->getStorageClass() == 0 &&        !D->hasCXXDirectInitializer() && // Can params have this ever?        D->getObjCDeclQualifier() == 0) @@ -523,6 +450,7 @@ void PCHWriter::WriteDeclsBlockAbbrevs() {    Abv->Add(BitCodeAbbrevOp(0));                       // isImplicit    Abv->Add(BitCodeAbbrevOp(0));                       // isUsed    Abv->Add(BitCodeAbbrevOp(AS_none));                 // C++ AccessSpecifier +  Abv->Add(BitCodeAbbrevOp(0));                       // PCH level    // NamedDecl    Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier @@ -607,80 +535,64 @@ static bool isRequiredDecl(const Decl *D, ASTContext &Context) {    }  } -/// \brief Write a block containing all of the declarations. -void PCHWriter::WriteDeclsBlock(ASTContext &Context) { -  // Enter the declarations block. -  Stream.EnterSubblock(pch::DECLS_BLOCK_ID, 3); - -  // Output the abbreviations that we will use in this block. -  WriteDeclsBlockAbbrevs(); - -  // Emit all of the declarations. +void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {    RecordData Record;    PCHDeclWriter W(*this, Context, Record); -  while (!DeclsToEmit.empty()) { -    // Pull the next declaration off the queue -    Decl *D = DeclsToEmit.front(); -    DeclsToEmit.pop(); - -    // If this declaration is also a DeclContext, write blocks for the -    // declarations that lexically stored inside its context and those -    // declarations that are visible from its context. These blocks -    // are written before the declaration itself so that we can put -    // their offsets into the record for the declaration. -    uint64_t LexicalOffset = 0; -    uint64_t VisibleOffset = 0; -    DeclContext *DC = dyn_cast<DeclContext>(D); -    if (DC) { -      LexicalOffset = WriteDeclContextLexicalBlock(Context, DC); -      VisibleOffset = WriteDeclContextVisibleBlock(Context, DC); -    } -    // Determine the ID for this declaration -    pch::DeclID &ID = DeclIDs[D]; -    if (ID == 0) -      ID = DeclIDs.size(); +  // If this declaration is also a DeclContext, write blocks for the +  // declarations that lexically stored inside its context and those +  // declarations that are visible from its context. These blocks +  // are written before the declaration itself so that we can put +  // their offsets into the record for the declaration. +  uint64_t LexicalOffset = 0; +  uint64_t VisibleOffset = 0; +  DeclContext *DC = dyn_cast<DeclContext>(D); +  if (DC) { +    LexicalOffset = WriteDeclContextLexicalBlock(Context, DC); +    VisibleOffset = WriteDeclContextVisibleBlock(Context, DC); +  } -    unsigned Index = ID - 1; +  // Determine the ID for this declaration +  pch::DeclID &ID = DeclIDs[D]; +  if (ID == 0) +    ID = DeclIDs.size(); -    // Record the offset for this declaration -    if (DeclOffsets.size() == Index) -      DeclOffsets.push_back(Stream.GetCurrentBitNo()); -    else if (DeclOffsets.size() < Index) { -      DeclOffsets.resize(Index+1); -      DeclOffsets[Index] = Stream.GetCurrentBitNo(); -    } +  unsigned Index = ID - 1; -    // Build and emit a record for this declaration -    Record.clear(); -    W.Code = (pch::DeclCode)0; -    W.AbbrevToUse = 0; -    W.Visit(D); -    if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); - -    if (!W.Code) { -      fprintf(stderr, "Cannot serialize declaration of kind %s\n", -              D->getDeclKindName()); -      assert(false && "Unhandled declaration kind while generating PCH"); -      exit(-1); -    } -    Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); +  // Record the offset for this declaration +  if (DeclOffsets.size() == Index) +    DeclOffsets.push_back(Stream.GetCurrentBitNo()); +  else if (DeclOffsets.size() < Index) { +    DeclOffsets.resize(Index+1); +    DeclOffsets[Index] = Stream.GetCurrentBitNo(); +  } -    // If the declaration had any attributes, write them now. -    if (D->hasAttrs()) -      WriteAttributeRecord(D->getAttrs()); +  // Build and emit a record for this declaration +  Record.clear(); +  W.Code = (pch::DeclCode)0; +  W.AbbrevToUse = 0; +  W.Visit(D); +  if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset); + +  if (!W.Code) { +    fprintf(stderr, "Cannot serialize declaration of kind %s\n", +            D->getDeclKindName()); +    assert(false && "Unhandled declaration kind while generating PCH"); +    exit(-1); +  } +  Stream.EmitRecord(W.Code, Record, W.AbbrevToUse); -    // Flush any expressions that were written as part of this declaration. -    FlushStmts(); +  // If the declaration had any attributes, write them now. +  if (D->hasAttrs()) +    WriteAttributeRecord(D->getAttrs()); -    // Note "external" declarations so that we can add them to a record in the -    // PCH file later. -    // -    // FIXME: This should be renamed, the predicate is much more complicated. -    if (isRequiredDecl(D, Context)) -      ExternalDefinitions.push_back(ID); -  } +  // Flush any expressions that were written as part of this declaration. +  FlushStmts(); -  // Exit the declarations block -  Stream.ExitBlock(); +  // Note "external" declarations so that we can add them to a record in the +  // PCH file later. +  // +  // FIXME: This should be renamed, the predicate is much more complicated. +  if (isRequiredDecl(D, Context)) +    ExternalDefinitions.push_back(Index + 1);  } diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 492b31a0ec39..f3cb20619ed5 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -399,7 +399,7 @@ static void PrintPreprocessedTokens(Preprocessor &PP, Token &Tok,      }      if (IdentifierInfo *II = Tok.getIdentifierInfo()) { -      OS.write(II->getName(), II->getLength()); +      OS << II->getName();      } else if (Tok.isLiteral() && !Tok.needsCleaning() &&                 Tok.getLiteralData()) {        OS.write(Tok.getLiteralData(), Tok.getLength()); @@ -434,7 +434,7 @@ namespace {    struct SortMacrosByID {      typedef std::pair<IdentifierInfo*, MacroInfo*> id_macro_pair;      bool operator()(const id_macro_pair &LHS, const id_macro_pair &RHS) const { -      return strcmp(LHS.first->getName(), RHS.first->getName()) < 0; +      return LHS.first->getName() < RHS.first->getName();      }    };  } diff --git a/lib/Frontend/RewriteMacros.cpp b/lib/Frontend/RewriteMacros.cpp index d92f5c78e690..b5d59c0aa401 100644 --- a/lib/Frontend/RewriteMacros.cpp +++ b/lib/Frontend/RewriteMacros.cpp @@ -128,13 +128,13 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) {        // comment the line out.        if (RawTokens[CurRawTok].is(tok::identifier)) {          const IdentifierInfo *II = RawTokens[CurRawTok].getIdentifierInfo(); -        if (!strcmp(II->getName(), "warning")) { +        if (II->getName() == "warning") {            // Comment out #warning.            RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//"); -        } else if (!strcmp(II->getName(), "pragma") && +        } else if (II->getName() == "pragma" &&                     RawTokens[CurRawTok+1].is(tok::identifier) && -                  !strcmp(RawTokens[CurRawTok+1].getIdentifierInfo()->getName(), -                          "mark")){ +                   (RawTokens[CurRawTok+1].getIdentifierInfo()->getName() == +                    "mark")) {            // Comment out #pragma mark.            RB.InsertTextAfter(SM.getFileOffset(RawTok.getLocation()), "//");          } diff --git a/lib/Frontend/RewriteObjC.cpp b/lib/Frontend/RewriteObjC.cpp index 55ab78e638bb..0ea0a58d5239 100644 --- a/lib/Frontend/RewriteObjC.cpp +++ b/lib/Frontend/RewriteObjC.cpp @@ -675,7 +675,7 @@ static std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl,    S = "((struct ";    S += ClassDecl->getIdentifier()->getName();    S += "_IMPL *)self)->"; -  S += OID->getNameAsCString(); +  S += OID->getName();    return S;  } @@ -2265,7 +2265,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {    if (clsName) { // class message.      // FIXME: We need to fix Sema (and the AST for ObjCMessageExpr) to handle      // the 'super' idiom within a class method. -    if (!strcmp(clsName->getName(), "super")) { +    if (clsName->getName() == "super") {        MsgSendFlavor = MsgSendSuperFunctionDecl;        if (MsgSendStretFlavor)          MsgSendStretFlavor = MsgSendSuperStretFunctionDecl; @@ -2289,9 +2289,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {        llvm::SmallVector<Expr*, 8> ClsExprs;        QualType argType = Context->getPointerType(Context->CharTy);        ClsExprs.push_back(StringLiteral::Create(*Context, -                                        SuperDecl->getIdentifier()->getName(), -                                        SuperDecl->getIdentifier()->getLength(), -                                        false, argType, SourceLocation())); +                                     SuperDecl->getIdentifier()->getNameStart(), +                                     SuperDecl->getIdentifier()->getLength(), +                                     false, argType, SourceLocation()));        CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,                                                     &ClsExprs[0],                                                     ClsExprs.size()); @@ -2343,7 +2343,7 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {        llvm::SmallVector<Expr*, 8> ClsExprs;        QualType argType = Context->getPointerType(Context->CharTy);        ClsExprs.push_back(StringLiteral::Create(*Context, -                                               clsName->getName(), +                                               clsName->getNameStart(),                                                 clsName->getLength(),                                                 false, argType,                                                 SourceLocation())); @@ -2375,9 +2375,9 @@ Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {        llvm::SmallVector<Expr*, 8> ClsExprs;        QualType argType = Context->getPointerType(Context->CharTy);        ClsExprs.push_back(StringLiteral::Create(*Context, -                                        SuperDecl->getIdentifier()->getName(), -                                        SuperDecl->getIdentifier()->getLength(), -                                        false, argType, SourceLocation())); +                                     SuperDecl->getIdentifier()->getNameStart(), +                                     SuperDecl->getIdentifier()->getLength(), +                                     false, argType, SourceLocation()));        CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,                                                     &ClsExprs[0],                                                     ClsExprs.size()); diff --git a/lib/Frontend/TextDiagnosticPrinter.cpp b/lib/Frontend/TextDiagnosticPrinter.cpp index 63d9a50b368b..14769c187393 100644 --- a/lib/Frontend/TextDiagnosticPrinter.cpp +++ b/lib/Frontend/TextDiagnosticPrinter.cpp @@ -214,6 +214,7 @@ static void SelectInterestingSourceRegion(std::string &SourceLine,      // Move the end of the interesting region right until we've      // pulled in something else interesting.      if (CaretEnd != SourceLength) { +      assert(CaretEnd < SourceLength && "Unexpected caret position!");        unsigned NewEnd = CaretEnd;        // Skip over any whitespace we see here; we're looking for @@ -320,6 +321,11 @@ void TextDiagnosticPrinter::EmitCaretDiagnostic(SourceLocation Loc,    while (*LineEnd != '\n' && *LineEnd != '\r' && *LineEnd != '\0')      ++LineEnd; +  // FIXME: This shouldn't be necessary, but the CaretEndColNo can extend past +  // the source line length as currently being computed. See +  // test/Misc/message-length.c. +  CaretEndColNo = std::min(CaretEndColNo, unsigned(LineEnd - LineStart)); +    // Copy the line of code into an std::string for ease of manipulation.    std::string SourceLine(LineStart, LineEnd); diff --git a/lib/Index/ASTLocation.cpp b/lib/Index/ASTLocation.cpp index 6294d699a88c..c24f3bf5b3c1 100644 --- a/lib/Index/ASTLocation.cpp +++ b/lib/Index/ASTLocation.cpp @@ -101,7 +101,7 @@ void ASTLocation::print(llvm::raw_ostream &OS) const {      break;    case N_Type: { -    QualType T = AsTypeLoc().getSourceType(); +    QualType T = AsTypeLoc().getType();      OS << "[Type: " << T->getTypeClassName() << " " << T.getAsString();    }    } diff --git a/lib/Index/ASTVisitor.h b/lib/Index/ASTVisitor.h index e18aa57b4d1a..0ae78fb74ff4 100644 --- a/lib/Index/ASTVisitor.h +++ b/lib/Index/ASTVisitor.h @@ -123,14 +123,14 @@ public:        BaseTypeLocVisitor::Visit(TL);    } -  void VisitArrayLoc(ArrayLoc TL) { -    BaseTypeLocVisitor::VisitArrayLoc(TL); +  void VisitArrayLoc(ArrayTypeLoc TL) { +    BaseTypeLocVisitor::VisitArrayTypeLoc(TL);      if (TL.getSizeExpr())        Visit(TL.getSizeExpr());    } -  void VisitFunctionLoc(FunctionLoc TL) { -    BaseTypeLocVisitor::VisitFunctionLoc(TL); +  void VisitFunctionTypeLoc(FunctionTypeLoc TL) { +    BaseTypeLocVisitor::VisitFunctionTypeLoc(TL);      for (unsigned i = 0; i != TL.getNumArgs(); ++i)        Visit(TL.getArg(i));    } diff --git a/lib/Index/DeclReferenceMap.cpp b/lib/Index/DeclReferenceMap.cpp index 0e48a369d5d9..366cf1b10830 100644 --- a/lib/Index/DeclReferenceMap.cpp +++ b/lib/Index/DeclReferenceMap.cpp @@ -31,8 +31,8 @@ public:    void VisitMemberExpr(MemberExpr *Node);    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node); -  void VisitTypedefLoc(TypedefLoc TL); -  void VisitObjCInterfaceLoc(ObjCInterfaceLoc TL); +  void VisitTypedefTypeLoc(TypedefTypeLoc TL); +  void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);  };  } // anonymous namespace @@ -55,12 +55,12 @@ void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {    Map.insert(std::make_pair(Node->getDecl(), ASTLocation(CurrentDecl, Node)));  } -void RefMapper::VisitTypedefLoc(TypedefLoc TL) { +void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) {    NamedDecl *ND = TL.getTypedefDecl();    Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));  } -void RefMapper::VisitObjCInterfaceLoc(ObjCInterfaceLoc TL) { +void RefMapper::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {    NamedDecl *ND = TL.getIFaceDecl();    Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc())));  } diff --git a/lib/Index/Entity.cpp b/lib/Index/Entity.cpp index 77d7a84da4db..03fe9f73af40 100644 --- a/lib/Index/Entity.cpp +++ b/lib/Index/Entity.cpp @@ -72,7 +72,8 @@ Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {    if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {      IdentifierInfo *GlobII = -        &ProgImpl.getIdents().get(II->getName(), II->getName() + II->getLength()); +      &ProgImpl.getIdents().get(II->getNameStart(), +                                II->getNameStart() + II->getLength());      GlobName = DeclarationName(GlobII);    } else {      Selector LocalSel = LocalName.getObjCSelector(); @@ -139,8 +140,9 @@ Decl *EntityImpl::getDecl(ASTContext &AST) {    DeclarationName LocalName;    if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) { -    IdentifierInfo &II = AST.Idents.get(GlobII->getName(), -                                       GlobII->getName() + GlobII->getLength()); +    IdentifierInfo &II = +      AST.Idents.get(GlobII->getNameStart(), +                     GlobII->getNameStart() + GlobII->getLength());      LocalName = DeclarationName(&II);    } else {      Selector GlobSel = Name.getObjCSelector(); diff --git a/lib/Index/GlobalSelector.cpp b/lib/Index/GlobalSelector.cpp index f3ec41d44ffe..2b2ca6d3b1cc 100644 --- a/lib/Index/GlobalSelector.cpp +++ b/lib/Index/GlobalSelector.cpp @@ -29,8 +29,9 @@ Selector GlobalSelector::getSelector(ASTContext &AST) const {    for (unsigned i = 0, e = GlobSel.isUnarySelector() ? 1 : GlobSel.getNumArgs();           i != e; ++i) {      IdentifierInfo *GlobII = GlobSel.getIdentifierInfoForSlot(i); -    IdentifierInfo *II = &AST.Idents.get(GlobII->getName(), -                                       GlobII->getName() + GlobII->getLength()); +    IdentifierInfo *II = +      &AST.Idents.get(GlobII->getNameStart(), +                      GlobII->getNameStart() + GlobII->getLength());      Ids.push_back(II);    } @@ -57,8 +58,9 @@ GlobalSelector GlobalSelector::get(Selector Sel, Program &Prog) {    for (unsigned i = 0, e = Sel.isUnarySelector() ? 1 : Sel.getNumArgs();           i != e; ++i) {      IdentifierInfo *II = Sel.getIdentifierInfoForSlot(i); -    IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName(), -                                               II->getName() + II->getLength()); +    IdentifierInfo *GlobII = +      &ProgImpl.getIdents().get(II->getNameStart(), +                                II->getNameStart() + II->getLength());      Ids.push_back(GlobII);    } diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp index 229669dc330b..8edd634f8af4 100644 --- a/lib/Index/ResolveLocation.cpp +++ b/lib/Index/ResolveLocation.cpp @@ -120,11 +120,12 @@ public:    TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)      : LocResolverBase(ctx, loc), ParentDecl(pd) { } -  ASTLocation VisitTypedefLoc(TypedefLoc TL); -  ASTLocation VisitFunctionLoc(FunctionLoc TL); -  ASTLocation VisitArrayLoc(ArrayLoc TL); -  ASTLocation VisitObjCInterfaceLoc(ObjCInterfaceLoc TL); -  ASTLocation VisitObjCProtocolListLoc(ObjCProtocolListLoc TL); +  ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL); +  ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL); +  ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL); +  ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL); +  ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL); +  ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);    ASTLocation VisitTypeLoc(TypeLoc TL);  }; @@ -349,7 +350,25 @@ ASTLocation DeclLocResolver::VisitDecl(Decl *D) {    return ASTLocation(D);  } -ASTLocation TypeLocResolver::VisitTypedefLoc(TypedefLoc TL) { +ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { +  // Continue the 'id' magic by making the builtin type (which cannot +  // actually be spelled) map to the typedef. +  BuiltinType *T = TL.getTypePtr(); +  if (T->getKind() == BuiltinType::ObjCId) { +    TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl(); +    return ASTLocation(ParentDecl, D, TL.getNameLoc()); +  } + +  // Same thing with 'Class'. +  if (T->getKind() == BuiltinType::ObjCClass) { +    TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl(); +    return ASTLocation(ParentDecl, D, TL.getNameLoc()); +  } + +  return ASTLocation(ParentDecl, TL); +} + +ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {    assert(ContainsLocation(TL) &&           "Should visit only after verifying that loc is in range");    if (ContainsLocation(TL.getNameLoc())) @@ -357,7 +376,7 @@ ASTLocation TypeLocResolver::VisitTypedefLoc(TypedefLoc TL) {    return ASTLocation(ParentDecl, TL);  } -ASTLocation TypeLocResolver::VisitFunctionLoc(FunctionLoc TL) { +ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {    assert(ContainsLocation(TL) &&           "Should visit only after verifying that loc is in range"); @@ -373,7 +392,7 @@ ASTLocation TypeLocResolver::VisitFunctionLoc(FunctionLoc TL) {    return ASTLocation(ParentDecl, TL);  } -ASTLocation TypeLocResolver::VisitArrayLoc(ArrayLoc TL) { +ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {    assert(ContainsLocation(TL) &&           "Should visit only after verifying that loc is in range"); @@ -384,17 +403,11 @@ ASTLocation TypeLocResolver::VisitArrayLoc(ArrayLoc TL) {    return ASTLocation(ParentDecl, TL);  } -ASTLocation TypeLocResolver::VisitObjCInterfaceLoc(ObjCInterfaceLoc TL) { +ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {    assert(ContainsLocation(TL) &&           "Should visit only after verifying that loc is in range");    if (ContainsLocation(TL.getNameLoc()))      return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc()); -  return ASTLocation(ParentDecl, TL); -} - -ASTLocation TypeLocResolver::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) { -  assert(ContainsLocation(TL) && -         "Should visit only after verifying that loc is in range");    for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {      SourceLocation L = TL.getProtocolLoc(i); @@ -408,6 +421,24 @@ ASTLocation TypeLocResolver::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {    return ASTLocation(ParentDecl, TL);  } +ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { +  assert(ContainsLocation(TL) && +         "Should visit only after verifying that loc is in range"); + +  if (TL.hasProtocolsAsWritten()) { +    for (unsigned i = 0; i != TL.getNumProtocols(); ++i) { +      SourceLocation L = TL.getProtocolLoc(i); +      RangePos RP = CheckRange(L); +      if (RP == AfterLoc) +        break; +      if (RP == ContainsLoc) +        return ASTLocation(ParentDecl, TL.getProtocol(i), L); +    } +  } + +  return ASTLocation(ParentDecl, TL); +} +  ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {    assert(ContainsLocation(TL) &&           "Should visit only after verifying that loc is in range"); @@ -497,9 +528,12 @@ void LocResolverBase::print(Stmt *Node) {  /// \brief Returns the AST node that a source location points to.  /// -ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc) { +ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc, +                                      Decl *RelativeToDecl) {    if (Loc.isInvalid())      return ASTLocation(); +  if (RelativeToDecl) +    return DeclLocResolver(Ctx, Loc).Visit(RelativeToDecl);        return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());  } diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index 196a77f6426a..e264efab9d7b 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -1071,7 +1071,7 @@ void Preprocessor::HandleIncludeDirective(Token &IncludeTok,    // we allow macros that expand to nothing after the filename, because this    // falls into the category of "#include pp-tokens new-line" specified in    // C99 6.10.2p4. -  CheckEndOfDirective(IncludeTok.getIdentifierInfo()->getName(), true); +  CheckEndOfDirective(IncludeTok.getIdentifierInfo()->getNameStart(), true);    // Check that we don't have infinite #include recursion.    if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) { diff --git a/lib/Lex/PTHLexer.cpp b/lib/Lex/PTHLexer.cpp index 36ace8be7e06..f17a5d93a91a 100644 --- a/lib/Lex/PTHLexer.cpp +++ b/lib/Lex/PTHLexer.cpp @@ -20,8 +20,9 @@  #include "clang/Lex/PTHManager.h"  #include "clang/Lex/Token.h"  #include "clang/Lex/Preprocessor.h" -#include "llvm/ADT/StringMap.h"  #include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h"  #include "llvm/Support/MemoryBuffer.h"  #include <sys/stat.h>  using namespace clang; @@ -95,14 +96,6 @@ LexNextToken:    //===--------------------------------------==//    // Process the token.    //===--------------------------------------==// -#if 0 -  SourceManager& SM = PP->getSourceManager(); -  llvm::errs() << SM.getFileEntryForID(FileID)->getName() -    << ':' << SM.getLogicalLineNumber(Tok.getLocation()) -    << ':' << SM.getLogicalColumnNumber(Tok.getLocation()) -    << '\n'; -#endif -    if (TKind == tok::eof) {      // Save the end-of-file token.      EofToken = Tok; @@ -308,7 +301,7 @@ public:    typedef std::pair<unsigned char, const char*> internal_key_type;    static unsigned ComputeHash(internal_key_type x) { -    return BernsteinHash(x.second); +    return llvm::HashString(x.second);    }    static std::pair<unsigned, unsigned> @@ -363,7 +356,7 @@ public:    }    static unsigned ComputeHash(const internal_key_type& a) { -    return BernsteinHash(a.first, a.second); +    return llvm::HashString(llvm::StringRef(a.first, a.second));    }    // This hopefully will just get inlined and removed by the optimizer. @@ -562,7 +555,7 @@ IdentifierInfo* PTHManager::LazilyCreateIdentifierInfo(unsigned PersistentID) {    // Store the new IdentifierInfo in the cache.    PerIDCache[PersistentID] = II; -  assert(II->getName() && II->getName()[0] != '\0'); +  assert(II->getNameStart() && II->getNameStart()[0] != '\0');    return II;  } @@ -679,7 +672,8 @@ public:      CacheTy::iterator I = Cache.find(path);      // If we don't get a hit in the PTH file just forward to 'stat'. -    if (I == Cache.end()) return ::stat(path, buf); +    if (I == Cache.end())  +      return StatSysCallCache::stat(path, buf);      const PTHStatData& Data = *I; diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index bfa090a09e87..7f3afc60764c 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -122,7 +122,7 @@ Preprocessor::~Preprocessor() {  void Preprocessor::setPTHManager(PTHManager* pm) {    PTH.reset(pm); -  FileMgr.setStatCache(PTH->createStatCache()); +  FileMgr.addStatCache(PTH->createStatCache());  }  void Preprocessor::DumpToken(const Token &Tok, bool DumpFlags) const { @@ -234,7 +234,7 @@ unsigned Preprocessor::getSpelling(const Token &Tok,    // If this token is an identifier, just return the string from the identifier    // table, which is very quick.    if (const IdentifierInfo *II = Tok.getIdentifierInfo()) { -    Buffer = II->getName(); +    Buffer = II->getNameStart();      return II->getLength();    } diff --git a/lib/Lex/TokenConcatenation.cpp b/lib/Lex/TokenConcatenation.cpp index ade7f8516ea7..07951646ffe1 100644 --- a/lib/Lex/TokenConcatenation.cpp +++ b/lib/Lex/TokenConcatenation.cpp @@ -95,7 +95,7 @@ TokenConcatenation::TokenConcatenation(Preprocessor &pp) : PP(pp) {  static char GetFirstChar(Preprocessor &PP, const Token &Tok) {    if (IdentifierInfo *II = Tok.getIdentifierInfo()) {      // Avoid spelling identifiers, the most common form of token. -    return II->getName()[0]; +    return II->getNameStart()[0];    } else if (!Tok.needsCleaning()) {      if (Tok.isLiteral() && Tok.getLiteralData()) {        return *Tok.getLiteralData(); diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 2ee41bc3eb8d..224a31cd5a5e 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -45,18 +45,15 @@ AttributeList::~AttributeList() {  }  AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { -  const char *Str = Name->getName(); -  unsigned Len = Name->getLength(); +  llvm::StringRef AttrName = Name->getName();    // Normalize the attribute name, __foo__ becomes foo. -  if (Len > 4 && Str[0] == '_' && Str[1] == '_' && -      Str[Len - 2] == '_' && Str[Len - 1] == '_') { -    Str += 2; -    Len -= 4; -  } +  if (AttrName.startswith("__") && AttrName.endswith("__")) +    AttrName = AttrName.substr(2, AttrName.size() - 4);    // FIXME: Hand generating this is neither smart nor efficient. -  switch (Len) { +  const char *Str = AttrName.data(); +  switch (AttrName.size()) {    case 4:      if (!memcmp(Str, "weak", 4)) return AT_weak;      if (!memcmp(Str, "pure", 4)) return AT_pure; diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index 72e30e3b6079..8be89a891680 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -972,13 +972,41 @@ Parser::ParsePostfixExpressionSuffix(OwningExprResult LHS) {            return ExprError();          } -        if (!LHS.isInvalid()) -          LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS), -                                                     OpLoc, OpKind, -                                                     Tok.getLocation(), -                                                     Tok.getIdentifierInfo(), -                                                     SS, -                                               NextToken().is(tok::l_paren)); +        if (NextToken().is(tok::less)) { +          // class-name:  +          //     ~ simple-template-id +          TemplateTy Template  +            = Actions.ActOnDependentTemplateName(SourceLocation(), +                                                 *Tok.getIdentifierInfo(),    +                                                 Tok.getLocation(), +                                                 SS, +                                                 ObjectType); +          if (AnnotateTemplateIdToken(Template, TNK_Type_template, &SS,  +                                      SourceLocation(), true)) +            return ExprError(); +           +          assert(Tok.is(tok::annot_typename) &&  +                 "AnnotateTemplateIdToken didn't work?"); +          if (!LHS.isInvalid()) +            LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS), +                                                       OpLoc, OpKind, +                                                       Tok.getAnnotationRange(), +                                                       Tok.getAnnotationValue(), +                                                       SS, +                                                 NextToken().is(tok::l_paren));                                                                    +        } else { +          // class-name:  +          //     ~ identifier +          if (!LHS.isInvalid()) +            LHS = Actions.ActOnDestructorReferenceExpr(CurScope, move(LHS), +                                                       OpLoc, OpKind, +                                                       Tok.getLocation(), +                                                       Tok.getIdentifierInfo(), +                                                       SS, +                                                 NextToken().is(tok::l_paren)); +        } +         +        // Consume the identifier or template-id token.          ConsumeToken();        } else if (getLang().CPlusPlus && Tok.is(tok::kw_operator)) {          // We have a reference to a member operator, e.g., t.operator int or diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 325f085a49d8..fa651569f8e1 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -356,7 +356,8 @@ Parser::OwningExprResult Parser::ParseCXXIdExpression(bool isAddressOfOperand) {                                         TemplateId->NumArgs);      OwningExprResult Result -      = Actions.ActOnTemplateIdExpr(TemplateTy::make(TemplateId->Template), +      = Actions.ActOnTemplateIdExpr(SS,  +                                    TemplateTy::make(TemplateId->Template),                                      TemplateId->TemplateNameLoc,                                      TemplateId->LAngleLoc,                                      TemplateArgsPtr, diff --git a/lib/Parse/ParseInit.cpp b/lib/Parse/ParseInit.cpp index 6ab23fd42ddc..c4e79cae3f54 100644 --- a/lib/Parse/ParseInit.cpp +++ b/lib/Parse/ParseInit.cpp @@ -15,6 +15,7 @@  #include "clang/Parse/Parser.h"  #include "clang/Parse/ParseDiagnostic.h"  #include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h"  using namespace clang; @@ -65,9 +66,9 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {    if (Tok.is(tok::identifier)) {      const IdentifierInfo *FieldName = Tok.getIdentifierInfo(); -    std::string NewSyntax("."); -    NewSyntax += FieldName->getName(); -    NewSyntax += " = "; +    llvm::SmallString<256> NewSyntax; +    llvm::raw_svector_ostream(NewSyntax) << '.' << FieldName->getName() +                                         << " = ";      SourceLocation NameLoc = ConsumeToken(); // Eat the identifier. @@ -77,7 +78,7 @@ Parser::OwningExprResult Parser::ParseInitializerWithPotentialDesignator() {      Diag(Tok, diag::ext_gnu_old_style_field_designator)        << CodeModificationHint::CreateReplacement(SourceRange(NameLoc,                                                               ColonLoc), -                                                 NewSyntax); +                                                 NewSyntax.str());      Designation D;      D.AddDesignator(Designator::getField(FieldName, SourceLocation(), NameLoc)); diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 1d29f319c584..2e0cd6d0d932 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -428,7 +428,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) {          return;        } -      if (II->getName()[0] == 's') { +      if (II->getNameStart()[0] == 's') {          DS.setPropertyAttributes(ObjCDeclSpec::DQ_PR_setter);          DS.setSetterName(Tok.getIdentifierInfo());          ConsumeToken();  // consume method name @@ -1371,8 +1371,11 @@ Parser::DeclPtrTy Parser::ParseObjCMethodDefinition() {                                          "parsing Objective-C method");    // parse optional ';' -  if (Tok.is(tok::semi)) +  if (Tok.is(tok::semi)) { +    if (ObjCImpDecl) +      Diag(Tok, diag::warn_semicolon_before_method_nody);      ConsumeToken(); +  }    // We should have an opening brace now.    if (Tok.isNot(tok::l_brace)) { diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 907ca802b4ae..272be2f66017 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -1256,6 +1256,8 @@ Parser::OwningStmtResult Parser::ParseAsmStatement(bool &msAsm) {  ///         asm-string-literal '(' expression ')'  ///         '[' identifier ']' asm-string-literal '(' expression ')'  /// +// +// FIXME: Avoid unnecessary std::string trashing.  bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,                                   llvm::SmallVectorImpl<ExprTy*> &Constraints,                                   llvm::SmallVectorImpl<ExprTy*> &Exprs) { @@ -1281,7 +1283,7 @@ bool Parser::ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names,        IdentifierInfo *II = Tok.getIdentifierInfo();        ConsumeToken(); -      Names.push_back(std::string(II->getName(), II->getLength())); +      Names.push_back(II->getName());        MatchRHSPunctuation(tok::r_square, Loc);      } else        Names.push_back(std::string()); diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 2f500a484da3..bc737e9f0c80 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -77,7 +77,10 @@ void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const {    const Preprocessor &PP = P.getPreprocessor();    Tok.getLocation().print(OS, PP.getSourceManager()); -  OS << ": current parser token '" << PP.getSpelling(Tok) << "'\n"; +  if (Tok.isAnnotation()) +    OS << ": at annotation token \n"; +  else +    OS << ": current parser token '" << PP.getSpelling(Tok) << "'\n";  } diff --git a/lib/Rewrite/RewriteRope.cpp b/lib/Rewrite/RewriteRope.cpp index 30bbcfafb532..fdb6fc385ba1 100644 --- a/lib/Rewrite/RewriteRope.cpp +++ b/lib/Rewrite/RewriteRope.cpp @@ -154,6 +154,7 @@ namespace {      ~RopePieceBTreeLeaf() {        if (PrevLeaf || NextLeaf)          removeFromLeafInOrder(); +      clear();      }      bool isFull() const { return NumPieces == 2*WidthFactor; } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index ba05a07f2654..fc9c14f456bd 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -23,44 +23,134 @@  #include "clang/Basic/TargetInfo.h"  using namespace clang; +/// Determines whether we should have an a.k.a. clause when +/// pretty-printing a type.  There are three main criteria: +/// +/// 1) Some types provide very minimal sugar that doesn't impede the +///    user's understanding --- for example, elaborated type +///    specifiers.  If this is all the sugar we see, we don't want an +///    a.k.a. clause. +/// 2) Some types are technically sugared but are much more familiar +///    when seen in their sugared form --- for example, va_list, +///    vector types, and the magic Objective C types.  We don't +///    want to desugar these, even if we do produce an a.k.a. clause. +/// 3) Some types may have already been desugared previously in this diagnostic. +///    if this is the case, doing another "aka" would just be clutter. +/// +static bool ShouldAKA(ASTContext &Context, QualType QT, +                      const Diagnostic::ArgumentValue *PrevArgs, +                      unsigned NumPrevArgs, +                      QualType &DesugaredQT) { +  QualType InputTy = QT; +   +  bool AKA = false; +  QualifierCollector Qc; + +  while (true) { +    const Type *Ty = Qc.strip(QT); + +    // Don't aka just because we saw an elaborated type... +    if (isa<ElaboratedType>(Ty)) { +      QT = cast<ElaboratedType>(Ty)->desugar(); +      continue; +    } + +    // ...or a qualified name type... +    if (isa<QualifiedNameType>(Ty)) { +      QT = cast<QualifiedNameType>(Ty)->desugar(); +      continue; +    } + +    // ...or a substituted template type parameter. +    if (isa<SubstTemplateTypeParmType>(Ty)) { +      QT = cast<SubstTemplateTypeParmType>(Ty)->desugar(); +      continue; +    } +       +    // Don't desugar template specializations.  +    if (isa<TemplateSpecializationType>(Ty)) +      break; + +    // Don't desugar magic Objective-C types. +    if (QualType(Ty,0) == Context.getObjCIdType() || +        QualType(Ty,0) == Context.getObjCClassType() || +        QualType(Ty,0) == Context.getObjCSelType() || +        QualType(Ty,0) == Context.getObjCProtoType()) +      break; + +    // Don't desugar va_list. +    if (QualType(Ty,0) == Context.getBuiltinVaListType()) +      break; + +    // Otherwise, do a single-step desugar. +    QualType Underlying; +    bool IsSugar = false; +    switch (Ty->getTypeClass()) { +#define ABSTRACT_TYPE(Class, Base) +#define TYPE(Class, Base) \ +    case Type::Class: { \ +      const Class##Type *CTy = cast<Class##Type>(Ty); \ +      if (CTy->isSugared()) { \ +        IsSugar = true; \ +        Underlying = CTy->desugar(); \ +      } \ +      break; \ +    } +#include "clang/AST/TypeNodes.def" +    } + +    // If it wasn't sugared, we're done. +    if (!IsSugar) +      break; + +    // If the desugared type is a vector type, we don't want to expand +    // it, it will turn into an attribute mess. People want their "vec4". +    if (isa<VectorType>(Underlying)) +      break; + +    // Otherwise, we're tearing through something opaque; note that +    // we'll eventually need an a.k.a. clause and keep going. +    AKA = true; +    QT = Underlying; +    continue; +  } + +  // If we never tore through opaque sugar, don't print aka. +  if (!AKA) return false; + +  // If we did, check to see if we already desugared this type in this +  // diagnostic.  If so, don't do it again. +  for (unsigned i = 0; i != NumPrevArgs; ++i) { +    // TODO: Handle ak_declcontext case. +    if (PrevArgs[i].first == Diagnostic::ak_qualtype) { +      void *Ptr = (void*)PrevArgs[i].second; +      QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); +      if (PrevTy == InputTy) +        return false; +    } +  } +   +  DesugaredQT = Qc.apply(QT); +  return true; +} +  /// \brief Convert the given type to a string suitable for printing as part of   /// a diagnostic.   ///  /// \param Context the context in which the type was allocated  /// \param Ty the type to print -static std::string ConvertTypeToDiagnosticString(ASTContext &Context, -                                                 QualType Ty) { +static std::string +ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, +                              const Diagnostic::ArgumentValue *PrevArgs, +                              unsigned NumPrevArgs) {    // FIXME: Playing with std::string is really slow.    std::string S = Ty.getAsString(Context.PrintingPolicy); -  // If this is a sugared type (like a typedef, typeof, etc), then unwrap one -  // level of the sugar so that the type is more obvious to the user. -  QualType DesugaredTy = Ty.getDesugaredType(); -   -  if (Ty != DesugaredTy && -      // If the desugared type is a vector type, we don't want to expand it, -      // it will turn into an attribute mess. People want their "vec4". -      !isa<VectorType>(DesugaredTy) && -       -      // Don't aka just because we saw an elaborated type... -      (!isa<ElaboratedType>(Ty) || -       cast<ElaboratedType>(Ty)->desugar() != DesugaredTy) && -       -      // ...or a qualified name type... -      (!isa<QualifiedNameType>(Ty) || -       cast<QualifiedNameType>(Ty)->desugar() != DesugaredTy) && -       -      // ...or a non-dependent template specialization. -      (!isa<TemplateSpecializationType>(Ty) || Ty->isDependentType()) && -       -      // Don't desugar magic Objective-C types. -      Ty.getUnqualifiedType() != Context.getObjCIdType() && -      Ty.getUnqualifiedType() != Context.getObjCClassType() && -      Ty.getUnqualifiedType() != Context.getObjCSelType() && -      Ty.getUnqualifiedType() != Context.getObjCProtoType() && -       -      // Not va_list. -      Ty.getUnqualifiedType() != Context.getBuiltinVaListType()) { +  // Consider producing an a.k.a. clause if removing all the direct +  // sugar gives us something "significantly different". + +  QualType DesugaredTy; +  if (ShouldAKA(Context, Ty, PrevArgs, NumPrevArgs, DesugaredTy)) {      S = "'"+S+"' (aka '";      S += DesugaredTy.getAsString(Context.PrintingPolicy);      S += "')"; @@ -76,21 +166,27 @@ static std::string ConvertTypeToDiagnosticString(ASTContext &Context,  static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,                                   const char *Modifier, unsigned ModLen,                                   const char *Argument, unsigned ArgLen, +                                 const Diagnostic::ArgumentValue *PrevArgs, +                                 unsigned NumPrevArgs,                                   llvm::SmallVectorImpl<char> &Output,                                   void *Cookie) {    ASTContext &Context = *static_cast<ASTContext*>(Cookie);    std::string S;    bool NeedQuotes = true; -  if (Kind == Diagnostic::ak_qualtype) { +   +  switch (Kind) { +  default: assert(0 && "unknown ArgumentKind"); +  case Diagnostic::ak_qualtype: {      assert(ModLen == 0 && ArgLen == 0 &&             "Invalid modifier for QualType argument");      QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); -    S = ConvertTypeToDiagnosticString(Context, Ty); +    S = ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs);      NeedQuotes = false; -  } else if (Kind == Diagnostic::ak_declarationname) { - +    break; +  } +  case Diagnostic::ak_declarationname: {      DeclarationName N = DeclarationName::getFromOpaqueInteger(Val);      S = N.getAsString(); @@ -101,7 +197,9 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,      else        assert(ModLen == 0 && ArgLen == 0 &&               "Invalid modifier for DeclarationName argument"); -  } else if (Kind == Diagnostic::ak_nameddecl) { +    break; +  } +  case Diagnostic::ak_nameddecl: {      bool Qualified;      if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0)        Qualified = true; @@ -110,30 +208,30 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,             "Invalid modifier for NamedDecl* argument");        Qualified = false;      } -    reinterpret_cast<NamedDecl*>(Val)->getNameForDiagnostic(S, -                                                         Context.PrintingPolicy, -                                                            Qualified); -  } else if (Kind == Diagnostic::ak_nestednamespec) { +    reinterpret_cast<NamedDecl*>(Val)-> +      getNameForDiagnostic(S, Context.PrintingPolicy, Qualified); +    break; +  } +  case Diagnostic::ak_nestednamespec: {      llvm::raw_string_ostream OS(S); -    reinterpret_cast<NestedNameSpecifier*> (Val)->print(OS, -                                                        Context.PrintingPolicy); +    reinterpret_cast<NestedNameSpecifier*>(Val)->print(OS, +                                                       Context.PrintingPolicy);      NeedQuotes = false; -  } else { -    assert(Kind == Diagnostic::ak_declcontext); +    break; +  } +  case Diagnostic::ak_declcontext: {      DeclContext *DC = reinterpret_cast<DeclContext *> (Val); -    NeedQuotes = false; -    if (!DC) { -      assert(false && "Should never have a null declaration context"); -      S = "unknown context"; -    } else if (DC->isTranslationUnit()) { +    assert(DC && "Should never have a null declaration context"); +     +    if (DC->isTranslationUnit()) {        // FIXME: Get these strings from some localized place        if (Context.getLangOptions().CPlusPlus)          S = "the global namespace";        else          S = "the global scope";      } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { -      S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type)); -      NeedQuotes = false; +      S = ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), +                                        PrevArgs, NumPrevArgs);      } else {        // FIXME: Get these strings from some localized place        NamedDecl *ND = cast<NamedDecl>(DC); @@ -147,8 +245,10 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,        S += "'";        ND->getNameForDiagnostic(S, Context.PrintingPolicy, true);        S += "'"; -      NeedQuotes = false;      } +    NeedQuotes = false; +    break; +  }    }    if (NeedQuotes) @@ -361,9 +461,8 @@ void Sema::ActOnEndOfTranslationUnit() {        // Set the length of the array to 1 (C99 6.9.2p5).        Diag(VD->getLocation(), diag::warn_tentative_incomplete_array);        llvm::APInt One(Context.getTypeSize(Context.getSizeType()), true); -      QualType T -        = Context.getConstantArrayWithoutExprType(ArrayT->getElementType(), -                                                  One, ArrayType::Normal, 0); +      QualType T = Context.getConstantArrayType(ArrayT->getElementType(), +                                                One, ArrayType::Normal, 0);        VD->setType(T);      } else if (RequireCompleteType(VD->getLocation(), VD->getType(),                                     diag::err_tentative_def_incomplete_type)) diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 80f366302171..6dd081bdc25e 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -448,7 +448,7 @@ public:    //    QualType adjustParameterType(QualType T);    QualType ConvertDeclSpecToType(const DeclSpec &DS, SourceLocation DeclLoc, -                                 bool &IsInvalid, QualType &SourceTy); +                                 bool &IsInvalid);    void ProcessTypeAttributeList(QualType &Result, const AttributeList *AL);    QualType BuildPointerType(QualType T, unsigned Quals,                              SourceLocation Loc, DeclarationName Entity); @@ -908,6 +908,7 @@ public:                             bool IsAssignmentOperator = false,                             unsigned NumContextualBoolArguments = 0);    void AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, +                                    SourceLocation OpLoc,                                      Expr **Args, unsigned NumArgs,                                      OverloadCandidateSet& CandidateSet);    void AddArgumentDependentLookupCandidates(DeclarationName Name, @@ -929,7 +930,7 @@ public:    FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,                                                     bool Complain); -  void FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn); +  Expr *FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn);    void AddOverloadedCallCandidates(NamedDecl *Callee,                                     DeclarationName &UnqualifiedName, @@ -2108,6 +2109,15 @@ public:                                 bool HasTrailingLParen);    virtual OwningExprResult +  ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, +                               SourceLocation OpLoc, +                               tok::TokenKind OpKind, +                               SourceRange TypeRange, +                               TypeTy *Type, +                               const CXXScopeSpec &SS, +                               bool HasTrailingLParen); +     +  virtual OwningExprResult    ActOnOverloadedOperatorReferenceExpr(Scope *S, ExprArg Base,                                         SourceLocation OpLoc,                                         tok::TokenKind OpKind, @@ -2343,6 +2353,10 @@ public:                                   FunctionDecl::StorageClass& SC);    DeclPtrTy ActOnConversionDeclarator(CXXConversionDecl *Conversion); +  bool isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, +                                 SourceLocation NameLoc, QualType &ThisType, +                                 QualType &MemberType); +      //===--------------------------------------------------------------------===//    // C++ Derived Classes    // @@ -2515,14 +2529,17 @@ public:                                              DeclSpec::TST TagSpec,                                              SourceLocation TagLoc); -  OwningExprResult BuildTemplateIdExpr(TemplateName Template, +  OwningExprResult BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, +                                       SourceRange QualifierRange, +                                       TemplateName Template,                                         SourceLocation TemplateNameLoc,                                         SourceLocation LAngleLoc,                                         const TemplateArgument *TemplateArgs,                                         unsigned NumTemplateArgs,                                         SourceLocation RAngleLoc); -  virtual OwningExprResult ActOnTemplateIdExpr(TemplateTy Template, +  virtual OwningExprResult ActOnTemplateIdExpr(const CXXScopeSpec &SS, +                                               TemplateTy Template,                                                 SourceLocation TemplateNameLoc,                                                 SourceLocation LAngleLoc,                                                 ASTTemplateArgsPtr TemplateArgs, @@ -3143,6 +3160,10 @@ public:    void PerformPendingImplicitInstantiations(); +  DeclaratorInfo *SubstType(DeclaratorInfo *T, +                            const MultiLevelTemplateArgumentList &TemplateArgs, +                            SourceLocation Loc, DeclarationName Entity); +    QualType SubstType(QualType T,                       const MultiLevelTemplateArgumentList &TemplateArgs,                       SourceLocation Loc, DeclarationName Entity); @@ -3197,11 +3218,13 @@ public:    void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,                                       FunctionDecl *Function, -                                     bool Recursive = false); +                                     bool Recursive = false, +                                     bool DefinitionRequired = false);    void InstantiateStaticDataMemberDefinition(                                       SourceLocation PointOfInstantiation,                                       VarDecl *Var, -                                     bool Recursive = false); +                                     bool Recursive = false, +                                     bool DefinitionRequired = false);    void InstantiateMemInitializers(CXXConstructorDecl *New,                                    const CXXConstructorDecl *Tmpl, @@ -3404,8 +3427,7 @@ public:    /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit    /// cast.  If there is already an implicit cast, merge into the existing one.    /// If isLvalue, the result of the cast is an lvalue. -  void ImpCastExprToType(Expr *&Expr, QualType Type,  -                         CastExpr::CastKind Kind = CastExpr::CK_Unknown, +  void ImpCastExprToType(Expr *&Expr, QualType Type, CastExpr::CastKind Kind,                           bool isLvalue = false);    // UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts @@ -3550,6 +3572,10 @@ public:    bool PerformImplicitConversion(Expr *&From, QualType ToType,                                   const StandardConversionSequence& SCS,                                   const char *Flavor); +   +  bool BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind, +                                 const ImplicitConversionSequence& ICS, +                                 const char *Flavor);    /// the following "Check" methods will return a valid/converted QualType    /// or a null QualType (indicating an error diagnostic was issued). @@ -3659,14 +3685,16 @@ public:    // Since vectors are an extension, there are no C standard reference for this.    // We allow casting between vectors and integer datatypes of the same size.    // returns true if the cast is invalid -  bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty); +  bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, +                       CastExpr::CastKind &Kind);    // CheckExtVectorCast - check type constraints for extended vectors.    // Since vectors are an extension, there are no C standard reference for this.    // We allow casting between vectors and integer datatypes of the same size,    // or vectors and the element type of that vector.    // returns true if the cast is invalid -  bool CheckExtVectorCast(SourceRange R, QualType VectorTy, QualType Ty); +  bool CheckExtVectorCast(SourceRange R, QualType VectorTy, Expr *&CastExpr, +                          CastExpr::CastKind &Kind);    /// CXXCheckCStyleCast - Check constraints of a C-style or function-style    /// cast under C++ semantics. @@ -3727,22 +3755,6 @@ public:                        QualType FieldTy, const Expr *BitWidth,                        bool *ZeroWidth = 0); -  /// adjustFunctionParamType - Converts the type of a function parameter to a -  // type that can be passed as an argument type to -  /// ASTContext::getFunctionType. -  /// -  /// C++ [dcl.fct]p3: "...Any cv-qualifier modifying a parameter type is -  /// deleted. Such cv-qualifiers affect only the definition of the parameter  -  /// within the body of the function; they do not affect the function type.  -  QualType adjustFunctionParamType(QualType T) const { -    if (!Context.getLangOptions().CPlusPlus) -      return T; -    return  -      T->isDependentType() ? T.getUnqualifiedType() -                            : T.getDesugaredType().getUnqualifiedType(); -     -  } -    /// \name Code completion    //@{    void setCodeCompleteConsumer(CodeCompleteConsumer *CCC); diff --git a/lib/Sema/SemaCXXCast.cpp b/lib/Sema/SemaCXXCast.cpp index 69d1f92a0832..bf396041b473 100644 --- a/lib/Sema/SemaCXXCast.cpp +++ b/lib/Sema/SemaCXXCast.cpp @@ -175,7 +175,7 @@ Sema::ActOnCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind,  /// DestType casts away constness as defined in C++ 5.2.11p8ff. This is used by  /// the cast checkers.  Both arguments must denote pointer (possibly to member)  /// types. -bool +static bool  CastsAwayConstness(Sema &Self, QualType SrcType, QualType DestType) {    // Casting away constness is defined in C++ 5.2.11p8 with reference to    // C++ 4.4. We piggyback on Sema::IsQualificationConversion for this, since @@ -605,6 +605,11 @@ TryCastResult  TryStaticDowncast(Sema &Self, QualType SrcType, QualType DestType,                    bool CStyle, const SourceRange &OpRange, QualType OrigSrcType,                    QualType OrigDestType, unsigned &msg) { +  // We can only work with complete types. But don't complain if it doesn't work +  if (Self.RequireCompleteType(OpRange.getBegin(), SrcType, PDiag(0)) || +      Self.RequireCompleteType(OpRange.getBegin(), DestType, PDiag(0))) +    return TC_NotApplicable; +    // Downcast can only happen in class hierarchies, so we need classes.    if (!DestType->isRecordType() || !SrcType->isRecordType()) {      return TC_NotApplicable; @@ -943,6 +948,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,      }      // A valid member pointer cast. +    Kind = CastExpr::CK_BitCast;      return TC_Success;    } @@ -1044,6 +1050,7 @@ static TryCastResult TryReinterpretCast(Sema &Self, Expr *SrcExpr,    // Not casting away constness, so the only remaining check is for compatible    // pointer categories. +  Kind = CastExpr::CK_BitCast;    if (SrcType->isFunctionPointerType()) {      if (DestType->isFunctionPointerType()) { @@ -1085,8 +1092,10 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,    // This test is outside everything else because it's the only case where    // a non-lvalue-reference target type does not lead to decay.    // C++ 5.2.9p4: Any expression can be explicitly converted to type "cv void". -  if (CastTy->isVoidType()) +  if (CastTy->isVoidType()) { +    Kind = CastExpr::CK_ToVoid;      return false; +  }    // If the type is dependent, we won't do any other semantic analysis now.    if (CastTy->isDependentType() || CastExpr->isTypeDependent()) @@ -1109,6 +1118,9 @@ bool Sema::CXXCheckCStyleCast(SourceRange R, QualType CastTy, Expr *&CastExpr,    unsigned msg = diag::err_bad_cxx_cast_generic;    TryCastResult tcr = TryConstCast(*this, CastExpr, CastTy, /*CStyle*/true,                                     msg); +  if (tcr == TC_Success) +    Kind = CastExpr::CK_NoOp; +    if (tcr == TC_NotApplicable) {      // ... or if that is not possible, a static_cast, ignoring const, ...      tcr = TryStaticCast(*this, CastExpr, CastTy, /*CStyle*/true, R, msg, diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 92bf83f0830d..589b0c6bd0ec 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -381,8 +381,7 @@ bool Sema::SemaBuiltinAtomicOverloaded(CallExpr *TheCall) {    // If the first type needs to be converted (e.g. void** -> int*), do it now.    if (BuiltinFT->getArgType(0) != FirstArg->getType()) { -    ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), CastExpr::CK_Unknown, -                      /*isLvalue=*/false); +    ImpCastExprToType(FirstArg, BuiltinFT->getArgType(0), CastExpr::CK_BitCast);      TheCall->setArg(0, FirstArg);    } diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 3981b8d22fa3..381151325a03 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -235,8 +235,10 @@ void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {      // Filter out names reserved for the implementation (C99 7.1.3,       // C++ [lib.global.names]). Users don't need to see those. +    // +    // FIXME: Add predicate for this.      if (Id->getLength() >= 2) { -      const char *Name = Id->getName(); +      const char *Name = Id->getNameStart();        if (Name[0] == '_' &&            (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))          return; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 606b33f5f74b..b83181becb93 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -218,7 +218,7 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,        << &II << DC << SS->getRange();    else if (isDependentScopeSpecifier(*SS)) {      Diag(SS->getRange().getBegin(), diag::err_typename_missing) -      << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()  +      << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()        << SourceRange(SS->getRange().getBegin(), IILoc)        << CodeModificationHint::CreateInsertion(SS->getRange().getBegin(),                                                 "typename "); @@ -1059,6 +1059,8 @@ void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {  /// NeverFallThrough iff we never fall off the end of the statement.  We assume  /// that functions not marked noreturn will return.  Sema::ControlFlowKind Sema::CheckFallThrough(Stmt *Root) { +  // FIXME: Eventually share this CFG object when we have other warnings based +  // of the CFG.  This can be done using AnalysisContext.    llvm::OwningPtr<CFG> cfg (CFG::buildCFG(Root, &Context));    // FIXME: They should never return 0, fix that, delete this code. @@ -1527,14 +1529,19 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,      Invalid = true;    } +  // Mock up a declarator. +  Declarator Dc(DS, Declarator::TypeNameContext); +  DeclaratorInfo *DInfo = 0; +  GetTypeForDeclarator(Dc, S, &DInfo); +  assert(DInfo && "couldn't build declarator info for anonymous struct/union"); +    // Create a declaration for this anonymous struct/union.    NamedDecl *Anon = 0;    if (RecordDecl *OwningClass = dyn_cast<RecordDecl>(Owner)) {      Anon = FieldDecl::Create(Context, OwningClass, Record->getLocation(),                               /*IdentifierInfo=*/0,                               Context.getTypeDeclType(Record), -                             // FIXME: Type source info. -                             /*DInfo=*/0, +                             DInfo,                               /*BitWidth=*/0, /*Mutable=*/false);      Anon->setAccess(AS_public);      if (getLangOptions().CPlusPlus) @@ -1561,8 +1568,7 @@ Sema::DeclPtrTy Sema::BuildAnonymousStructOrUnion(Scope *S, DeclSpec &DS,      Anon = VarDecl::Create(Context, Owner, Record->getLocation(),                             /*IdentifierInfo=*/0,                             Context.getTypeDeclType(Record), -                           // FIXME: Type source info. -                           /*DInfo=*/0, +                           DInfo,                             SC);    }    Anon->setImplicit(); @@ -1903,16 +1909,9 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T,    llvm::APSInt &Res = EvalResult.Val.getInt();    if (Res >= llvm::APSInt(Res.getBitWidth(), Res.isUnsigned())) { -    Expr* ArySizeExpr = VLATy->getSizeExpr(); -    // FIXME: here we could "steal" (how?) ArySizeExpr from the VLA, -    // so as to transfer ownership to the ConstantArrayWithExpr. -    // Alternatively, we could "clone" it (how?). -    // Since we don't know how to do things above, we just use the -    // very same Expr*. -    return Context.getConstantArrayWithExprType(VLATy->getElementType(), -                                                Res, ArySizeExpr, -                                                ArrayType::Normal, 0, -                                                VLATy->getBracketsRange()); +    // TODO: preserve the size expression in declarator info +    return Context.getConstantArrayType(VLATy->getElementType(), +                                        Res, ArrayType::Normal, 0);    }    SizeIsNegative = true; @@ -3331,7 +3330,7 @@ void Sema::AddInitializerToDecl(DeclPtrTy dcl, ExprArg init, bool DirectInit) {              << Init->getSourceRange();            VDecl->setInvalidDecl();          } else if (!VDecl->getType()->isDependentType()) -          ImpCastExprToType(Init, VDecl->getType()); +          ImpCastExprToType(Init, VDecl->getType(), CastExpr::CK_IntegralCast);        }      }    } else if (VDecl->isFileVarDecl()) { @@ -3534,10 +3533,37 @@ Sema::DeclGroupPtrTy Sema::FinalizeDeclaratorGroup(Scope *S, const DeclSpec &DS,      // Block scope. C99 6.7p7: If an identifier for an object is declared with      // no linkage (C99 6.2.2p6), the type for the object shall be complete...      if (IDecl->isBlockVarDecl() && !IDecl->hasExternalStorage()) { -      if (!IDecl->isInvalidDecl() && -          RequireCompleteType(IDecl->getLocation(), T, -                              diag::err_typecheck_decl_incomplete_type)) -        IDecl->setInvalidDecl(); +      if (T->isDependentType()) { +        // If T is dependent, we should not require a complete type. +        // (RequireCompleteType shouldn't be called with dependent types.) +        // But we still can at least check if we've got an array of unspecified +        // size without an initializer. +        if (!IDecl->isInvalidDecl() && T->isIncompleteArrayType() && +            !IDecl->getInit()) { +          Diag(IDecl->getLocation(), diag::err_typecheck_decl_incomplete_type) +            << T; +          IDecl->setInvalidDecl(); +        } +      } else if (!IDecl->isInvalidDecl()) { +        // If T is an incomplete array type with an initializer list that is +        // dependent on something, its size has not been fixed. We could attempt +        // to fix the size for such arrays, but we would still have to check +        // here for initializers containing a C++0x vararg expansion, e.g. +        // template <typename... Args> void f(Args... args) { +        //   int vals[] = { args }; +        // } +        const IncompleteArrayType *IAT = T->getAs<IncompleteArrayType>(); +        Expr *Init = IDecl->getInit(); +        if (IAT && Init && +            (Init->isTypeDependent() || Init->isValueDependent())) { +          // Check that the member type of the array is complete, at least. +          if (RequireCompleteType(IDecl->getLocation(), IAT->getElementType(), +                                  diag::err_typecheck_decl_incomplete_type)) +            IDecl->setInvalidDecl(); +        } else if (RequireCompleteType(IDecl->getLocation(), T, +                                      diag::err_typecheck_decl_incomplete_type)) +          IDecl->setInvalidDecl(); +      }      }      // File scope. C99 6.9.2p2: A declaration of an identifier for an      // object that has file scope without an initializer, and without a @@ -3707,12 +3733,13 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,      for (int i = FTI.NumArgs; i != 0; /* decrement in loop */) {        --i;        if (FTI.ArgInfo[i].Param == 0) { -        std::string Code = "  int "; -        Code += FTI.ArgInfo[i].Ident->getName(); -        Code += ";\n"; +        llvm::SmallString<256> Code; +        llvm::raw_svector_ostream(Code) << "  int " +                                        << FTI.ArgInfo[i].Ident->getName() +                                        << ";\n";          Diag(FTI.ArgInfo[i].IdentLoc, diag::ext_param_not_declared)            << FTI.ArgInfo[i].Ident -          << CodeModificationHint::CreateInsertion(LocAfterDecls, Code); +          << CodeModificationHint::CreateInsertion(LocAfterDecls, Code.str());          // Implicitly declare the argument as type 'int' for lack of a better          // type. @@ -3975,9 +4002,7 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,    }    // Extension in C99.  Legal in C90, but warn about it. -  static const unsigned int BuiltinLen = strlen("__builtin_"); -  if (II.getLength() > BuiltinLen && -      std::equal(II.getName(), II.getName() + BuiltinLen, "__builtin_")) +  if (II.getName().startswith("__builtin_"))      Diag(Loc, diag::warn_builtin_unknown) << &II;    else if (getLangOptions().C99)      Diag(Loc, diag::ext_implicit_function_decl) << &II; @@ -5587,7 +5612,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc,      // Adjust the Expr initializer and type.      if (ECD->getInitExpr())        ECD->setInitExpr(new (Context) ImplicitCastExpr(NewTy, -                                                      CastExpr::CK_Unknown, +                                                      CastExpr::CK_IntegralCast,                                                        ECD->getInitExpr(),                                                        /*isLvalue=*/false));      if (getLangOptions().CPlusPlus) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 50ebb49e7d5b..341d49ead418 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1202,6 +1202,35 @@ static void HandleFormatArgAttr(Decl *d, const AttributeList &Attr, Sema &S) {    d->addAttr(::new (S.Context) FormatArgAttr(Idx.getZExtValue()));  } +enum FormatAttrKind { +  CFStringFormat, +  NSStringFormat, +  StrftimeFormat, +  SupportedFormat, +  InvalidFormat +}; + +/// getFormatAttrKind - Map from format attribute names to supported format +/// types. +static FormatAttrKind getFormatAttrKind(llvm::StringRef Format) { +  // Check for formats that get handled specially. +  if (Format == "NSString") +    return NSStringFormat; +  if (Format == "CFString") +    return CFStringFormat; +  if (Format == "strftime") +    return StrftimeFormat; + +  // Otherwise, check for supported formats. +  if (Format == "scanf" || Format == "printf" || Format == "printf0" || +      Format == "strfmon" || Format == "cmn_err" || Format == "strftime" || +      Format == "NSString" || Format == "CFString" || Format == "vcmn_err" || +      Format == "zcmn_err") +    return SupportedFormat; + +  return InvalidFormat; +} +  /// Handle __attribute__((format(type,idx,firstarg))) attributes based on  /// http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html  static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) { @@ -1226,38 +1255,15 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {    unsigned NumArgs  = getFunctionOrMethodNumArgs(d);    unsigned FirstIdx = 1; -  const char *Format = Attr.getParameterName()->getName(); -  unsigned FormatLen = Attr.getParameterName()->getLength(); +  llvm::StringRef Format = Attr.getParameterName()->getName();    // Normalize the argument, __foo__ becomes foo. -  if (FormatLen > 4 && Format[0] == '_' && Format[1] == '_' && -      Format[FormatLen - 2] == '_' && Format[FormatLen - 1] == '_') { -    Format += 2; -    FormatLen -= 4; -  } - -  bool Supported = false; -  bool is_NSString = false; -  bool is_strftime = false; -  bool is_CFString = false; - -  switch (FormatLen) { -  default: break; -  case 5: Supported = !memcmp(Format, "scanf", 5); break; -  case 6: Supported = !memcmp(Format, "printf", 6); break; -  case 7: Supported = !memcmp(Format, "printf0", 7) || -                      !memcmp(Format, "strfmon", 7) || -                      !memcmp(Format, "cmn_err", 7); break; -  case 8: -    Supported = (is_strftime = !memcmp(Format, "strftime", 8)) || -                (is_NSString = !memcmp(Format, "NSString", 8)) || -                !memcmp(Format, "vcmn_err", 8) || -                !memcmp(Format, "zcmn_err", 8) || -                (is_CFString = !memcmp(Format, "CFString", 8)); -    break; -  } +  if (Format.startswith("__") && Format.endswith("__")) +    Format = Format.substr(2, Format.size() - 4); -  if (!Supported) { +  // Check for supported formats. +  FormatAttrKind Kind = getFormatAttrKind(Format); +  if (Kind == InvalidFormat) {      S.Diag(Attr.getLoc(), diag::warn_attribute_type_not_supported)        << "format" << Attr.getParameterName()->getName();      return; @@ -1296,13 +1302,13 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {    // make sure the format string is really a string    QualType Ty = getFunctionOrMethodArgType(d, ArgIdx); -  if (is_CFString) { +  if (Kind == CFStringFormat) {      if (!isCFStringType(Ty, S.Context)) {        S.Diag(Attr.getLoc(), diag::err_format_attribute_not)          << "a CFString" << IdxExpr->getSourceRange();        return;      } -  } else if (is_NSString) { +  } else if (Kind == NSStringFormat) {      // FIXME: do we need to check if the type is NSString*?  What are the      // semantics?      if (!isNSStringType(Ty, S.Context)) { @@ -1340,7 +1346,7 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {    // strftime requires FirstArg to be 0 because it doesn't read from any    // variable the input is just the current time + the format string. -  if (is_strftime) { +  if (Kind == StrftimeFormat) {      if (FirstArg != 0) {        S.Diag(Attr.getLoc(), diag::err_format_strftime_third_parameter)          << FirstArgExpr->getSourceRange(); @@ -1353,8 +1359,8 @@ static void HandleFormatAttr(Decl *d, const AttributeList &Attr, Sema &S) {      return;    } -  d->addAttr(::new (S.Context) FormatAttr(std::string(Format, FormatLen), -                            Idx.getZExtValue(), FirstArg.getZExtValue())); +  d->addAttr(::new (S.Context) FormatAttr(Format, Idx.getZExtValue(), +                                          FirstArg.getZExtValue()));  }  static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, @@ -1496,20 +1502,17 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {      S.Diag(Attr.getLoc(), diag::err_attribute_missing_parameter_name);      return;    } -  const char *Str = Name->getName(); -  unsigned Len = Name->getLength(); + +  llvm::StringRef Str = Attr.getParameterName()->getName();    // Normalize the attribute name, __foo__ becomes foo. -  if (Len > 4 && Str[0] == '_' && Str[1] == '_' && -      Str[Len - 2] == '_' && Str[Len - 1] == '_') { -    Str += 2; -    Len -= 4; -  } +  if (Str.startswith("__") && Str.endswith("__")) +    Str = Str.substr(2, Str.size() - 4);    unsigned DestWidth = 0;    bool IntegerMode = true;    bool ComplexMode = false; -  switch (Len) { +  switch (Str.size()) {    case 2:      switch (Str[0]) {      case 'Q': DestWidth = 8; break; @@ -1531,13 +1534,13 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) {    case 4:      // FIXME: glibc uses 'word' to define register_t; this is narrower than a      // pointer on PIC16 and other embedded platforms. -    if (!memcmp(Str, "word", 4)) +    if (Str == "word")        DestWidth = S.Context.Target.getPointerWidth(0); -    if (!memcmp(Str, "byte", 4)) +    else if (Str == "byte")        DestWidth = S.Context.Target.getCharWidth();      break;    case 7: -    if (!memcmp(Str, "pointer", 7)) +    if (Str == "pointer")        DestWidth = S.Context.Target.getPointerWidth(0);      break;    } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 419c8a13c2d4..6d1f4ea4a865 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1658,12 +1658,10 @@ namespace {        // Traverse the record, looking for methods.        if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*i)) {          // If the method is pure virtual, add it to the methods vector. -        if (MD->isPure()) { +        if (MD->isPure())            Methods.push_back(MD); -          continue; -        } -        // Otherwise, record all the overridden methods in our set. +        // Record all the overridden methods in our set.          for (CXXMethodDecl::method_iterator I = MD->begin_overridden_methods(),               E = MD->end_overridden_methods(); I != E; ++I) {            // Keep track of the overridden methods. @@ -3571,7 +3569,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,          if (DiagnoseUseOfDecl(Fn, DeclLoc))            return true; -        FixOverloadedFunctionReference(Init, Fn); +        Init = FixOverloadedFunctionReference(Init, Fn);        }        T2 = Fn->getType(); @@ -3660,7 +3658,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,    //          applicable conversion functions (13.3.1.6) and choosing    //          the best one through overload resolution (13.3)),    if (!isRValRef && !SuppressUserConversions && T2->isRecordType() && -      !RequireCompleteType(SourceLocation(), T2, 0)) { +      !RequireCompleteType(DeclLoc, T2, 0)) {      CXXRecordDecl *T2RecordDecl        = dyn_cast<CXXRecordDecl>(T2->getAs<RecordType>()->getDecl()); @@ -4283,8 +4281,7 @@ Sema::DeclPtrTy Sema::ActOnFriendTypeDecl(Scope *S,    // friend templates because ActOnTag never produces a ClassTemplateDecl    // for a TUK_Friend.    bool invalid = false; -  QualType SourceTy; -  QualType T = ConvertDeclSpecToType(DS, Loc, invalid, SourceTy); +  QualType T = ConvertDeclSpecToType(DS, Loc, invalid);    if (invalid) return DeclPtrTy();    // This is definitely an error in C++98.  It's probably meant to diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index a946500660e8..ae45429952c7 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -241,12 +241,12 @@ Expr *Sema::UsualUnaryConversions(Expr *&Expr) {    //   other types are unchanged by the integer promotions.    QualType PTy = Context.isPromotableBitField(Expr);    if (!PTy.isNull()) { -    ImpCastExprToType(Expr, PTy); +    ImpCastExprToType(Expr, PTy, CastExpr::CK_IntegralCast);      return Expr;    }    if (Ty->isPromotableIntegerType()) {      QualType PT = Context.getPromotedIntegerType(Ty); -    ImpCastExprToType(Expr, PT); +    ImpCastExprToType(Expr, PT, CastExpr::CK_IntegralCast);      return Expr;    } @@ -264,7 +264,8 @@ void Sema::DefaultArgumentPromotion(Expr *&Expr) {    // If this is a 'float' (CVR qualified or typedef) promote to double.    if (const BuiltinType *BT = Ty->getAs<BuiltinType>())      if (BT->getKind() == BuiltinType::Float) -      return ImpCastExprToType(Expr, Context.DoubleTy); +      return ImpCastExprToType(Expr, Context.DoubleTy, +                               CastExpr::CK_FloatingCast);    UsualUnaryConversions(Expr);  } @@ -330,8 +331,8 @@ QualType Sema::UsualArithmeticConversions(Expr *&lhsExpr, Expr *&rhsExpr,    QualType destType = Context.UsualArithmeticConversionsType(lhs, rhs);    if (!isCompAssign) -    ImpCastExprToType(lhsExpr, destType); -  ImpCastExprToType(rhsExpr, destType); +    ImpCastExprToType(lhsExpr, destType, CastExpr::CK_Unknown); +  ImpCastExprToType(rhsExpr, destType, CastExpr::CK_Unknown);    return destType;  } @@ -940,95 +941,31 @@ Sema::BuildDeclarationNameExpr(SourceLocation Loc, NamedDecl *D,    // We may have found a field within an anonymous union or struct    // (C++ [class.union]). +  // FIXME: This needs to happen post-isImplicitMemberReference?    if (FieldDecl *FD = dyn_cast<FieldDecl>(D))      if (cast<RecordDecl>(FD->getDeclContext())->isAnonymousStructOrUnion())        return BuildAnonymousStructUnionMemberReference(Loc, FD); -  if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext)) { -    if (!MD->isStatic()) { -      // C++ [class.mfct.nonstatic]p2: -      //   [...] if name lookup (3.4.1) resolves the name in the -      //   id-expression to a nonstatic nontype member of class X or of -      //   a base class of X, the id-expression is transformed into a -      //   class member access expression (5.2.5) using (*this) (9.3.2) -      //   as the postfix-expression to the left of the '.' operator. -      DeclContext *Ctx = 0; -      QualType MemberType; -      if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { -        Ctx = FD->getDeclContext(); -        MemberType = FD->getType(); - -        if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>()) -          MemberType = RefType->getPointeeType(); -        else if (!FD->isMutable()) -          MemberType -            = Context.getQualifiedType(MemberType, -                            Qualifiers::fromCVRMask(MD->getTypeQualifiers())); -      } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) { -        if (!Method->isStatic()) { -          Ctx = Method->getParent(); -          MemberType = Method->getType(); -        } -      } else if (FunctionTemplateDecl *FunTmpl -                   = dyn_cast<FunctionTemplateDecl>(D)) { -        if (CXXMethodDecl *Method -              = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl())) { -          if (!Method->isStatic()) { -            Ctx = Method->getParent(); -            MemberType = Context.OverloadTy; -          } -        } -      } else if (OverloadedFunctionDecl *Ovl -                   = dyn_cast<OverloadedFunctionDecl>(D)) { -        // FIXME: We need an abstraction for iterating over one or more function -        // templates or functions. This code is far too repetitive! -        for (OverloadedFunctionDecl::function_iterator -               Func = Ovl->function_begin(), -               FuncEnd = Ovl->function_end(); -             Func != FuncEnd; ++Func) { -          CXXMethodDecl *DMethod = 0; -          if (FunctionTemplateDecl *FunTmpl -                = dyn_cast<FunctionTemplateDecl>(*Func)) -            DMethod = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); -          else -            DMethod = dyn_cast<CXXMethodDecl>(*Func); - -          if (DMethod && !DMethod->isStatic()) { -            Ctx = DMethod->getDeclContext(); -            MemberType = Context.OverloadTy; -            break; -          } -        } -      } - -      if (Ctx && Ctx->isRecord()) { -        QualType CtxType = Context.getTagDeclType(cast<CXXRecordDecl>(Ctx)); -        QualType ThisType = Context.getTagDeclType(MD->getParent()); -        if ((Context.getCanonicalType(CtxType) -               == Context.getCanonicalType(ThisType)) || -            IsDerivedFrom(ThisType, CtxType)) { -          // Build the implicit member access expression. -          Expr *This = new (Context) CXXThisExpr(SourceLocation(), -                                                 MD->getThisType(Context)); -          MarkDeclarationReferenced(Loc, D); -          if (PerformObjectMemberConversion(This, D)) -            return ExprError(); - -          bool ShouldCheckUse = true; -          if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { -            // Don't diagnose the use of a virtual member function unless it's -            // explicitly qualified. -            if (MD->isVirtual() && (!SS || !SS->isSet())) -              ShouldCheckUse = false; -          } +  // Cope with an implicit member access in a C++ non-static member function. +  QualType ThisType, MemberType; +  if (isImplicitMemberReference(SS, D, Loc, ThisType, MemberType)) { +    Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); +    MarkDeclarationReferenced(Loc, D); +    if (PerformObjectMemberConversion(This, D)) +      return ExprError(); -          if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc)) -            return ExprError(); -          return Owned(BuildMemberExpr(Context, This, true, SS, D, -                                       Loc, MemberType)); -        } -      } +    bool ShouldCheckUse = true; +    if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { +      // Don't diagnose the use of a virtual member function unless it's +      // explicitly qualified. +      if (MD->isVirtual() && (!SS || !SS->isSet())) +        ShouldCheckUse = false;      } + +    if (ShouldCheckUse && DiagnoseUseOfDecl(D, Loc)) +      return ExprError(); +    return Owned(BuildMemberExpr(Context, This, true, SS, D, +                                 Loc, MemberType));    }    if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { @@ -1813,7 +1750,8 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,      // force the promotion here.      Diag(LHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<          LHSExp->getSourceRange(); -    ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy)); +    ImpCastExprToType(LHSExp, Context.getArrayDecayedType(LHSTy), +                      CastExpr::CK_ArrayToPointerDecay);      LHSTy = LHSExp->getType();      BaseExpr = LHSExp; @@ -1823,7 +1761,8 @@ Sema::ActOnArraySubscriptExpr(Scope *S, ExprArg Base, SourceLocation LLoc,      // Same as previous, except for 123[f().a] case      Diag(RHSExp->getLocStart(), diag::ext_subscript_non_lvalue) <<          RHSExp->getSourceRange(); -    ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy)); +    ImpCastExprToType(RHSExp, Context.getArrayDecayedType(RHSTy), +                      CastExpr::CK_ArrayToPointerDecay);      RHSTy = RHSExp->getType();      BaseExpr = RHSExp; @@ -1877,10 +1816,15 @@ QualType Sema::  CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,                          const IdentifierInfo *CompName,                          SourceLocation CompLoc) { +  // FIXME: Share logic with ExtVectorElementExpr::containsDuplicateElements, +  // see FIXME there. +  // +  // FIXME: This logic can be greatly simplified by splitting it along +  // halving/not halving and reworking the component checking.    const ExtVectorType *vecType = baseType->getAs<ExtVectorType>();    // The vector accessor can't exceed the number of elements. -  const char *compStr = CompName->getName(); +  const char *compStr = CompName->getNameStart();    // This flag determines whether or not the component is one of the four    // special names that indicate a subset of exactly half the elements are @@ -1917,7 +1861,7 @@ CheckExtVectorComponent(QualType baseType, SourceLocation OpLoc,    // Ensure no component accessor exceeds the width of the vector type it    // operates on.    if (!HalvingSwizzle) { -    compStr = CompName->getName(); +    compStr = CompName->getNameStart();      if (HexSwizzle)        compStr++; @@ -2042,7 +1986,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,      // is a reference to 'isa'.      if (BaseType != Context.ObjCIdRedefinitionType) {        BaseType = Context.ObjCIdRedefinitionType; -      ImpCastExprToType(BaseExpr, BaseType); +      ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);      }    }    assert(!BaseType.isNull() && "no type for member expression"); @@ -2100,7 +2044,7 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,    if (BaseType->isObjCClassType() &&        BaseType != Context.ObjCClassRedefinitionType) {      BaseType = Context.ObjCClassRedefinitionType; -    ImpCastExprToType(BaseExpr, BaseType); +    ImpCastExprToType(BaseExpr, BaseType, CastExpr::CK_BitCast);    }    // Get the type being accessed in BaseType.  If this is an arrow, the BaseExpr @@ -2184,6 +2128,12 @@ Sema::BuildMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,        // If the member name was a qualified-id, look into the        // nested-name-specifier.        DC = computeDeclContext(*SS, false); +       +      if (!isa<TypeDecl>(DC)) { +        Diag(MemberLoc, diag::err_qualified_member_nonclass) +          << DC << SS->getRange(); +        return ExprError(); +      }        // FIXME: If DC is not computable, we should build a        // CXXUnresolvedMemberExpr. @@ -3142,6 +3092,40 @@ Sema::ActOnInitList(SourceLocation LBraceLoc, MultiExprArg initlist,    return Owned(E);  } +static CastExpr::CastKind getScalarCastKind(ASTContext &Context, +                                            QualType SrcTy, QualType DestTy) { +  if (Context.getCanonicalType(SrcTy).getUnqualifiedType() == +      Context.getCanonicalType(DestTy).getUnqualifiedType()) +    return CastExpr::CK_NoOp; + +  if (SrcTy->hasPointerRepresentation()) { +    if (DestTy->hasPointerRepresentation()) +      return CastExpr::CK_BitCast; +    if (DestTy->isIntegerType()) +      return CastExpr::CK_PointerToIntegral; +  } +   +  if (SrcTy->isIntegerType()) { +    if (DestTy->isIntegerType()) +      return CastExpr::CK_IntegralCast; +    if (DestTy->hasPointerRepresentation()) +      return CastExpr::CK_IntegralToPointer; +    if (DestTy->isRealFloatingType()) +      return CastExpr::CK_IntegralToFloating; +  } +   +  if (SrcTy->isRealFloatingType()) { +    if (DestTy->isRealFloatingType()) +      return CastExpr::CK_FloatingCast; +    if (DestTy->isIntegerType()) +      return CastExpr::CK_FloatingToIntegral; +  } +   +  // FIXME: Assert here. +  // assert(false && "Unhandled cast combination!"); +  return CastExpr::CK_Unknown; +} +  /// CheckCastTypes - Check type constraints for casting between types.  bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,                            CastExpr::CastKind& Kind, @@ -3157,7 +3141,11 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,    // type needs to be scalar.    if (castType->isVoidType()) {      // Cast to void allows any expr type. -  } else if (!castType->isScalarType() && !castType->isVectorType()) { +    Kind = CastExpr::CK_ToVoid; +    return false; +  } +   +  if (!castType->isScalarType() && !castType->isVectorType()) {      if (Context.getCanonicalType(castType).getUnqualifiedType() ==          Context.getCanonicalType(castExpr->getType().getUnqualifiedType()) &&          (castType->isStructureType() || castType->isUnionType())) { @@ -3166,7 +3154,10 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,        Diag(TyR.getBegin(), diag::ext_typecheck_cast_nonscalar)          << castType << castExpr->getSourceRange();        Kind = CastExpr::CK_NoOp; -    } else if (castType->isUnionType()) { +      return false; +    } +     +    if (castType->isUnionType()) {        // GCC cast to union extension        RecordDecl *RD = castType->getAs<RecordType>()->getDecl();        RecordDecl::field_iterator Field, FieldEnd; @@ -3183,28 +3174,36 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,          return Diag(TyR.getBegin(), diag::err_typecheck_cast_to_union_no_type)            << castExpr->getType() << castExpr->getSourceRange();        Kind = CastExpr::CK_ToUnion; -    } else { -      // Reject any other conversions to non-scalar types. -      return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar) -        << castType << castExpr->getSourceRange(); +      return false;      } -  } else if (!castExpr->getType()->isScalarType() && -             !castExpr->getType()->isVectorType()) { +     +    // Reject any other conversions to non-scalar types. +    return Diag(TyR.getBegin(), diag::err_typecheck_cond_expect_scalar) +      << castType << castExpr->getSourceRange(); +  } +   +  if (!castExpr->getType()->isScalarType() &&  +      !castExpr->getType()->isVectorType()) {      return Diag(castExpr->getLocStart(),                  diag::err_typecheck_expect_scalar_operand)        << castExpr->getType() << castExpr->getSourceRange(); -  } else if (castType->isExtVectorType()) { -    if (CheckExtVectorCast(TyR, castType, castExpr->getType())) -      return true; -  } else if (castType->isVectorType()) { -    if (CheckVectorCast(TyR, castType, castExpr->getType())) -      return true; -  } else if (castExpr->getType()->isVectorType()) { -    if (CheckVectorCast(TyR, castExpr->getType(), castType)) -      return true; -  } else if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr)) { +  } +   +  if (castType->isExtVectorType())  +    return CheckExtVectorCast(TyR, castType, castExpr, Kind); +   +  if (castType->isVectorType()) +    return CheckVectorCast(TyR, castType, castExpr->getType(), Kind); +  if (castExpr->getType()->isVectorType()) +    return CheckVectorCast(TyR, castExpr->getType(), castType, Kind); + +  if (getLangOptions().ObjC1 && isa<ObjCSuperExpr>(castExpr))      return Diag(castExpr->getLocStart(), diag::err_illegal_super_cast) << TyR; -  } else if (!castType->isArithmeticType()) { +   +  if (isa<ObjCSelectorExpr>(castExpr)) +    return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr); +   +  if (!castType->isArithmeticType()) {      QualType castExprType = castExpr->getType();      if (!castExprType->isIntegralType() && castExprType->isArithmeticType())        return Diag(castExpr->getLocStart(), @@ -3216,12 +3215,13 @@ bool Sema::CheckCastTypes(SourceRange TyR, QualType castType, Expr *&castExpr,                    diag::err_cast_pointer_to_non_pointer_int)          << castType << castExpr->getSourceRange();    } -  if (isa<ObjCSelectorExpr>(castExpr)) -    return Diag(castExpr->getLocStart(), diag::err_cast_selector_expr); + +  Kind = getScalarCastKind(Context, castExpr->getType(), castType);    return false;  } -bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) { +bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, +                           CastExpr::CastKind &Kind) {    assert(VectorTy->isVectorType() && "Not a vector type!");    if (Ty->isVectorType() || Ty->isIntegerType()) { @@ -3236,18 +3236,23 @@ bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty) {                  diag::err_invalid_conversion_between_vector_and_scalar)        << VectorTy << Ty << R; +  Kind = CastExpr::CK_BitCast;    return false;  } -bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) { +bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, Expr *&CastExpr,  +                              CastExpr::CastKind &Kind) {    assert(DestTy->isExtVectorType() && "Not an extended vector type!"); - +   +  QualType SrcTy = CastExpr->getType(); +      // If SrcTy is a VectorType, the total size must match to explicitly cast to    // an ExtVectorType.    if (SrcTy->isVectorType()) {      if (Context.getTypeSize(DestTy) != Context.getTypeSize(SrcTy))        return Diag(R.getBegin(),diag::err_invalid_conversion_between_ext_vectors)          << DestTy << SrcTy << R; +    Kind = CastExpr::CK_BitCast;      return false;    } @@ -3258,6 +3263,12 @@ bool Sema::CheckExtVectorCast(SourceRange R, QualType DestTy, QualType SrcTy) {      return Diag(R.getBegin(),                  diag::err_invalid_conversion_between_vector_and_scalar)        << DestTy << SrcTy << R; + +  QualType DestElemTy = DestTy->getAs<ExtVectorType>()->getElementType(); +  ImpCastExprToType(CastExpr, DestElemTy, +                    getScalarCastKind(Context, SrcTy, DestElemTy)); +   +  Kind = CastExpr::CK_VectorSplat;    return false;  } @@ -3414,20 +3425,21 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,      if (!RHSTy->isVoidType())        Diag(LHS->getLocStart(), diag::ext_typecheck_cond_one_void)          << LHS->getSourceRange(); -    ImpCastExprToType(LHS, Context.VoidTy); -    ImpCastExprToType(RHS, Context.VoidTy); +    ImpCastExprToType(LHS, Context.VoidTy, CastExpr::CK_ToVoid); +    ImpCastExprToType(RHS, Context.VoidTy, CastExpr::CK_ToVoid);      return Context.VoidTy;    }    // C99 6.5.15p6 - "if one operand is a null pointer constant, the result has    // the type of the other operand."    if ((LHSTy->isAnyPointerType() || LHSTy->isBlockPointerType()) &&        RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { -    ImpCastExprToType(RHS, LHSTy); // promote the null to a pointer. +    // promote the null to a pointer. +    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_Unknown);      return LHSTy;    }    if ((RHSTy->isAnyPointerType() || RHSTy->isBlockPointerType()) &&        LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { -    ImpCastExprToType(LHS, RHSTy); // promote the null to a pointer. +    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_Unknown);      return RHSTy;    }    // Handle things like Class and struct objc_class*.  Here we case the result @@ -3435,23 +3447,23 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,    // redefinition type if an attempt is made to access its fields.    if (LHSTy->isObjCClassType() &&        (RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { -    ImpCastExprToType(RHS, LHSTy); +    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);      return LHSTy;    }    if (RHSTy->isObjCClassType() &&        (LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { -    ImpCastExprToType(LHS, RHSTy); +    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);      return RHSTy;    }    // And the same for struct objc_object* / id    if (LHSTy->isObjCIdType() &&        (RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { -    ImpCastExprToType(RHS, LHSTy); +    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);      return LHSTy;    }    if (RHSTy->isObjCIdType() &&        (LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { -    ImpCastExprToType(LHS, RHSTy); +    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_BitCast);      return RHSTy;    }    // Handle block pointer types. @@ -3459,8 +3471,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,      if (!LHSTy->isBlockPointerType() || !RHSTy->isBlockPointerType()) {        if (LHSTy->isVoidPointerType() || RHSTy->isVoidPointerType()) {          QualType destType = Context.getPointerType(Context.VoidTy); -        ImpCastExprToType(LHS, destType); -        ImpCastExprToType(RHS, destType); +        ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast); +        ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);          return destType;        }        Diag(QuestionLoc, diag::err_typecheck_cond_incompatible_operands) @@ -3484,13 +3496,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,        // reason, but this is what gcc does, and we do have to pick        // to get a consistent AST.        QualType incompatTy = Context.getPointerType(Context.VoidTy); -      ImpCastExprToType(LHS, incompatTy); -      ImpCastExprToType(RHS, incompatTy); +      ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast); +      ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);        return incompatTy;      }      // The block pointer types are compatible. -    ImpCastExprToType(LHS, LHSTy); -    ImpCastExprToType(RHS, LHSTy); +    ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast); +    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);      return LHSTy;    }    // Check constraints for Objective-C object pointers types. @@ -3536,13 +3548,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,          << LHSTy << RHSTy          << LHS->getSourceRange() << RHS->getSourceRange();        QualType incompatTy = Context.getObjCIdType(); -      ImpCastExprToType(LHS, incompatTy); -      ImpCastExprToType(RHS, incompatTy); +      ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast); +      ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);        return incompatTy;      }      // The object pointer types are compatible. -    ImpCastExprToType(LHS, compositeType); -    ImpCastExprToType(RHS, compositeType); +    ImpCastExprToType(LHS, compositeType, CastExpr::CK_BitCast); +    ImpCastExprToType(RHS, compositeType, CastExpr::CK_BitCast);      return compositeType;    }    // Check Objective-C object pointer types and 'void *' @@ -3552,8 +3564,10 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,      QualType destPointee        = Context.getQualifiedType(lhptee, rhptee.getQualifiers());      QualType destType = Context.getPointerType(destPointee); -    ImpCastExprToType(LHS, destType); // add qualifiers if necessary -    ImpCastExprToType(RHS, destType); // promote to void* +    // Add qualifiers if necessary. +    ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp); +    // Promote to void*. +    ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);      return destType;    }    if (LHSTy->isObjCObjectPointerType() && RHSTy->isVoidPointerType()) { @@ -3562,8 +3576,10 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,      QualType destPointee        = Context.getQualifiedType(rhptee, lhptee.getQualifiers());      QualType destType = Context.getPointerType(destPointee); -    ImpCastExprToType(RHS, destType); // add qualifiers if necessary -    ImpCastExprToType(LHS, destType); // promote to void* +    // Add qualifiers if necessary. +    ImpCastExprToType(RHS, destType, CastExpr::CK_NoOp); +    // Promote to void*. +    ImpCastExprToType(LHS, destType, CastExpr::CK_BitCast);      return destType;    }    // Check constraints for C object pointers types (C99 6.5.15p3,6). @@ -3578,16 +3594,20 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,        QualType destPointee          = Context.getQualifiedType(lhptee, rhptee.getQualifiers());        QualType destType = Context.getPointerType(destPointee); -      ImpCastExprToType(LHS, destType); // add qualifiers if necessary -      ImpCastExprToType(RHS, destType); // promote to void* +      // Add qualifiers if necessary. +      ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp); +      // Promote to void*. +      ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);        return destType;      }      if (rhptee->isVoidType() && lhptee->isIncompleteOrObjectType()) {        QualType destPointee          = Context.getQualifiedType(rhptee, lhptee.getQualifiers());        QualType destType = Context.getPointerType(destPointee); -      ImpCastExprToType(LHS, destType); // add qualifiers if necessary -      ImpCastExprToType(RHS, destType); // promote to void* +      // Add qualifiers if necessary. +      ImpCastExprToType(LHS, destType, CastExpr::CK_NoOp); +      // Promote to void*. +      ImpCastExprToType(RHS, destType, CastExpr::CK_BitCast);        return destType;      } @@ -3603,8 +3623,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,        // reason, but this is what gcc does, and we do have to pick        // to get a consistent AST.        QualType incompatTy = Context.getPointerType(Context.VoidTy); -      ImpCastExprToType(LHS, incompatTy); -      ImpCastExprToType(RHS, incompatTy); +      ImpCastExprToType(LHS, incompatTy, CastExpr::CK_BitCast); +      ImpCastExprToType(RHS, incompatTy, CastExpr::CK_BitCast);        return incompatTy;      }      // The pointer types are compatible. @@ -3614,8 +3634,8 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,      // type.      // FIXME: Need to calculate the composite type.      // FIXME: Need to add qualifiers -    ImpCastExprToType(LHS, LHSTy); -    ImpCastExprToType(RHS, LHSTy); +    ImpCastExprToType(LHS, LHSTy, CastExpr::CK_BitCast); +    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_BitCast);      return LHSTy;    } @@ -3623,13 +3643,13 @@ QualType Sema::CheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,    if (RHSTy->isPointerType() && LHSTy->isIntegerType()) {      Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)        << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); -    ImpCastExprToType(LHS, RHSTy); // promote the integer to a pointer. +    ImpCastExprToType(LHS, RHSTy, CastExpr::CK_IntegralToPointer);      return RHSTy;    }    if (LHSTy->isPointerType() && RHSTy->isIntegerType()) {      Diag(QuestionLoc, diag::warn_typecheck_cond_pointer_integer_mismatch)        << LHSTy << RHSTy << LHS->getSourceRange() << RHS->getSourceRange(); -    ImpCastExprToType(RHS, LHSTy); // promote the integer to a pointer. +    ImpCastExprToType(RHS, LHSTy, CastExpr::CK_IntegralToPointer);      return LHSTy;    } @@ -3728,16 +3748,16 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) {      // Check if the pointee types are compatible ignoring the sign.      // We explicitly check for char so that we catch "char" vs      // "unsigned char" on systems where "char" is unsigned. -    if (lhptee->isCharType()) { +    if (lhptee->isCharType())        lhptee = Context.UnsignedCharTy; -    } else if (lhptee->isSignedIntegerType()) { +    else if (lhptee->isSignedIntegerType())        lhptee = Context.getCorrespondingUnsignedType(lhptee); -    } -    if (rhptee->isCharType()) { +     +    if (rhptee->isCharType())        rhptee = Context.UnsignedCharTy; -    } else if (rhptee->isSignedIntegerType()) { +    else if (rhptee->isSignedIntegerType())        rhptee = Context.getCorrespondingUnsignedType(rhptee); -    } +      if (lhptee == rhptee) {        // Types are compatible ignoring the sign. Qualifier incompatibility        // takes priority over sign incompatibility because the sign @@ -4003,14 +4023,14 @@ Sema::CheckTransparentUnionArgumentConstraints(QualType ArgType, Expr *&rExpr) {        // 2) null pointer constant        if (FromType->isPointerType())          if (FromType->getAs<PointerType>()->getPointeeType()->isVoidType()) { -          ImpCastExprToType(rExpr, it->getType()); +          ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_BitCast);            InitField = *it;            break;          }        if (rExpr->isNullPointerConstant(Context,                                          Expr::NPC_ValueDependentIsNull)) { -        ImpCastExprToType(rExpr, it->getType()); +        ImpCastExprToType(rExpr, it->getType(), CastExpr::CK_IntegralToPointer);          InitField = *it;          break;        } @@ -4054,7 +4074,7 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {         lhsType->isBlockPointerType())        && rExpr->isNullPointerConstant(Context,                                         Expr::NPC_ValueDependentIsNull)) { -    ImpCastExprToType(rExpr, lhsType); +    ImpCastExprToType(rExpr, lhsType, CastExpr::CK_Unknown);      return Compatible;    } @@ -4077,7 +4097,8 @@ Sema::CheckSingleAssignmentConstraints(QualType lhsType, Expr *&rExpr) {    // The getNonReferenceType() call makes sure that the resulting expression    // does not have reference type.    if (result != Incompatible && rExpr->getType() != lhsType) -    ImpCastExprToType(rExpr, lhsType.getNonReferenceType()); +    ImpCastExprToType(rExpr, lhsType.getNonReferenceType(), +                      CastExpr::CK_Unknown);    return result;  } @@ -4128,7 +4149,7 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex,      QualType EltTy = LV->getElementType();      if (EltTy->isIntegralType() && rhsType->isIntegralType()) {        if (Context.getIntegerTypeOrder(EltTy, rhsType) >= 0) { -        ImpCastExprToType(rex, lhsType); +        ImpCastExprToType(rex, lhsType, CastExpr::CK_IntegralCast);          if (swapped) std::swap(rex, lex);          return lhsType;        } @@ -4136,7 +4157,7 @@ inline QualType Sema::CheckVectorOperands(SourceLocation Loc, Expr *&lex,      if (EltTy->isRealFloatingType() && rhsType->isScalarType() &&          rhsType->isRealFloatingType()) {        if (Context.getFloatingTypeOrder(EltTy, rhsType) >= 0) { -        ImpCastExprToType(rex, lhsType); +        ImpCastExprToType(rex, lhsType, CastExpr::CK_FloatingCast);          if (swapped) std::swap(rex, lex);          return lhsType;        } @@ -4416,7 +4437,7 @@ QualType Sema::CheckShiftOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,        LHSTy = Context.getPromotedIntegerType(LHSTy);    }    if (!isCompAssign) -    ImpCastExprToType(lex, LHSTy); +    ImpCastExprToType(lex, LHSTy, CastExpr::CK_IntegralCast);    UsualUnaryConversions(rex); @@ -4567,8 +4588,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,          return QualType();        } -      ImpCastExprToType(lex, T); -      ImpCastExprToType(rex, T); +      ImpCastExprToType(lex, T, CastExpr::CK_BitCast); +      ImpCastExprToType(rex, T, CastExpr::CK_BitCast);        return ResultTy;      }      // C99 6.5.9p2 and C99 6.5.8p2 @@ -4593,7 +4614,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,          << lType << rType << lex->getSourceRange() << rex->getSourceRange();      }      if (LCanPointeeTy != RCanPointeeTy) -      ImpCastExprToType(rex, lType); // promote the pointer to pointer +      ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);      return ResultTy;    } @@ -4633,8 +4654,8 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,          return QualType();        } -      ImpCastExprToType(lex, T); -      ImpCastExprToType(rex, T); +      ImpCastExprToType(lex, T, CastExpr::CK_BitCast); +      ImpCastExprToType(rex, T, CastExpr::CK_BitCast);        return ResultTy;      } @@ -4653,7 +4674,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,        Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)          << lType << rType << lex->getSourceRange() << rex->getSourceRange();      } -    ImpCastExprToType(rex, lType); // promote the pointer to pointer +    ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);      return ResultTy;    }    // Allow block pointers to be compared with null pointer constants. @@ -4668,7 +4689,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,          Diag(Loc, diag::err_typecheck_comparison_of_distinct_blocks)            << lType << rType << lex->getSourceRange() << rex->getSourceRange();      } -    ImpCastExprToType(rex, lType); // promote the pointer to pointer +    ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);      return ResultTy;    } @@ -4686,14 +4707,14 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,          Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)            << lType << rType << lex->getSourceRange() << rex->getSourceRange();        } -      ImpCastExprToType(rex, lType); +      ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);        return ResultTy;      }      if (lType->isObjCObjectPointerType() && rType->isObjCObjectPointerType()) {        if (!Context.areComparableObjCPointerTypes(lType, rType))          Diag(Loc, diag::ext_typecheck_comparison_of_distinct_pointers)            << lType << rType << lex->getSourceRange() << rex->getSourceRange(); -      ImpCastExprToType(rex, lType); +      ImpCastExprToType(rex, lType, CastExpr::CK_BitCast);        return ResultTy;      }    } @@ -4711,7 +4732,7 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,        Diag(Loc, DiagID)          << lType << rType << lex->getSourceRange() << rex->getSourceRange();      } -    ImpCastExprToType(rex, lType); // promote the integer to pointer +    ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);      return ResultTy;    }    if (lType->isIntegerType() && rType->isAnyPointerType()) { @@ -4728,18 +4749,18 @@ QualType Sema::CheckCompareOperands(Expr *&lex, Expr *&rex, SourceLocation Loc,        Diag(Loc, DiagID)          << lType << rType << lex->getSourceRange() << rex->getSourceRange();      } -    ImpCastExprToType(lex, rType); // promote the integer to pointer +    ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);      return ResultTy;    }    // Handle block pointers.    if (!isRelational && RHSIsNull        && lType->isBlockPointerType() && rType->isIntegerType()) { -    ImpCastExprToType(rex, lType); // promote the integer to pointer +    ImpCastExprToType(rex, lType, CastExpr::CK_IntegralToPointer);      return ResultTy;    }    if (!isRelational && LHSIsNull        && lType->isIntegerType() && rType->isBlockPointerType()) { -    ImpCastExprToType(lex, rType); // promote the integer to pointer +    ImpCastExprToType(lex, rType, CastExpr::CK_IntegralToPointer);      return ResultTy;    }    return InvalidOperands(Loc, lex, rex); @@ -4812,9 +4833,16 @@ inline QualType Sema::CheckLogicalOperands( // C99 6.5.[13,14]    UsualUnaryConversions(lex);    UsualUnaryConversions(rex); -  if (lex->getType()->isScalarType() && rex->getType()->isScalarType()) -    return Context.IntTy; -  return InvalidOperands(Loc, lex, rex); +  if (!lex->getType()->isScalarType() || !rex->getType()->isScalarType()) +    return InvalidOperands(Loc, lex, rex); +     +  if (Context.getLangOptions().CPlusPlus) { +    // C++ [expr.log.and]p2 +    // C++ [expr.log.or]p2 +    return Context.BoolTy; +  } + +  return Context.IntTy;  }  /// IsReadonlyProperty - Verify that otherwise a valid l-value expression diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 5f111c8a60e7..d4d031f91ed5 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -411,13 +411,15 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,        }      } -    ImpCastExprToType(ArraySize, Context.getSizeType()); +    ImpCastExprToType(ArraySize, Context.getSizeType(), +                      CastExpr::CK_IntegralCast);    }    FunctionDecl *OperatorNew = 0;    FunctionDecl *OperatorDelete = 0;    Expr **PlaceArgs = (Expr**)PlacementArgs.get();    unsigned NumPlaceArgs = PlacementArgs.size(); +        if (!AllocType->isDependentType() &&        !Expr::hasAnyTypeDependentArguments(PlaceArgs, NumPlaceArgs) &&        FindAllocationFunctions(StartLoc, @@ -448,7 +450,9 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,    Expr **ConsArgs = (Expr**)ConstructorArgs.get();    const RecordType *RT;    unsigned NumConsArgs = ConstructorArgs.size(); -  if (AllocType->isDependentType()) { +   +  if (AllocType->isDependentType() ||  +      Expr::hasAnyTypeDependentArguments(ConsArgs, NumConsArgs)) {      // Skip all the checks.    } else if ((RT = AllocType->getAs<RecordType>()) &&               !AllocType->isAggregateType()) { @@ -491,7 +495,7 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal,    }    // FIXME: Also check that the destructor is accessible. (C++ 5.3.4p16) - +      PlacementArgs.release();    ConstructorArgs.release();    ArraySizeE.release(); @@ -1043,6 +1047,40 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,    return PerformImplicitConversion(From, ToType, ICS, Flavor);  } +/// BuildCXXDerivedToBaseExpr - This routine generates the suitable AST +/// for the derived to base conversion of the expression 'From'. All +/// necessary information is passed in ICS. +bool  +Sema::BuildCXXDerivedToBaseExpr(Expr *&From, CastExpr::CastKind CastKind, +                                     const ImplicitConversionSequence& ICS, +                                     const char *Flavor) { +  QualType  BaseType =  +    QualType::getFromOpaquePtr(ICS.UserDefined.After.ToTypePtr); +  // Must do additional defined to base conversion. +  QualType  DerivedType =  +    QualType::getFromOpaquePtr(ICS.UserDefined.After.FromTypePtr); + +  From = new (Context) ImplicitCastExpr( +                                        DerivedType.getNonReferenceType(), +                                        CastKind,  +                                        From,  +                                        DerivedType->isLValueReferenceType()); +  From = new (Context) ImplicitCastExpr(BaseType.getNonReferenceType(), +                                        CastExpr::CK_DerivedToBase, From,  +                                        BaseType->isLValueReferenceType()); +  ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(*this); +  OwningExprResult FromResult = +  BuildCXXConstructExpr( +                        ICS.UserDefined.After.CopyConstructor->getLocation(), +                        BaseType, +                        ICS.UserDefined.After.CopyConstructor, +                        MultiExprArg(*this, (void **)&From, 1)); +  if (FromResult.isInvalid()) +    return true; +  From = FromResult.takeAs<Expr>(); +  return false; +} +  /// PerformImplicitConversion - Perform an implicit conversion of the  /// expression From to the type ToType using the pre-computed implicit  /// conversion sequence ICS. Returns true if there was an error, false @@ -1095,13 +1133,19 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,        if (CastArg.isInvalid())          return true; +     +      if (ICS.UserDefined.After.Second == ICK_Derived_To_Base && +          ICS.UserDefined.After.CopyConstructor) { +        From = CastArg.takeAs<Expr>(); +        return BuildCXXDerivedToBaseExpr(From, CastKind, ICS, Flavor); +      }        From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(), -                                            CastKind, CastArg.takeAs<Expr>(),  +                                            CastKind, CastArg.takeAs<Expr>(),                                              ToType->isLValueReferenceType());        return false; -    } - +  } +          case ImplicitConversionSequence::EllipsisConversion:      assert(false && "Cannot perform an ellipsis conversion");      return false; @@ -1182,8 +1226,14 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,        if (DiagnoseUseOfDecl(Fn, From->getSourceRange().getBegin()))          return true; -      FixOverloadedFunctionReference(From, Fn); +      From = FixOverloadedFunctionReference(From, Fn);        FromType = From->getType(); +         +      // If there's already an address-of operator in the expression, we have +      // the right type already, and the code below would just introduce an +      // invalid additional pointer level. +      if (FromType->isPointerType() || FromType->isMemberFunctionPointerType()) +        break;      }      FromType = Context.getPointerType(FromType);      ImpCastExprToType(From, FromType, CastExpr::CK_FunctionToPointerDecay); @@ -1205,17 +1255,33 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,      break;    case ICK_Integral_Promotion: -  case ICK_Floating_Promotion: -  case ICK_Complex_Promotion:    case ICK_Integral_Conversion: +    ImpCastExprToType(From, ToType, CastExpr::CK_IntegralCast); +    break; + +  case ICK_Floating_Promotion:    case ICK_Floating_Conversion: +    ImpCastExprToType(From, ToType, CastExpr::CK_FloatingCast); +    break; + +  case ICK_Complex_Promotion:    case ICK_Complex_Conversion: +    ImpCastExprToType(From, ToType, CastExpr::CK_Unknown); +    break; +    case ICK_Floating_Integral: +    if (ToType->isFloatingType()) +      ImpCastExprToType(From, ToType, CastExpr::CK_IntegralToFloating); +    else +      ImpCastExprToType(From, ToType, CastExpr::CK_FloatingToIntegral); +    break; +    case ICK_Complex_Real: +    ImpCastExprToType(From, ToType, CastExpr::CK_Unknown); +    break; +    case ICK_Compatible_Conversion: -      // FIXME: Go deeper to get the unqualified type! -    FromType = ToType.getUnqualifiedType(); -    ImpCastExprToType(From, FromType); +    ImpCastExprToType(From, ToType, CastExpr::CK_NoOp);      break;    case ICK_Pointer_Conversion: { @@ -1245,8 +1311,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,      break;    }    case ICK_Boolean_Conversion: -    FromType = Context.BoolTy; -    ImpCastExprToType(From, FromType); +    ImpCastExprToType(From, Context.BoolTy, CastExpr::CK_Unknown);      break;    default: @@ -1263,7 +1328,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,      // FIXME: Not sure about lvalue vs rvalue here in the presence of rvalue      // references.      ImpCastExprToType(From, ToType.getNonReferenceType(), -                      CastExpr::CK_Unknown, +                      CastExpr::CK_NoOp,                        ToType->isLValueReferenceType());      break; @@ -1465,7 +1530,7 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,                                      SourceLocation Loc) {    Expr *Args[2] = { LHS, RHS };    OverloadCandidateSet CandidateSet; -  Self.AddBuiltinOperatorCandidates(OO_Conditional, Args, 2, CandidateSet); +  Self.AddBuiltinOperatorCandidates(OO_Conditional, Loc, Args, 2, CandidateSet);    OverloadCandidateSet::iterator Best;    switch (Self.BestViableFunction(CandidateSet, Loc, Best)) { @@ -1691,12 +1756,12 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,    const MemberPointerType *RMemPtr = RTy->getAs<MemberPointerType>();    if (LMemPtr &&         RHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { -    ImpCastExprToType(RHS, LTy); +    ImpCastExprToType(RHS, LTy, CastExpr::CK_NullToMemberPointer);      return LTy;    }    if (RMemPtr &&         LHS->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { -    ImpCastExprToType(LHS, RTy); +    ImpCastExprToType(LHS, RTy, CastExpr::CK_NullToMemberPointer);      return RTy;    }    if (LMemPtr && RMemPtr) { @@ -1787,11 +1852,17 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {    //   one operand is a null pointer constant, the composite pointer type is    //   the type of the other operand.    if (E1->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { -    ImpCastExprToType(E1, T2); +    if (T2->isMemberPointerType()) +      ImpCastExprToType(E1, T2, CastExpr::CK_NullToMemberPointer); +    else +      ImpCastExprToType(E1, T2, CastExpr::CK_IntegralToPointer);      return T2;    }    if (E2->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) { -    ImpCastExprToType(E2, T1); +    if (T1->isMemberPointerType()) +      ImpCastExprToType(E2, T1, CastExpr::CK_NullToMemberPointer); +    else +      ImpCastExprToType(E2, T1, CastExpr::CK_IntegralToPointer);      return T1;    } @@ -2051,6 +2122,8 @@ Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,                                         ClassName);    else {      TypeTy *BaseTy = getTypeName(*ClassName, ClassNameLoc, S, &SS); +     +    // FIXME: If Base is dependent, we might not be able to resolve it here.      if (!BaseTy) {        Diag(ClassNameLoc, diag::err_ident_in_pseudo_dtor_not_a_type)          << ClassName; @@ -2060,25 +2133,41 @@ Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base,      BaseType = GetTypeFromParser(BaseTy);    } -  CanQualType CanBaseType = Context.getCanonicalType(BaseType); -  DeclarationName DtorName = -    Context.DeclarationNames.getCXXDestructorName(CanBaseType); +  return ActOnDestructorReferenceExpr(S, move(Base), OpLoc, OpKind, +                                      SourceRange(ClassNameLoc), +                                      BaseType.getAsOpaquePtr(), +                                      SS, HasTrailingLParen); +} +Sema::OwningExprResult +Sema::ActOnDestructorReferenceExpr(Scope *S, ExprArg Base, +                             SourceLocation OpLoc, +                             tok::TokenKind OpKind, +                             SourceRange TypeRange, +                             TypeTy *T, +                             const CXXScopeSpec &SS, +                             bool HasTrailingLParen) { +  QualType Type = QualType::getFromOpaquePtr(T); +  CanQualType CanType = Context.getCanonicalType(Type); +  DeclarationName DtorName = +    Context.DeclarationNames.getCXXDestructorName(CanType); +      OwningExprResult Result -    = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind, ClassNameLoc, -                               DtorName, DeclPtrTy(), &SS); +    = BuildMemberReferenceExpr(S, move(Base), OpLoc, OpKind,  +                               TypeRange.getBegin(), DtorName, DeclPtrTy(),  +                               &SS);    if (Result.isInvalid() || HasTrailingLParen)      return move(Result); - +      // The only way a reference to a destructor can be used is to    // immediately call them. Since the next token is not a '(', produce a    // diagnostic and build the call now.    Expr *E = (Expr *)Result.get(); -  SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(E->getLocEnd()); +  SourceLocation ExpectedLParenLoc = PP.getLocForEndOfToken(TypeRange.getEnd());    Diag(E->getLocStart(), diag::err_dtor_expr_without_call)      << isa<CXXPseudoDestructorExpr>(E)      << CodeModificationHint::CreateInsertion(ExpectedLParenLoc, "()"); - +      return ActOnCallExpr(0, move(Result), ExpectedLParenLoc,                         MultiExprArg(*this, 0, 0), 0, ExpectedLParenLoc);  } @@ -2154,9 +2243,14 @@ Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,                                  MultiExprArg(*this, (void **)&From, 1),                                  CastLoc, ConstructorArgs))        return ExprError(); -                                 -    return BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),  -                                 move_arg(ConstructorArgs)); +     +    OwningExprResult Result =  +      BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),  +                            move_arg(ConstructorArgs)); +    if (Result.isInvalid()) +      return ExprError(); +     +    return MaybeBindToTemporary(Result.takeAs<Expr>());    }    case CastExpr::CK_UserDefinedConversion: { @@ -2168,7 +2262,7 @@ Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,      // Create an implicit call expr that calls it.      CXXMemberCallExpr *CE = BuildCXXMemberCallExpr(From, Method); -    return Owned(CE); +    return MaybeBindToTemporary(CE);    }    }  }     @@ -2182,3 +2276,84 @@ Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {    return Owned(FullExpr);  } + +/// \brief Determine whether a reference to the given declaration in the  +/// current context is an implicit member access  +/// (C++ [class.mfct.non-static]p2). +/// +/// FIXME: Should Objective-C also use this approach? +/// +/// \param SS if non-NULL, the C++ nested-name-specifier that precedes the  +/// name of the declaration referenced. +/// +/// \param D the declaration being referenced from the current scope. +/// +/// \param NameLoc the location of the name in the source. +/// +/// \param ThisType if the reference to this declaration is an implicit member +/// access, will be set to the type of the "this" pointer to be used when +/// building that implicit member access. +/// +/// \param MemberType if the reference to this declaration is an implicit +/// member access, will be set to the type of the member being referenced +/// (for use at the type of the resulting member access expression). +/// +/// \returns true if this is an implicit member reference (in which case  +/// \p ThisType and \p MemberType will be set), or false if it is not an +/// implicit member reference. +bool Sema::isImplicitMemberReference(const CXXScopeSpec *SS, NamedDecl *D, +                                     SourceLocation NameLoc, QualType &ThisType, +                                     QualType &MemberType) { +  // If this isn't a C++ method, then it isn't an implicit member reference. +  CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(CurContext); +  if (!MD || MD->isStatic()) +    return false; +   +  // C++ [class.mfct.nonstatic]p2: +  //   [...] if name lookup (3.4.1) resolves the name in the +  //   id-expression to a nonstatic nontype member of class X or of +  //   a base class of X, the id-expression is transformed into a +  //   class member access expression (5.2.5) using (*this) (9.3.2) +  //   as the postfix-expression to the left of the '.' operator. +  DeclContext *Ctx = 0; +  if (FieldDecl *FD = dyn_cast<FieldDecl>(D)) { +    Ctx = FD->getDeclContext(); +    MemberType = FD->getType(); +     +    if (const ReferenceType *RefType = MemberType->getAs<ReferenceType>()) +      MemberType = RefType->getPointeeType(); +    else if (!FD->isMutable()) +      MemberType +        = Context.getQualifiedType(MemberType, +                           Qualifiers::fromCVRMask(MD->getTypeQualifiers())); +  } else { +    for (OverloadIterator Ovl(D), OvlEnd; Ovl != OvlEnd; ++Ovl) { +      CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl); +      FunctionTemplateDecl *FunTmpl = 0; +      if (!Method && (FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl))) +        Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); +       +      if (Method && !Method->isStatic()) { +        Ctx = Method->getParent(); +        if (isa<CXXMethodDecl>(D) && !FunTmpl) +          MemberType = Method->getType(); +        else +          MemberType = Context.OverloadTy; +        break; +      } +    } +  }  +   +  if (!Ctx || !Ctx->isRecord()) +    return false; +   +  // Determine whether the declaration(s) we found are actually in a base  +  // class. If not, this isn't an implicit member reference. +  ThisType = MD->getThisType(Context); +  QualType CtxType = Context.getTypeDeclType(cast<CXXRecordDecl>(Ctx)); +  QualType ClassType +    = Context.getTypeDeclType(cast<CXXRecordDecl>(MD->getParent())); +  return Context.hasSameType(CtxType, ClassType) ||  +         IsDerivedFrom(ClassType, CtxType); +} + diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index d7e4e4a67fe9..b78c10b0dd80 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -636,7 +636,11 @@ Sema::ExprResult Sema::ActOnInstanceMessage(ExprTy *receiver, Selector Sel,      // Implicitly convert integers and pointers to 'id' but emit a warning.      Diag(lbrac, diag::warn_bad_receiver_type)        << RExpr->getType() << RExpr->getSourceRange(); -    ImpCastExprToType(RExpr, Context.getObjCIdType()); +    if (ReceiverCType->isPointerType()) +      ImpCastExprToType(RExpr, Context.getObjCIdType(), CastExpr::CK_BitCast); +    else +      ImpCastExprToType(RExpr, Context.getObjCIdType(), +                        CastExpr::CK_IntegralToPointer);    } else {      // Reject other random receiver types (e.g. structs).      Diag(lbrac, diag::err_bad_receiver_type) diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 27f089680763..4746a2597e55 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -109,9 +109,9 @@ static void CheckStringInit(Expr *Str, QualType &DeclT, Sema &S) {      llvm::APSInt ConstVal(32);      ConstVal = StrLength;      // Return a new array type (C99 6.7.8p22). -    DeclT = S.Context.getConstantArrayWithoutExprType(IAT->getElementType(), -                                                      ConstVal, -                                                      ArrayType::Normal, 0); +    DeclT = S.Context.getConstantArrayType(IAT->getElementType(), +                                           ConstVal, +                                           ArrayType::Normal, 0);      return;    } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 99e7b0811c91..ebcf3ad8e2bc 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -1934,14 +1934,43 @@ Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,          return ImplicitConversionSequence::Worse;      }    } - - -  // FIXME: conversion of A::* to B::* is better than conversion of -  // A::* to C::*, - -  // FIXME: conversion of B::* to C::* is better than conversion of -  // A::* to C::*, and - +   +  // Ranking of member-pointer types. +  if (SCS1.Second == ICK_Pointer_Member && SCS2.Second == ICK_Pointer_Member && +      FromType1->isMemberPointerType() && FromType2->isMemberPointerType() && +      ToType1->isMemberPointerType() && ToType2->isMemberPointerType()) { +    const MemberPointerType * FromMemPointer1 =  +                                        FromType1->getAs<MemberPointerType>(); +    const MemberPointerType * ToMemPointer1 =  +                                          ToType1->getAs<MemberPointerType>(); +    const MemberPointerType * FromMemPointer2 =  +                                          FromType2->getAs<MemberPointerType>(); +    const MemberPointerType * ToMemPointer2 =  +                                          ToType2->getAs<MemberPointerType>(); +    const Type *FromPointeeType1 = FromMemPointer1->getClass(); +    const Type *ToPointeeType1 = ToMemPointer1->getClass(); +    const Type *FromPointeeType2 = FromMemPointer2->getClass(); +    const Type *ToPointeeType2 = ToMemPointer2->getClass(); +    QualType FromPointee1 = QualType(FromPointeeType1, 0).getUnqualifiedType(); +    QualType ToPointee1 = QualType(ToPointeeType1, 0).getUnqualifiedType(); +    QualType FromPointee2 = QualType(FromPointeeType2, 0).getUnqualifiedType(); +    QualType ToPointee2 = QualType(ToPointeeType2, 0).getUnqualifiedType(); +    // conversion of A::* to B::* is better than conversion of A::* to C::*, +    if (FromPointee1 == FromPointee2 && ToPointee1 != ToPointee2) { +      if (IsDerivedFrom(ToPointee1, ToPointee2)) +        return ImplicitConversionSequence::Worse; +      else if (IsDerivedFrom(ToPointee2, ToPointee1)) +        return ImplicitConversionSequence::Better; +    } +    // conversion of B::* to C::* is better than conversion of A::* to C::* +    if (ToPointee1 == ToPointee2 && FromPointee1 != FromPointee2) { +      if (IsDerivedFrom(FromPointee1, FromPointee2)) +        return ImplicitConversionSequence::Better; +      else if (IsDerivedFrom(FromPointee2, FromPointee1)) +        return ImplicitConversionSequence::Worse; +    } +  } +      if (SCS1.CopyConstructor && SCS2.CopyConstructor &&        SCS1.Second == ICK_Derived_To_Base) {      //   -- conversion of C to B is better than conversion of C to A, @@ -2539,6 +2568,18 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,      Candidate.Viable = false;      return;    } +   +  // We won't go through a user-define type conversion function to convert a  +  // derived to base as such conversions are given Conversion Rank. They only +  // go through a copy constructor. 13.3.3.1.2-p4 [over.ics.user] +  QualType FromCanon +    = Context.getCanonicalType(From->getType().getUnqualifiedType()); +  QualType ToCanon = Context.getCanonicalType(ToType).getUnqualifiedType(); +  if (FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon)) { +    Candidate.Viable = false; +    return; +  } +      // To determine what the conversion from the result of calling the    // conversion function to the type we're eventually trying to @@ -2551,7 +2592,7 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,    DeclRefExpr ConversionRef(Conversion, Conversion->getType(),                              SourceLocation());    ImplicitCastExpr ConversionFn(Context.getPointerType(Conversion->getType()), -                                CastExpr::CK_Unknown, +                                CastExpr::CK_FunctionToPointerDecay,                                  &ConversionRef, false);    // Note that it is safe to allocate CallExpr on the stack here because @@ -2723,7 +2764,7 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,    ArgumentDependentLookup(OpName, Args, NumArgs, Functions);    AddFunctionCandidates(Functions, Args, NumArgs, CandidateSet);    AddMemberOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet, OpRange); -  AddBuiltinOperatorCandidates(Op, Args, NumArgs, CandidateSet); +  AddBuiltinOperatorCandidates(Op, OpLoc, Args, NumArgs, CandidateSet);  }  /// \brief Add overload candidates for overloaded operators that are @@ -2873,7 +2914,8 @@ class BuiltinCandidateTypeSet  {    /// Context - The AST context in which we will build the type sets.    ASTContext &Context; -  bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty); +  bool AddPointerWithMoreQualifiedTypeVariants(QualType Ty, +                                               const Qualifiers &VisibleQuals);    bool AddMemberPointerWithMoreQualifiedTypeVariants(QualType Ty);  public: @@ -2883,8 +2925,11 @@ public:    BuiltinCandidateTypeSet(Sema &SemaRef)      : SemaRef(SemaRef), Context(SemaRef.Context) { } -  void AddTypesConvertedFrom(QualType Ty, bool AllowUserConversions, -                             bool AllowExplicitConversions); +  void AddTypesConvertedFrom(QualType Ty,  +                             SourceLocation Loc, +                             bool AllowUserConversions, +                             bool AllowExplicitConversions, +                             const Qualifiers &VisibleTypeConversionsQuals);    /// pointer_begin - First pointer type found;    iterator pointer_begin() { return PointerTypes.begin(); } @@ -2915,7 +2960,8 @@ public:  ///  /// FIXME: what to do about extended qualifiers?  bool -BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) { +BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty, +                                             const Qualifiers &VisibleQuals) {    // Insert this type.    if (!PointerTypes.insert(Ty)) @@ -2926,11 +2972,16 @@ BuiltinCandidateTypeSet::AddPointerWithMoreQualifiedTypeVariants(QualType Ty) {    QualType PointeeTy = PointerTy->getPointeeType();    unsigned BaseCVR = PointeeTy.getCVRQualifiers(); - +  bool hasVolatile = VisibleQuals.hasVolatile(); +  bool hasRestrict = VisibleQuals.hasRestrict(); +      // Iterate through all strict supersets of BaseCVR.    for (unsigned CVR = BaseCVR+1; CVR <= Qualifiers::CVRMask; ++CVR) {      if ((CVR | BaseCVR) != CVR) continue; -     +    // Skip over Volatile/Restrict if no Volatile/Restrict found anywhere +    // in the types. +    if ((CVR & Qualifiers::Volatile) && !hasVolatile) continue; +    if ((CVR & Qualifiers::Restrict) && !hasRestrict) continue;      QualType QPointeeTy = Context.getCVRQualifiedType(PointeeTy, CVR);      PointerTypes.insert(Context.getPointerType(QPointeeTy));    } @@ -2983,8 +3034,10 @@ BuiltinCandidateTypeSet::AddMemberPointerWithMoreQualifiedTypeVariants(  /// type.  void  BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty, +                                               SourceLocation Loc,                                                 bool AllowUserConversions, -                                               bool AllowExplicitConversions) { +                                               bool AllowExplicitConversions, +                                               const Qualifiers &VisibleQuals) {    // Only deal with canonical types.    Ty = Context.getCanonicalType(Ty); @@ -3001,33 +3054,8 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,      // Insert our type, and its more-qualified variants, into the set      // of types. -    if (!AddPointerWithMoreQualifiedTypeVariants(Ty)) +    if (!AddPointerWithMoreQualifiedTypeVariants(Ty, VisibleQuals))        return; - -    // Add 'cv void*' to our set of types. -    if (!Ty->isVoidType()) { -      QualType QualVoid -        = Context.getCVRQualifiedType(Context.VoidTy, -                                   PointeeTy.getCVRQualifiers()); -      AddPointerWithMoreQualifiedTypeVariants(Context.getPointerType(QualVoid)); -    } - -    // If this is a pointer to a class type, add pointers to its bases -    // (with the same level of cv-qualification as the original -    // derived class, of course). -    if (const RecordType *PointeeRec = PointeeTy->getAs<RecordType>()) { -      CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(PointeeRec->getDecl()); -      for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(); -           Base != ClassDecl->bases_end(); ++Base) { -        QualType BaseTy = Context.getCanonicalType(Base->getType()); -        BaseTy = Context.getCVRQualifiedType(BaseTy.getUnqualifiedType(), -                                          PointeeTy.getCVRQualifiers()); - -        // Add the pointer type, recursively, so that we get all of -        // the indirect base classes, too. -        AddTypesConvertedFrom(Context.getPointerType(BaseTy), false, false); -      } -    }    } else if (Ty->isMemberPointerType()) {      // Member pointers are far easier, since the pointee can't be converted.      if (!AddMemberPointerWithMoreQualifiedTypeVariants(Ty)) @@ -3036,7 +3064,7 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,      EnumerationTypes.insert(Ty);    } else if (AllowUserConversions) {      if (const RecordType *TyRec = Ty->getAs<RecordType>()) { -      if (SemaRef.RequireCompleteType(SourceLocation(), Ty, 0)) { +      if (SemaRef.RequireCompleteType(Loc, Ty, 0)) {          // No conversion functions in incomplete types.          return;        } @@ -3056,8 +3084,10 @@ BuiltinCandidateTypeSet::AddTypesConvertedFrom(QualType Ty,          if (ConvTemplate)            continue; -        if (AllowExplicitConversions || !Conv->isExplicit()) -          AddTypesConvertedFrom(Conv->getConversionType(), false, false); +        if (AllowExplicitConversions || !Conv->isExplicit()) { +          AddTypesConvertedFrom(Conv->getConversionType(), Loc, false, false,  +                                VisibleQuals); +        }        }      }    } @@ -3089,6 +3119,58 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,    }  } +/// CollectVRQualifiers - This routine returns Volatile/Restrict qualifiers +/// , if any, found in visible type conversion functions found in ArgExpr's +/// type. +static  Qualifiers CollectVRQualifiers(ASTContext &Context, Expr* ArgExpr) { +    Qualifiers VRQuals; +    const RecordType *TyRec; +    if (const MemberPointerType *RHSMPType = +        ArgExpr->getType()->getAs<MemberPointerType>()) +      TyRec = cast<RecordType>(RHSMPType->getClass()); +    else +      TyRec = ArgExpr->getType()->getAs<RecordType>(); +    if (!TyRec) { +      // Just to be safe, assume the worst case. +      VRQuals.addVolatile(); +      VRQuals.addRestrict(); +      return VRQuals; +    } +     +    CXXRecordDecl *ClassDecl = cast<CXXRecordDecl>(TyRec->getDecl()); +    OverloadedFunctionDecl *Conversions = +    ClassDecl->getVisibleConversionFunctions(); +     +    for (OverloadedFunctionDecl::function_iterator Func +         = Conversions->function_begin(); +         Func != Conversions->function_end(); ++Func) { +      if (CXXConversionDecl *Conv = dyn_cast<CXXConversionDecl>(*Func)) { +        QualType CanTy = Context.getCanonicalType(Conv->getConversionType()); +        if (const ReferenceType *ResTypeRef = CanTy->getAs<ReferenceType>()) +          CanTy = ResTypeRef->getPointeeType(); +        // Need to go down the pointer/mempointer chain and add qualifiers +        // as see them. +        bool done = false; +        while (!done) { +          if (const PointerType *ResTypePtr = CanTy->getAs<PointerType>()) +            CanTy = ResTypePtr->getPointeeType(); +          else if (const MemberPointerType *ResTypeMPtr =  +                CanTy->getAs<MemberPointerType>()) +            CanTy = ResTypeMPtr->getPointeeType(); +          else +            done = true; +          if (CanTy.isVolatileQualified()) +            VRQuals.addVolatile(); +          if (CanTy.isRestrictQualified()) +            VRQuals.addRestrict(); +          if (VRQuals.hasRestrict() && VRQuals.hasVolatile()) +            return VRQuals; +        } +      } +    } +    return VRQuals; +} +    /// AddBuiltinOperatorCandidates - Add the appropriate built-in  /// operator overloads to the candidate set (C++ [over.built]), based  /// on the operator @p Op and the arguments given. For example, if the @@ -3096,6 +3178,7 @@ static void AddBuiltinAssignmentOperatorCandidates(Sema &S,  /// operator+(int, int)" to cover integer addition.  void  Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, +                                   SourceLocation OpLoc,                                     Expr **Args, unsigned NumArgs,                                     OverloadCandidateSet& CandidateSet) {    // The set of "promoted arithmetic types", which are the arithmetic @@ -3119,10 +3202,25 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,      Context.UnsignedIntTy, Context.UnsignedLongTy, Context.UnsignedLongLongTy,      Context.FloatTy, Context.DoubleTy, Context.LongDoubleTy    }; - +  assert(ArithmeticTypes[FirstPromotedIntegralType] == Context.IntTy && +         "Invalid first promoted integral type"); +  assert(ArithmeticTypes[LastPromotedIntegralType - 1]  +           == Context.UnsignedLongLongTy && +         "Invalid last promoted integral type"); +  assert(ArithmeticTypes[FirstPromotedArithmeticType] == Context.IntTy && +         "Invalid first promoted arithmetic type"); +  assert(ArithmeticTypes[LastPromotedArithmeticType - 1]  +            == Context.LongDoubleTy && +         "Invalid last promoted arithmetic type"); +             // Find all of the types that the arguments can convert to, but only    // if the operator we're looking at has built-in operator candidates    // that make use of these types. +  Qualifiers VisibleTypeConversionsQuals; +  VisibleTypeConversionsQuals.addConst(); +  for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) +    VisibleTypeConversionsQuals += CollectVRQualifiers(Context, Args[ArgIdx]); +      BuiltinCandidateTypeSet CandidateTypes(*this);    if (Op == OO_Less || Op == OO_Greater || Op == OO_LessEqual ||        Op == OO_GreaterEqual || Op == OO_EqualEqual || Op == OO_ExclaimEqual || @@ -3132,10 +3230,12 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,        (Op == OO_Star && NumArgs == 1) || Op == OO_Conditional) {      for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx)        CandidateTypes.AddTypesConvertedFrom(Args[ArgIdx]->getType(), +                                           OpLoc,                                             true,                                             (Op == OO_Exclaim ||                                              Op == OO_AmpAmp || -                                            Op == OO_PipePipe)); +                                            Op == OO_PipePipe), +                                           VisibleTypeConversionsQuals);    }    bool isComparison = false; @@ -3202,14 +3302,17 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet);        else          AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet); - -      // Volatile version -      ParamTypes[0] -        = Context.getLValueReferenceType(Context.getVolatileType(ArithTy)); -      if (NumArgs == 1) -        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); -      else -        AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet); +      // heuristic to reduce number of builtin candidates in the set. +      // Add volatile version only if there are conversions to a volatile type. +      if (VisibleTypeConversionsQuals.hasVolatile()) { +        // Volatile version +        ParamTypes[0] +          = Context.getLValueReferenceType(Context.getVolatileType(ArithTy)); +        if (NumArgs == 1) +          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 1, CandidateSet); +        else +          AddBuiltinCandidate(ArithTy, ParamTypes, Args, 2, CandidateSet); +      }      }      // C++ [over.built]p5: @@ -3238,7 +3341,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,        else          AddBuiltinCandidate(*Ptr, ParamTypes, Args, 2, CandidateSet); -      if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) { +      if (!Context.getCanonicalType(*Ptr).isVolatileQualified() && +          VisibleTypeConversionsQuals.hasVolatile()) {          // With volatile          ParamTypes[0]            = Context.getLValueReferenceType(Context.getVolatileType(*Ptr)); @@ -3550,7 +3654,8 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet,                            /*IsAssigmentOperator=*/Op == OO_Equal); -      if (!Context.getCanonicalType(*Ptr).isVolatileQualified()) { +      if (!Context.getCanonicalType(*Ptr).isVolatileQualified() && +          VisibleTypeConversionsQuals.hasVolatile()) {          // volatile version          ParamTypes[0]            = Context.getLValueReferenceType(Context.getVolatileType(*Ptr)); @@ -3586,10 +3691,12 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,                              /*IsAssigmentOperator=*/Op == OO_Equal);          // Add this built-in operator as a candidate (VQ is 'volatile'). -        ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]); -        ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); -        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, -                            /*IsAssigmentOperator=*/Op == OO_Equal); +        if (VisibleTypeConversionsQuals.hasVolatile()) { +          ParamTypes[0] = Context.getVolatileType(ArithmeticTypes[Left]); +          ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); +          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet, +                              /*IsAssigmentOperator=*/Op == OO_Equal); +        }        }      }      break; @@ -3621,12 +3728,13 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,          // Add this built-in operator as a candidate (VQ is empty).          ParamTypes[0] = Context.getLValueReferenceType(ArithmeticTypes[Left]);          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); - -        // Add this built-in operator as a candidate (VQ is 'volatile'). -        ParamTypes[0] = ArithmeticTypes[Left]; -        ParamTypes[0] = Context.getVolatileType(ParamTypes[0]); -        ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); -        AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); +        if (VisibleTypeConversionsQuals.hasVolatile()) { +          // Add this built-in operator as a candidate (VQ is 'volatile'). +          ParamTypes[0] = ArithmeticTypes[Left]; +          ParamTypes[0] = Context.getVolatileType(ParamTypes[0]); +          ParamTypes[0] = Context.getLValueReferenceType(ParamTypes[0]); +          AddBuiltinCandidate(ParamTypes[0], ParamTypes, Args, 2, CandidateSet); +        }        }      }      break; @@ -3708,6 +3816,13 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,            C1 = QualType(Q1.strip(PointerTy->getPointeeType()), 0);            if (!isa<RecordType>(C1))              continue; +          // heuristic to reduce number of builtin candidates in the set. +          // Add volatile/restrict version only if there are conversions to a +          // volatile/restrict type. +          if (!VisibleTypeConversionsQuals.hasVolatile() && Q1.hasVolatile()) +            continue; +          if (!VisibleTypeConversionsQuals.hasRestrict() && Q1.hasRestrict()) +            continue;          }          for (BuiltinCandidateTypeSet::iterator               MemPtr = CandidateTypes.member_pointer_begin(), @@ -3721,6 +3836,12 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op,            QualType ParamTypes[2] = { *Ptr, *MemPtr };            // build CV12 T&            QualType T = mptr->getPointeeType(); +          if (!VisibleTypeConversionsQuals.hasVolatile() &&  +              T.isVolatileQualified()) +            continue; +          if (!VisibleTypeConversionsQuals.hasRestrict() &&  +              T.isRestrictQualified()) +            continue;            T = Q1.apply(T);            QualType ResultTy = Context.getLValueReferenceType(T);            AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); @@ -4061,13 +4182,20 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,        } else if (OnlyViable) {          assert(Cand->Conversions.size() <= 2 &&                  "builtin-binary-operator-not-binary"); -        if (Cand->Conversions.size() == 1) -          Diag(OpLoc, diag::err_ovl_builtin_unary_candidate) -                << Opc << Cand->BuiltinTypes.ParamTypes[0]; -        else -          Diag(OpLoc, diag::err_ovl_builtin_binary_candidate) -                << Opc << Cand->BuiltinTypes.ParamTypes[0] -                << Cand->BuiltinTypes.ParamTypes[1]; +        std::string TypeStr("operator"); +        TypeStr += Opc; +        TypeStr += "("; +        TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString(); +        if (Cand->Conversions.size() == 1) { +          TypeStr += ")"; +          Diag(OpLoc, diag::err_ovl_builtin_unary_candidate) << TypeStr; +        } +        else { +          TypeStr += ", "; +          TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString(); +          TypeStr += ")"; +          Diag(OpLoc, diag::err_ovl_builtin_binary_candidate) << TypeStr; +        }        }        else if (!Cand->Viable && !Reported) {          // Non-viability might be due to ambiguous user-defined conversions, @@ -4150,6 +4278,10 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,        OvlExpr = UnOp->getSubExpr()->IgnoreParens();    } +  bool HasExplicitTemplateArgs = false; +  const TemplateArgument *ExplicitTemplateArgs = 0; +  unsigned NumExplicitTemplateArgs = 0; +      // Try to dig out the overloaded function.    FunctionTemplateDecl *FunctionTemplate = 0;    if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(OvlExpr)) { @@ -4159,9 +4291,17 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,      Ovl = dyn_cast<OverloadedFunctionDecl>(ME->getMemberDecl());      FunctionTemplate = dyn_cast<FunctionTemplateDecl>(ME->getMemberDecl());      // FIXME: Explicit template arguments +  } else if (TemplateIdRefExpr *TIRE = dyn_cast<TemplateIdRefExpr>(OvlExpr)) { +    TemplateName Name = TIRE->getTemplateName(); +    Ovl = Name.getAsOverloadedFunctionDecl(); +    FunctionTemplate =  +      dyn_cast_or_null<FunctionTemplateDecl>(Name.getAsTemplateDecl()); +     +    HasExplicitTemplateArgs = true; +    ExplicitTemplateArgs = TIRE->getTemplateArgs(); +    NumExplicitTemplateArgs = TIRE->getNumTemplateArgs();    } -  // FIXME: TemplateIdRefExpr? - +      // If there's no overloaded function declaration or function template,    // we're done.    if (!Ovl && !FunctionTemplate) @@ -4206,8 +4346,9 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,        FunctionDecl *Specialization = 0;        TemplateDeductionInfo Info(Context);        if (TemplateDeductionResult Result -            = DeduceTemplateArguments(FunctionTemplate, /*FIXME*/false, -                                      /*FIXME:*/0, /*FIXME:*/0, +            = DeduceTemplateArguments(FunctionTemplate, HasExplicitTemplateArgs, +                                      ExplicitTemplateArgs, +                                      NumExplicitTemplateArgs,                                        FunctionType, Specialization, Info)) {          // FIXME: make a note of the failed deduction for diagnostics.          (void)Result; @@ -4240,8 +4381,11 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,    // If there were 0 or 1 matches, we're done.    if (Matches.empty())      return 0; -  else if (Matches.size() == 1) -    return *Matches.begin(); +  else if (Matches.size() == 1) { +    FunctionDecl *Result = *Matches.begin(); +    MarkDeclarationReferenced(From->getLocStart(), Result); +    return Result; +  }    // C++ [over.over]p4:    //   If more than one function is selected, [...] @@ -4257,14 +4401,17 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,      // two-pass algorithm (similar to the one used to identify the      // best viable function in an overload set) that identifies the      // best function template (if it exists). -    llvm::SmallVector<FunctionDecl *, 8> TemplateMatches(Matches.begin(),  +    llvm::SmallVector<FunctionDecl *, 8> TemplateMatches(Matches.begin(),                                                           Matches.end()); -    return getMostSpecialized(TemplateMatches.data(), TemplateMatches.size(),  -                              TPOC_Other, From->getLocStart(), -                              PDiag(), -                              PDiag(diag::err_addr_ovl_ambiguous) -                              << TemplateMatches[0]->getDeclName(),  -                              PDiag(diag::err_ovl_template_candidate)); +    FunctionDecl *Result = +        getMostSpecialized(TemplateMatches.data(), TemplateMatches.size(), +                           TPOC_Other, From->getLocStart(), +                           PDiag(), +                           PDiag(diag::err_addr_ovl_ambiguous) +                               << TemplateMatches[0]->getDeclName(), +                           PDiag(diag::err_ovl_template_candidate)); +    MarkDeclarationReferenced(From->getLocStart(), Result); +    return Result;    }    //   [...] any function template specializations in the set are @@ -4276,8 +4423,11 @@ Sema::ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,    // [...] After such eliminations, if any, there shall remain exactly one    // selected function. -  if (RemainingMatches.size() == 1) -    return RemainingMatches.front(); +  if (RemainingMatches.size() == 1) { +    FunctionDecl *Result = RemainingMatches.front(); +    MarkDeclarationReferenced(From->getLocStart(), Result); +    return Result; +  }    // FIXME: We should probably return the same thing that BestViableFunction    // returns (even if we issue the diagnostics here). @@ -4511,7 +4661,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,    AddMemberOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);    // Add builtin operator candidates. -  AddBuiltinOperatorCandidates(Op, &Args[0], NumArgs, CandidateSet); +  AddBuiltinOperatorCandidates(Op, OpLoc, &Args[0], NumArgs, CandidateSet);    // Perform overload resolution.    OverloadCandidateSet::iterator Best; @@ -4671,7 +4821,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,    AddMemberOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);    // Add builtin operator candidates. -  AddBuiltinOperatorCandidates(Op, Args, 2, CandidateSet); +  AddBuiltinOperatorCandidates(Op, OpLoc, Args, 2, CandidateSet);    // Perform overload resolution.    OverloadCandidateSet::iterator Best; @@ -4925,6 +5075,11 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,      AddMethodCandidate(cast<CXXMethodDecl>(*Oper), Object, Args, NumArgs,                         CandidateSet, /*SuppressUserConversions=*/false); +  if (RequireCompleteType(LParenLoc, Object->getType(),  +                          PartialDiagnostic(diag::err_incomplete_object_call) +                            << Object->getSourceRange())) +    return true; +      // C++ [over.call.object]p2:    //   In addition, for each conversion function declared in T of the    //   form @@ -4942,33 +5097,30 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,    //   functions for each conversion function declared in an    //   accessible base class provided the function is not hidden    //   within T by another intervening declaration. +  // FIXME: Look in base classes for more conversion operators! +  OverloadedFunctionDecl *Conversions +    = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions(); +  for (OverloadedFunctionDecl::function_iterator +         Func = Conversions->function_begin(), +         FuncEnd = Conversions->function_end(); +       Func != FuncEnd; ++Func) { +    CXXConversionDecl *Conv; +    FunctionTemplateDecl *ConvTemplate; +    GetFunctionAndTemplate(*Func, Conv, ConvTemplate); -  if (!RequireCompleteType(SourceLocation(), Object->getType(), 0)) { -    // FIXME: Look in base classes for more conversion operators! -    OverloadedFunctionDecl *Conversions -      = cast<CXXRecordDecl>(Record->getDecl())->getConversionFunctions(); -    for (OverloadedFunctionDecl::function_iterator -           Func = Conversions->function_begin(), -           FuncEnd = Conversions->function_end(); -         Func != FuncEnd; ++Func) { -      CXXConversionDecl *Conv; -      FunctionTemplateDecl *ConvTemplate; -      GetFunctionAndTemplate(*Func, Conv, ConvTemplate); - -      // Skip over templated conversion functions; they aren't -      // surrogates. -      if (ConvTemplate) -        continue; +    // Skip over templated conversion functions; they aren't +    // surrogates. +    if (ConvTemplate) +      continue; -      // Strip the reference type (if any) and then the pointer type (if -      // any) to get down to what might be a function type. -      QualType ConvType = Conv->getConversionType().getNonReferenceType(); -      if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) -        ConvType = ConvPtrType->getPointeeType(); +    // Strip the reference type (if any) and then the pointer type (if +    // any) to get down to what might be a function type. +    QualType ConvType = Conv->getConversionType().getNonReferenceType(); +    if (const PointerType *ConvPtrType = ConvType->getAs<PointerType>()) +      ConvType = ConvPtrType->getPointeeType(); -      if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>()) -        AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet); -    } +    if (const FunctionProtoType *Proto = ConvType->getAs<FunctionProtoType>()) +      AddSurrogateCandidate(Conv, Proto, Object, Args, NumArgs, CandidateSet);    }    // Perform overload resolution. @@ -5205,11 +5357,12 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {  /// a C++ overloaded function (possibly with some parentheses and  /// perhaps a '&' around it). We have resolved the overloaded function  /// to the function declaration Fn, so patch up the expression E to -/// refer (possibly indirectly) to Fn. -void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) { +/// refer (possibly indirectly) to Fn. Returns the new expr. +Expr *Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {    if (ParenExpr *PE = dyn_cast<ParenExpr>(E)) { -    FixOverloadedFunctionReference(PE->getSubExpr(), Fn); -    E->setType(PE->getSubExpr()->getType()); +    Expr *NewExpr = FixOverloadedFunctionReference(PE->getSubExpr(), Fn); +    NewExpr->setType(PE->getSubExpr()->getType()); +    return NewExpr;    } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(E)) {      assert(UnOp->getOpcode() == UnaryOperator::AddrOf &&             "Can only take the address of an overloaded function"); @@ -5228,11 +5381,16 @@ void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {            = Context.getTypeDeclType(cast<RecordDecl>(Method->getDeclContext()));          E->setType(Context.getMemberPointerType(Fn->getType(),                                                  ClassType.getTypePtr())); -        return; +        return E;        } +      // FIXME: TemplateIdRefExpr referring to a member function template +      // specialization!      } -    FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); -    E->setType(Context.getPointerType(UnOp->getSubExpr()->getType())); +    Expr *NewExpr = FixOverloadedFunctionReference(UnOp->getSubExpr(), Fn); +    UnOp->setSubExpr(NewExpr); +    UnOp->setType(Context.getPointerType(NewExpr->getType())); +     +    return UnOp;    } else if (DeclRefExpr *DR = dyn_cast<DeclRefExpr>(E)) {      assert((isa<OverloadedFunctionDecl>(DR->getDecl()) ||              isa<FunctionTemplateDecl>(DR->getDecl())) && @@ -5242,9 +5400,24 @@ void Sema::FixOverloadedFunctionReference(Expr *E, FunctionDecl *Fn) {    } else if (MemberExpr *MemExpr = dyn_cast<MemberExpr>(E)) {      MemExpr->setMemberDecl(Fn);      E->setType(Fn->getType()); +  } else if (TemplateIdRefExpr *TID = dyn_cast<TemplateIdRefExpr>(E)) { +    // FIXME: We should capture the template arguments here. +    if (NestedNameSpecifier *Qualifier = TID->getQualifier()) +      E = new (Context) QualifiedDeclRefExpr(Fn, Fn->getType(), +                                             TID->getTemplateNameLoc(), +                                             /*FIXME?*/false, /*FIXME?*/false, +                                             TID->getQualifierRange(), +                                             Qualifier); +    else +      E = new (Context) DeclRefExpr(Fn, Fn->getType(),  +                                    TID->getTemplateNameLoc()); +     +    TID->Destroy(Context);    } else {      assert(false && "Invalid reference to overloaded function");    } +   +  return E;  }  } // end namespace clang diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index e8cd6b081de1..145342438503 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -368,6 +368,21 @@ static bool CmpCaseVals(const std::pair<llvm::APSInt, CaseStmt*>& lhs,    return false;  } +/// GetTypeBeforeIntegralPromotion - Returns the pre-promotion type of +/// potentially integral-promoted expression @p expr. +static QualType GetTypeBeforeIntegralPromotion(const Expr* expr) { +  const ImplicitCastExpr *ImplicitCast = +      dyn_cast_or_null<ImplicitCastExpr>(expr); +  if (ImplicitCast != NULL) { +    const Expr *ExprBeforePromotion = ImplicitCast->getSubExpr(); +    QualType TypeBeforePromotion = ExprBeforePromotion->getType(); +    if (TypeBeforePromotion->isIntegralType()) { +      return TypeBeforePromotion; +    } +  } +  return expr->getType(); +} +  Action::OwningStmtResult  Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,                              StmtArg Body) { @@ -382,11 +397,30 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,    Expr *CondExpr = SS->getCond();    QualType CondType = CondExpr->getType(); -  if (!CondExpr->isTypeDependent() && -      !CondType->isIntegerType()) { // C99 6.8.4.2p1 -    Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer) -      << CondType << CondExpr->getSourceRange(); -    return StmtError(); +  // C++ 6.4.2.p2: +  // Integral promotions are performed (on the switch condition). +  // +  // A case value unrepresentable by the original switch condition +  // type (before the promotion) doesn't make sense, even when it can +  // be represented by the promoted type.  Therefore we need to find +  // the pre-promotion type of the switch condition. +  QualType CondTypeBeforePromotion = +      GetTypeBeforeIntegralPromotion(CondExpr); + +  if (!CondExpr->isTypeDependent()) { +    if (!CondType->isIntegerType()) { // C99 6.8.4.2p1 +      Diag(SwitchLoc, diag::err_typecheck_statement_requires_integer) +          << CondType << CondExpr->getSourceRange(); +      return StmtError(); +    } + +    if (CondTypeBeforePromotion->isBooleanType()) { +      // switch(bool_expr) {...} is often a programmer error, e.g. +      //   switch(n && mask) { ... }  // Doh - should be "n & mask". +      // One can always use an if statement instead of switch(bool_expr). +      Diag(SwitchLoc, diag::warn_bool_switch_condition) +          << CondExpr->getSourceRange(); +    }    }    // Get the bitwidth of the switched-on value before promotions.  We must @@ -395,8 +429,8 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,      = CondExpr->isTypeDependent() || CondExpr->isValueDependent();    unsigned CondWidth      = HasDependentValue? 0 -                       : static_cast<unsigned>(Context.getTypeSize(CondType)); -  bool CondIsSigned = CondType->isSignedIntegerType(); +      : static_cast<unsigned>(Context.getTypeSize(CondTypeBeforePromotion)); +  bool CondIsSigned = CondTypeBeforePromotion->isSignedIntegerType();    // Accumulate all of the case values in a vector so that we can sort them    // and detect duplicates.  This vector contains the APInt for the case after @@ -448,7 +482,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,        // If the LHS is not the same type as the condition, insert an implicit        // cast. -      ImpCastExprToType(Lo, CondType); +      ImpCastExprToType(Lo, CondType, CastExpr::CK_IntegralCast);        CS->setLHS(Lo);        // If this is a case range, remember it in CaseRanges, otherwise CaseVals. @@ -504,7 +538,7 @@ Sema::ActOnFinishSwitchStmt(SourceLocation SwitchLoc, StmtArg Switch,          // If the LHS is not the same type as the condition, insert an implicit          // cast. -        ImpCastExprToType(Hi, CondType); +        ImpCastExprToType(Hi, CondType, CastExpr::CK_IntegralCast);          CR->setRHS(Hi);          // If the low value is bigger than the high value, the case is empty. diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ab0bbe081dbf..0f223208a938 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1251,7 +1251,9 @@ Sema::TypeResult Sema::ActOnTagTemplateIdType(TypeResult TypeResult,    return ElabType.getAsOpaquePtr();  } -Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template, +Sema::OwningExprResult Sema::BuildTemplateIdExpr(NestedNameSpecifier *Qualifier, +                                                 SourceRange QualifierRange, +                                                 TemplateName Template,                                                   SourceLocation TemplateNameLoc,                                                   SourceLocation LAngleLoc,                                             const TemplateArgument *TemplateArgs, @@ -1261,16 +1263,36 @@ Sema::OwningExprResult Sema::BuildTemplateIdExpr(TemplateName Template,    // template arguments that we have against the template name, if the template    // name refers to a single template. That's not a terribly common case,    // though. -  return Owned(TemplateIdRefExpr::Create(Context, -                                         /*FIXME: New type?*/Context.OverloadTy, -                                         /*FIXME: Necessary?*/0, -                                         /*FIXME: Necessary?*/SourceRange(), +   +  // Cope with an implicit member access in a C++ non-static member function. +  NamedDecl *D = Template.getAsTemplateDecl(); +  if (!D) +    D = Template.getAsOverloadedFunctionDecl(); +   +  CXXScopeSpec SS; +  SS.setRange(QualifierRange); +  SS.setScopeRep(Qualifier); +  QualType ThisType, MemberType; +  if (D && isImplicitMemberReference(&SS, D, TemplateNameLoc,  +                                     ThisType, MemberType)) { +    Expr *This = new (Context) CXXThisExpr(SourceLocation(), ThisType); +    return Owned(MemberExpr::Create(Context, This, true, +                                    Qualifier, QualifierRange, +                                    D, TemplateNameLoc, true, +                                    LAngleLoc, TemplateArgs, +                                    NumTemplateArgs, RAngleLoc, +                                    Context.OverloadTy)); +  } +   +  return Owned(TemplateIdRefExpr::Create(Context, Context.OverloadTy, +                                         Qualifier, QualifierRange,                                           Template, TemplateNameLoc, LAngleLoc,                                           TemplateArgs,                                           NumTemplateArgs, RAngleLoc));  } -Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD, +Sema::OwningExprResult Sema::ActOnTemplateIdExpr(const CXXScopeSpec &SS, +                                                 TemplateTy TemplateD,                                                   SourceLocation TemplateNameLoc,                                                   SourceLocation LAngleLoc,                                                ASTTemplateArgsPtr TemplateArgsIn, @@ -1283,7 +1305,9 @@ Sema::OwningExprResult Sema::ActOnTemplateIdExpr(TemplateTy TemplateD,    translateTemplateArguments(TemplateArgsIn, TemplateArgLocs, TemplateArgs);    TemplateArgsIn.release(); -  return BuildTemplateIdExpr(Template, TemplateNameLoc, LAngleLoc, +  return BuildTemplateIdExpr((NestedNameSpecifier *)SS.getScopeRep(), +                             SS.getRange(), +                             Template, TemplateNameLoc, LAngleLoc,                               TemplateArgs.data(), TemplateArgs.size(),                               RAngleLoc);  } @@ -1706,7 +1730,7 @@ bool Sema::CheckTemplateArgumentAddressOfObjectOrFunction(Expr *Arg,    bool Invalid = false;    // See through any implicit casts we added to fix the type. -  if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) +  while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))      Arg = Cast->getSubExpr();    // C++0x allows nullptr, and there's no further checking to be done for that. @@ -1808,7 +1832,7 @@ Sema::CheckTemplateArgumentPointerToMember(Expr *Arg, NamedDecl *&Member) {    bool Invalid = false;    // See through any implicit casts we added to fix the type. -  if (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg)) +  while (ImplicitCastExpr *Cast = dyn_cast<ImplicitCastExpr>(Arg))      Arg = Cast->getSubExpr();    // C++0x allows nullptr, and there's no further checking to be done for that. @@ -1936,7 +1960,7 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,      } else if (IsIntegralPromotion(Arg, ArgType, ParamType) ||                 !ParamType->isEnumeralType()) {        // This is an integral promotion or conversion. -      ImpCastExprToType(Arg, ParamType); +      ImpCastExprToType(Arg, ParamType, CastExpr::CK_IntegralCast);      } else {        // We can't perform this conversion.        Diag(Arg->getSourceRange().getBegin(), @@ -2025,20 +2049,23 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,      } else if (ArgType->isNullPtrType() && (ParamType->isPointerType() ||                   ParamType->isMemberPointerType())) {        ArgType = ParamType; -      ImpCastExprToType(Arg, ParamType); +      if (ParamType->isMemberPointerType()) +        ImpCastExprToType(Arg, ParamType, CastExpr::CK_NullToMemberPointer); +      else +        ImpCastExprToType(Arg, ParamType, CastExpr::CK_BitCast);      } else if (ArgType->isFunctionType() && ParamType->isPointerType()) {        ArgType = Context.getPointerType(ArgType); -      ImpCastExprToType(Arg, ArgType); +      ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay);      } else if (FunctionDecl *Fn                   = ResolveAddressOfOverloadedFunction(Arg, ParamType, true)) {        if (DiagnoseUseOfDecl(Fn, Arg->getSourceRange().getBegin()))          return true; -      FixOverloadedFunctionReference(Arg, Fn); +      Arg = FixOverloadedFunctionReference(Arg, Fn);        ArgType = Arg->getType();        if (ArgType->isFunctionType() && ParamType->isPointerType()) {          ArgType = Context.getPointerType(Arg->getType()); -        ImpCastExprToType(Arg, ArgType); +        ImpCastExprToType(Arg, ArgType, CastExpr::CK_FunctionToPointerDecay);        }      } @@ -2083,15 +2110,15 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,      if (ArgType->isNullPtrType()) {        ArgType = ParamType; -      ImpCastExprToType(Arg, ParamType); +      ImpCastExprToType(Arg, ParamType, CastExpr::CK_BitCast);      } else if (ArgType->isArrayType()) {        ArgType = Context.getArrayDecayedType(ArgType); -      ImpCastExprToType(Arg, ArgType); +      ImpCastExprToType(Arg, ArgType, CastExpr::CK_ArrayToPointerDecay);      }      if (IsQualificationConversion(ArgType, ParamType)) {        ArgType = ParamType; -      ImpCastExprToType(Arg, ParamType); +      ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp);      }      if (!Context.hasSameUnqualifiedType(ArgType, ParamType)) { @@ -2162,9 +2189,9 @@ bool Sema::CheckTemplateArgument(NonTypeTemplateParmDecl *Param,    if (Context.hasSameUnqualifiedType(ParamType, ArgType)) {      // Types match exactly: nothing more to do here.    } else if (ArgType->isNullPtrType()) { -    ImpCastExprToType(Arg, ParamType); +    ImpCastExprToType(Arg, ParamType, CastExpr::CK_NullToMemberPointer);    } else if (IsQualificationConversion(ArgType, ParamType)) { -    ImpCastExprToType(Arg, ParamType); +    ImpCastExprToType(Arg, ParamType, CastExpr::CK_NoOp);    } else {      // We can't perform this conversion.      Diag(Arg->getSourceRange().getBegin(), @@ -3038,6 +3065,173 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,    return DeclPtrTy();  } +/// \brief Diagnose cases where we have an explicit template specialization  +/// before/after an explicit template instantiation, producing diagnostics +/// for those cases where they are required and determining whether the  +/// new specialization/instantiation will have any effect. +/// +/// \param S the semantic analysis object. +/// +/// \param NewLoc the location of the new explicit specialization or  +/// instantiation. +/// +/// \param NewTSK the kind of the new explicit specialization or instantiation. +/// +/// \param PrevDecl the previous declaration of the entity. +/// +/// \param PrevTSK the kind of the old explicit specialization or instantiatin. +/// +/// \param PrevPointOfInstantiation if valid, indicates where the previus  +/// declaration was instantiated (either implicitly or explicitly). +/// +/// \param SuppressNew will be set to true to indicate that the new  +/// specialization or instantiation has no effect and should be ignored. +/// +/// \returns true if there was an error that should prevent the introduction of +/// the new declaration into the AST, false otherwise. +static bool  +CheckSpecializationInstantiationRedecl(Sema &S, +                                       SourceLocation NewLoc, +                                       TemplateSpecializationKind NewTSK, +                                       NamedDecl *PrevDecl, +                                       TemplateSpecializationKind PrevTSK, +                                       SourceLocation PrevPointOfInstantiation, +                                       bool &SuppressNew) { +  SuppressNew = false; +   +  switch (NewTSK) { +  case TSK_Undeclared: +  case TSK_ImplicitInstantiation: +    assert(false && "Don't check implicit instantiations here"); +    return false; +     +  case TSK_ExplicitSpecialization: +    switch (PrevTSK) { +    case TSK_Undeclared: +    case TSK_ExplicitSpecialization: +      // Okay, we're just specializing something that is either already  +      // explicitly specialized or has merely been mentioned without any +      // instantiation. +      return false; + +    case TSK_ImplicitInstantiation: +      if (PrevPointOfInstantiation.isInvalid()) { +        // The declaration itself has not actually been instantiated, so it is +        // still okay to specialize it. +        return false; +      } +      // Fall through +         +    case TSK_ExplicitInstantiationDeclaration: +    case TSK_ExplicitInstantiationDefinition: +      assert((PrevTSK == TSK_ImplicitInstantiation ||  +              PrevPointOfInstantiation.isValid()) &&  +             "Explicit instantiation without point of instantiation?"); +         +      // C++ [temp.expl.spec]p6: +      //   If a template, a member template or the member of a class template  +      //   is explicitly specialized then that specialization shall be declared +      //   before the first use of that specialization that would cause an  +      //   implicit instantiation to take place, in every translation unit in +      //   which such a use occurs; no diagnostic is required. +      S.Diag(NewLoc, diag::err_specialization_after_instantiation) +        << PrevDecl; +      S.Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here) +        << (PrevTSK != TSK_ImplicitInstantiation); +       +      return true; +    } +    break; +       +  case TSK_ExplicitInstantiationDeclaration: +    switch (PrevTSK) { +    case TSK_ExplicitInstantiationDeclaration: +      // This explicit instantiation declaration is redundant (that's okay). +      SuppressNew = true; +      return false; +         +    case TSK_Undeclared: +    case TSK_ImplicitInstantiation: +      // We're explicitly instantiating something that may have already been +      // implicitly instantiated; that's fine. +      return false; +         +    case TSK_ExplicitSpecialization: +      // C++0x [temp.explicit]p4: +      //   For a given set of template parameters, if an explicit instantiation +      //   of a template appears after a declaration of an explicit  +      //   specialization for that template, the explicit instantiation has no +      //   effect. +      return false; +         +    case TSK_ExplicitInstantiationDefinition: +      // C++0x [temp.explicit]p10: +      //   If an entity is the subject of both an explicit instantiation  +      //   declaration and an explicit instantiation definition in the same  +      //   translation unit, the definition shall follow the declaration. +      S.Diag(NewLoc,  +             diag::err_explicit_instantiation_declaration_after_definition); +      S.Diag(PrevPointOfInstantiation,  +             diag::note_explicit_instantiation_definition_here); +      assert(PrevPointOfInstantiation.isValid() && +             "Explicit instantiation without point of instantiation?"); +      SuppressNew = true; +      return false; +    } +    break; +       +  case TSK_ExplicitInstantiationDefinition: +    switch (PrevTSK) { +    case TSK_Undeclared: +    case TSK_ImplicitInstantiation: +      // We're explicitly instantiating something that may have already been +      // implicitly instantiated; that's fine. +      return false; +         +    case TSK_ExplicitSpecialization: +      // C++ DR 259, C++0x [temp.explicit]p4: +      //   For a given set of template parameters, if an explicit +      //   instantiation of a template appears after a declaration of +      //   an explicit specialization for that template, the explicit +      //   instantiation has no effect. +      // +      // In C++98/03 mode, we only give an extension warning here, because it  +      // is not not harmful to try to explicitly instantiate something that +      // has been explicitly specialized. +      if (!S.getLangOptions().CPlusPlus0x) { +        S.Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization) +          << PrevDecl; +        S.Diag(PrevDecl->getLocation(), +             diag::note_previous_template_specialization); +      } +      SuppressNew = true; +      return false; +         +    case TSK_ExplicitInstantiationDeclaration: +      // We're explicity instantiating a definition for something for which we +      // were previously asked to suppress instantiations. That's fine.  +      return false; +         +    case TSK_ExplicitInstantiationDefinition: +      // C++0x [temp.spec]p5: +      //   For a given template and a given set of template-arguments, +      //     - an explicit instantiation definition shall appear at most once +      //       in a program, +      S.Diag(NewLoc, diag::err_explicit_instantiation_duplicate) +        << PrevDecl; +      S.Diag(PrevPointOfInstantiation,  +             diag::note_previous_explicit_instantiation); +      SuppressNew = true; +      return false;         +    } +    break; +  } +   +  assert(false && "Missing specialization/instantiation case?"); +          +  return false; +} +  /// \brief Perform semantic analysis for the given function template   /// specialization.  /// @@ -3463,54 +3657,18 @@ Sema::ActOnExplicitInstantiation(Scope *S,    ClassTemplateSpecializationDecl *Specialization = 0; -  bool SpecializationRequiresInstantiation = true;    if (PrevDecl) { -    if (PrevDecl->getSpecializationKind() -          == TSK_ExplicitInstantiationDefinition) { -      // This particular specialization has already been declared or -      // instantiated. We cannot explicitly instantiate it. -      Diag(TemplateNameLoc, diag::err_explicit_instantiation_duplicate) -        << Context.getTypeDeclType(PrevDecl); -      Diag(PrevDecl->getLocation(), -           diag::note_previous_explicit_instantiation); +    bool SuppressNew = false; +    if (CheckSpecializationInstantiationRedecl(*this, TemplateNameLoc, TSK, +                                               PrevDecl,  +                                              PrevDecl->getSpecializationKind(),  +                                            PrevDecl->getPointOfInstantiation(), +                                               SuppressNew))        return DeclPtrTy::make(PrevDecl); -    } - -    if (PrevDecl->getSpecializationKind() == TSK_ExplicitSpecialization) { -      // C++ DR 259, C++0x [temp.explicit]p4: -      //   For a given set of template parameters, if an explicit -      //   instantiation of a template appears after a declaration of -      //   an explicit specialization for that template, the explicit -      //   instantiation has no effect. -      if (!getLangOptions().CPlusPlus0x) { -        Diag(TemplateNameLoc, -             diag::ext_explicit_instantiation_after_specialization) -          << Context.getTypeDeclType(PrevDecl); -        Diag(PrevDecl->getLocation(), -             diag::note_previous_template_specialization); -      } -      // Create a new class template specialization declaration node -      // for this explicit specialization. This node is only used to -      // record the existence of this explicit instantiation for -      // accurate reproduction of the source code; we don't actually -      // use it for anything, since it is semantically irrelevant. -      Specialization -        = ClassTemplateSpecializationDecl::Create(Context, -                                             ClassTemplate->getDeclContext(), -                                                  TemplateNameLoc, -                                                  ClassTemplate, -                                                  Converted, 0); -      Specialization->setLexicalDeclContext(CurContext); -      CurContext->addDecl(Specialization); +    if (SuppressNew)        return DeclPtrTy::make(PrevDecl); -    } - -    // If we have already (implicitly) instantiated this -    // specialization, there is less work to do. -    if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation) -      SpecializationRequiresInstantiation = false; - +          if (PrevDecl->getSpecializationKind() == TSK_ImplicitInstantiation ||          PrevDecl->getSpecializationKind() == TSK_Undeclared) {        // Since the only prior class template specialization with these @@ -3521,7 +3679,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,        Specialization->setLocation(TemplateNameLoc);        PrevDecl = 0;      } -  }  +  }    if (!Specialization) {      // Create a new class template specialization declaration node for @@ -3574,11 +3732,13 @@ Sema::ActOnExplicitInstantiation(Scope *S,    //    // This check comes when we actually try to perform the    // instantiation. -  if (SpecializationRequiresInstantiation) +  ClassTemplateSpecializationDecl *Def +    = cast_or_null<ClassTemplateSpecializationDecl>( +                                        Specialization->getDefinition(Context)); +  if (!Def)      InstantiateClassTemplateSpecialization(Specialization, TSK);    else // Instantiate the members of this class template specialization. -    InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization, -                                                  TSK); +    InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);    return DeclPtrTy::make(Specialization);  } @@ -3649,17 +3809,46 @@ Sema::ActOnExplicitInstantiation(Scope *S,    //    // This is C++ DR 275.    CheckExplicitInstantiationScope(*this, Record, NameLoc, true); - -  if (!Record->getDefinition(Context)) { -    // If the class has a definition, instantiate it (and all of its -    // members, recursively). -    Pattern = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context)); -    if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern, -                                    getTemplateInstantiationArgs(Record), -                                    TSK)) +   +  // Verify that it is okay to explicitly instantiate here. +  CXXRecordDecl *PrevDecl  +    = cast_or_null<CXXRecordDecl>(Record->getPreviousDeclaration()); +  if (!PrevDecl && Record->getDefinition(Context)) +    PrevDecl = Record; +  if (PrevDecl) { +    MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo(); +    bool SuppressNew = false; +    assert(MSInfo && "No member specialization information?"); +    if (CheckSpecializationInstantiationRedecl(*this, TemplateLoc, TSK,  +                                               PrevDecl, +                                        MSInfo->getTemplateSpecializationKind(), +                                             MSInfo->getPointOfInstantiation(),  +                                               SuppressNew)) +      return true; +    if (SuppressNew) +      return TagD; +  } +   +  CXXRecordDecl *RecordDef +    = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context)); +  if (!RecordDef) { +    // C++ [temp.explicit]p3: +    //   A definition of a member class of a class template shall be in scope  +    //   at the point of an explicit instantiation of the member class. +    CXXRecordDecl *Def  +      = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context)); +    if (!Def) { +      Diag(TemplateLoc, diag::err_explicit_instantiation_undefined_member) +        << 0 << Record->getDeclName() << Record->getDeclContext(); +      Diag(Pattern->getLocation(), diag::note_forward_declaration) +        << Pattern; +      return true; +    } else if (InstantiateClass(NameLoc, Record, Def, +                                getTemplateInstantiationArgs(Record), +                                TSK))        return true;    } else // Instantiate all of the members of the class. -    InstantiateClassMembers(TemplateLoc, Record, +    InstantiateClassMembers(NameLoc, RecordDef,                              getTemplateInstantiationArgs(Record), TSK);    // FIXME: We don't have any representation for explicit instantiations of @@ -3775,11 +3964,24 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,      // Check the scope of this explicit instantiation.      CheckExplicitInstantiationScope(*this, Prev, D.getIdentifierLoc(), true); +    // Verify that it is okay to explicitly instantiate here. +    MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo(); +    assert(MSInfo && "Missing static data member specialization info?"); +    bool SuppressNew = false; +    if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,  +                                               Prev, +                                        MSInfo->getTemplateSpecializationKind(), +                                              MSInfo->getPointOfInstantiation(),  +                                               SuppressNew)) +      return true; +    if (SuppressNew) +      return DeclPtrTy(); +          // Instantiate static data member. -    // FIXME: Check for prior specializations and such. -    Prev->setTemplateSpecializationKind(TSK); +    Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc());      if (TSK == TSK_ExplicitInstantiationDefinition) -      InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false); +      InstantiateStaticDataMemberDefinition(D.getIdentifierLoc(), Prev, false, +                                            /*DefinitionRequired=*/true);      // FIXME: Create an ExplicitInstantiation node?      return DeclPtrTy(); @@ -3850,8 +4052,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,    if (!Specialization)      return true; -  switch (Specialization->getTemplateSpecializationKind()) { -  case TSK_Undeclared: +  if (Specialization->getTemplateSpecializationKind() == TSK_Undeclared) {      Diag(D.getIdentifierLoc(),            diag::err_explicit_instantiation_member_function_not_instantiated)        << Specialization @@ -3859,35 +4060,33 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,            TSK_ExplicitSpecialization);      Diag(Specialization->getLocation(), diag::note_explicit_instantiation_here);      return true; +  }  +   +  FunctionDecl *PrevDecl = Specialization->getPreviousDeclaration(); +  if (!PrevDecl && Specialization->isThisDeclarationADefinition()) +    PrevDecl = Specialization; -  case TSK_ExplicitSpecialization: -    // C++ [temp.explicit]p4: -    //   For a given set of template parameters, if an explicit instantiation -    //   of a template appears after a declaration of an explicit  -    //   specialization for that template, the explicit instantiation has no  -    //   effect. -    break;       - -  case TSK_ExplicitInstantiationDefinition: -    // FIXME: Check that we aren't trying to perform an explicit instantiation -    // declaration now. -    // Fall through -       -  case TSK_ImplicitInstantiation: -  case TSK_ExplicitInstantiationDeclaration: -    // Instantiate the function, if this is an explicit instantiation  -    // definition. -    if (TSK == TSK_ExplicitInstantiationDefinition) -      InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization,  -                                    false); -       -    Specialization->setTemplateSpecializationKind(TSK); -    break; +  if (PrevDecl) { +    bool SuppressNew = false; +    if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK, +                                               PrevDecl,  +                                     PrevDecl->getTemplateSpecializationKind(),  +                                          PrevDecl->getPointOfInstantiation(), +                                               SuppressNew)) +      return true; +     +    // FIXME: We may still want to build some representation of this +    // explicit specialization. +    if (SuppressNew) +      return DeclPtrTy();    } - -  // Check the scope of this explicit instantiation. -  FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate(); +  if (TSK == TSK_ExplicitInstantiationDefinition) +    InstantiateFunctionDefinition(D.getIdentifierLoc(), Specialization,  +                                  false, /*DefinitionRequired=*/true); +       +  Specialization->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); +     // C++0x [temp.explicit]p2:    //   If the explicit instantiation is for a member function, a member class     //   or a static data member of a class template specialization, the name of @@ -3895,6 +4094,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,    //   name shall be a simple-template-id.    //    // C++98 has the same restriction, just worded differently. +  FunctionTemplateDecl *FunTmpl = Specialization->getPrimaryTemplate();    if (D.getKind() != Declarator::DK_TemplateId && !FunTmpl &&        D.getCXXScopeSpec().isSet() &&         !ScopeSpecifierHasTemplateId(D.getCXXScopeSpec())) @@ -4089,12 +4289,27 @@ namespace {      /// \brief Transforms a typename type by determining whether the type now      /// refers to a member of the current instantiation, and then      /// type-checking and building a QualifiedNameType (when possible). -    QualType TransformTypenameType(const TypenameType *T); +    QualType TransformTypenameType(TypeLocBuilder &TLB, TypenameTypeLoc TL); +    QualType TransformTypenameType(TypenameType *T);    };  }  QualType -CurrentInstantiationRebuilder::TransformTypenameType(const TypenameType *T) { +CurrentInstantiationRebuilder::TransformTypenameType(TypeLocBuilder &TLB, +                                                     TypenameTypeLoc TL) { +  QualType Result = TransformTypenameType(TL.getTypePtr()); +  if (Result.isNull()) +    return QualType(); + +  TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); + +  return Result; +} + +QualType +CurrentInstantiationRebuilder::TransformTypenameType(TypenameType *T) { +    NestedNameSpecifier *NNS      = TransformNestedNameSpecifier(T->getQualifier(),                                /*FIXME:*/SourceRange(getBaseLocation())); diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index b981389d1d15..2a44f83598e8 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -221,7 +221,7 @@ DeduceTemplateArguments(ASTContext &Context,                          QualType Arg,                          Sema::TemplateDeductionInfo &Info,                          llvm::SmallVectorImpl<TemplateArgument> &Deduced) { -  assert(Arg->isCanonical() && "Argument type must be canonical"); +  assert(Arg.isCanonical() && "Argument type must be canonical");    // Check whether the template argument is a dependent template-id.    // FIXME: This is untested code; it can be tested when we implement @@ -313,7 +313,7 @@ DeduceTemplateArguments(ASTContext &Context,  /// that corresponds to T. Otherwise, returns T.  static QualType getUnqualifiedArrayType(ASTContext &Context, QualType T,                                          Qualifiers &Quals) { -  assert(T->isCanonical() && "Only operates on canonical types"); +  assert(T.isCanonical() && "Only operates on canonical types");    if (!isa<ArrayType>(T)) {      Quals = T.getQualifiers();      return T.getUnqualifiedType(); diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 24b83704eba9..53d158088c8e 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -400,6 +400,10 @@ namespace {      /// instantiating it.      Decl *TransformDefinition(Decl *D); +    /// \bried Transform the first qualifier within a scope by instantiating the +    /// declaration. +    NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc); +            /// \brief Rebuild the exception declaration and register the declaration      /// as an instantiated local.      VarDecl *RebuildExceptionDecl(VarDecl *ExceptionDecl, QualType T, @@ -416,7 +420,8 @@ namespace {      /// \brief Transforms a template type parameter type by performing      /// substitution of the corresponding template type argument. -    QualType TransformTemplateTypeParmType(const TemplateTypeParmType *T); +    QualType TransformTemplateTypeParmType(TypeLocBuilder &TLB, +                                           TemplateTypeParmTypeLoc TL);    };  } @@ -457,6 +462,31 @@ Decl *TemplateInstantiator::TransformDefinition(Decl *D) {    return Inst;  } +NamedDecl * +TemplateInstantiator::TransformFirstQualifierInScope(NamedDecl *D,  +                                                     SourceLocation Loc) { +  // If the first part of the nested-name-specifier was a template type  +  // parameter, instantiate that type parameter down to a tag type. +  if (TemplateTypeParmDecl *TTPD = dyn_cast_or_null<TemplateTypeParmDecl>(D)) { +    const TemplateTypeParmType *TTP  +      = cast<TemplateTypeParmType>(getSema().Context.getTypeDeclType(TTPD)); +    if (TTP->getDepth() < TemplateArgs.getNumLevels()) { +      QualType T = TemplateArgs(TTP->getDepth(), TTP->getIndex()).getAsType(); +      if (T.isNull()) +        return cast_or_null<NamedDecl>(TransformDecl(D)); +       +      if (const TagType *Tag = T->getAs<TagType>()) +        return Tag->getDecl(); +       +      // The resulting type is not a tag; complain. +      getSema().Diag(Loc, diag::err_nested_name_spec_non_tag) << T; +      return 0; +    } +  } +   +  return cast_or_null<NamedDecl>(TransformDecl(D)); +} +  VarDecl *  TemplateInstantiator::RebuildExceptionDecl(VarDecl *ExceptionDecl,                                             QualType T, @@ -596,8 +626,9 @@ TemplateInstantiator::TransformDeclRefExpr(DeclRefExpr *E) {  }  QualType -TemplateInstantiator::TransformTemplateTypeParmType( -                                              const TemplateTypeParmType *T) { +TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB, +                                                TemplateTypeParmTypeLoc TL) { +  TemplateTypeParmType *T = TL.getTypePtr();    if (T->getDepth() < TemplateArgs.getNumLevels()) {      // Replace the template type parameter with its corresponding      // template argument. @@ -606,25 +637,42 @@ TemplateInstantiator::TransformTemplateTypeParmType(      // because we are performing instantiation from explicitly-specified      // template arguments in a function template class, but there were some      // arguments left unspecified. -    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) -      return QualType(T, 0); +    if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex())) { +      TemplateTypeParmTypeLoc NewTL +        = TLB.push<TemplateTypeParmTypeLoc>(TL.getType()); +      NewTL.setNameLoc(TL.getNameLoc()); +      return TL.getType(); +    }      assert(TemplateArgs(T->getDepth(), T->getIndex()).getKind()               == TemplateArgument::Type &&             "Template argument kind mismatch"); -    return TemplateArgs(T->getDepth(), T->getIndex()).getAsType(); +    QualType Replacement +      = TemplateArgs(T->getDepth(), T->getIndex()).getAsType(); + +    // TODO: only do this uniquing once, at the start of instantiation. +    QualType Result +      = getSema().Context.getSubstTemplateTypeParmType(T, Replacement); +    SubstTemplateTypeParmTypeLoc NewTL +      = TLB.push<SubstTemplateTypeParmTypeLoc>(Result); +    NewTL.setNameLoc(TL.getNameLoc()); +    return Result;    }    // The template type parameter comes from an inner template (e.g.,    // the template parameter list of a member template inside the    // template we are instantiating). Create a new template type    // parameter with the template "level" reduced by one. -  return getSema().Context.getTemplateTypeParmType( -                                  T->getDepth() - TemplateArgs.getNumLevels(), -                                                   T->getIndex(), -                                                   T->isParameterPack(), -                                                   T->getName()); +  QualType Result +    = getSema().Context.getTemplateTypeParmType(T->getDepth() +                                                 - TemplateArgs.getNumLevels(), +                                                T->getIndex(), +                                                T->isParameterPack(), +                                                T->getName()); +  TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); +  return Result;  }  /// \brief Perform substitution on the type T with a given set of template @@ -654,6 +702,22 @@ TemplateInstantiator::TransformTemplateTypeParmType(  ///  /// \returns If the instantiation succeeds, the instantiated  /// type. Otherwise, produces diagnostics and returns a NULL type. +DeclaratorInfo *Sema::SubstType(DeclaratorInfo *T, +                                const MultiLevelTemplateArgumentList &Args, +                                SourceLocation Loc, +                                DeclarationName Entity) { +  assert(!ActiveTemplateInstantiations.empty() && +         "Cannot perform an instantiation without some context on the " +         "instantiation stack"); +   +  if (!T->getType()->isDependentType()) +    return T; + +  TemplateInstantiator Instantiator(*this, Args, Loc, Entity); +  return Instantiator.TransformType(T); +} + +/// Deprecated form of the above.  QualType Sema::SubstType(QualType T,                           const MultiLevelTemplateArgumentList &TemplateArgs,                           SourceLocation Loc, DeclarationName Entity) { @@ -769,6 +833,13 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,    }    Pattern = PatternDef; +  // \brief Record the point of instantiation. +  if (MemberSpecializationInfo *MSInfo  +        = Instantiation->getMemberSpecializationInfo()) { +    MSInfo->setTemplateSpecializationKind(TSK); +    MSInfo->setPointOfInstantiation(PointOfInstantiation); +  } +      InstantiatingTemplate Inst(*this, PointOfInstantiation, Instantiation);    if (Inst)      return true; @@ -1007,7 +1078,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,                TSK_ExplicitSpecialization)            continue; -        Function->setTemplateSpecializationKind(TSK); +        Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);        }        if (!Function->getBody() && TSK == TSK_ExplicitInstantiationDefinition) @@ -1018,7 +1089,7 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,          if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)            continue; -        Var->setTemplateSpecializationKind(TSK); +        Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);          if (TSK == TSK_ExplicitInstantiationDefinition)            InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 060cc559833f..be4adbc93d15 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -123,16 +123,17 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {  Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {    // Do substitution on the type of the declaration -  QualType T = SemaRef.SubstType(D->getType(), TemplateArgs, -                                 D->getTypeSpecStartLoc(), -                                 D->getDeclName()); -  if (T.isNull()) +  DeclaratorInfo *DI = SemaRef.SubstType(D->getDeclaratorInfo(), +                                         TemplateArgs, +                                         D->getTypeSpecStartLoc(), +                                         D->getDeclName()); +  if (!DI)      return 0;    // Build the instantiated declaration    VarDecl *Var = VarDecl::Create(SemaRef.Context, Owner,                                   D->getLocation(), D->getIdentifier(), -                                 T, D->getDeclaratorInfo(), +                                 DI->getType(), DI,                                   D->getStorageClass());    Var->setThreadSpecified(D->isThreadSpecified());    Var->setCXXDirectInitializer(D->hasCXXDirectInitializer()); @@ -203,11 +204,14 @@ Decl *TemplateDeclInstantiator::VisitVarDecl(VarDecl *D) {  Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {    bool Invalid = false; -  QualType T = D->getType(); -  if (T->isDependentType())  { -    T = SemaRef.SubstType(T, TemplateArgs, -                          D->getLocation(), D->getDeclName()); -    if (!T.isNull() && T->isFunctionType()) { +  DeclaratorInfo *DI = D->getDeclaratorInfo(); +  if (DI->getType()->isDependentType())  { +    DI = SemaRef.SubstType(DI, TemplateArgs, +                           D->getLocation(), D->getDeclName()); +    if (!DI) { +      DI = D->getDeclaratorInfo(); +      Invalid = true; +    } else if (DI->getType()->isFunctionType()) {        // C++ [temp.arg.type]p3:        //   If a declaration acquires a function type through a type        //   dependent on a template-parameter and this causes a @@ -215,8 +219,7 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {        //   function declarator to have function type, the program is        //   ill-formed.        SemaRef.Diag(D->getLocation(), diag::err_field_instantiates_to_function) -        << T; -      T = QualType(); +        << DI->getType();        Invalid = true;      }    } @@ -237,8 +240,8 @@ Decl *TemplateDeclInstantiator::VisitFieldDecl(FieldDecl *D) {        BitWidth = InstantiatedBitWidth.takeAs<Expr>();    } -  FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), T, -                                            D->getDeclaratorInfo(), +  FieldDecl *Field = SemaRef.CheckFieldDecl(D->getDeclName(), +                                            DI->getType(), DI,                                              cast<RecordDecl>(Owner),                                              D->getLocation(),                                              D->isMutable(), @@ -1044,9 +1047,14 @@ TemplateDeclInstantiator::InitMethodInstantiation(CXXMethodDecl *New,  ///  /// \param Recursive if true, recursively instantiates any functions that  /// are required by this instantiation. +/// +/// \param DefinitionRequired if true, then we are performing an explicit +/// instantiation where the body of the function is required. Complain if +/// there is no such body.  void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,                                           FunctionDecl *Function, -                                         bool Recursive) { +                                         bool Recursive, +                                         bool DefinitionRequired) {    if (Function->isInvalidDecl())      return; @@ -1075,8 +1083,24 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,    if (PatternDecl)      Pattern = PatternDecl->getBody(PatternDecl); -  if (!Pattern) +  if (!Pattern) { +    if (DefinitionRequired) { +      if (Function->getPrimaryTemplate()) +        Diag(PointOfInstantiation,  +             diag::err_explicit_instantiation_undefined_func_template) +          << Function->getPrimaryTemplate(); +      else +        Diag(PointOfInstantiation,  +             diag::err_explicit_instantiation_undefined_member) +          << 1 << Function->getDeclName() << Function->getDeclContext(); +       +      if (PatternDecl) +        Diag(PatternDecl->getLocation(),  +             diag::note_explicit_instantiation_here); +    } +            return; +  }    // C++0x [temp.explicit]p9:    //   Except for inline functions, other explicit instantiation declarations @@ -1161,10 +1185,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,  ///  /// \param Recursive if true, recursively instantiates any functions that  /// are required by this instantiation. +/// +/// \param DefinitionRequired if true, then we are performing an explicit +/// instantiation where an out-of-line definition of the member variable +/// is required. Complain if there is no such definition.  void Sema::InstantiateStaticDataMemberDefinition(                                            SourceLocation PointOfInstantiation,                                                   VarDecl *Var, -                                                 bool Recursive) { +                                                 bool Recursive, +                                                 bool DefinitionRequired) {    if (Var->isInvalidDecl())      return; @@ -1187,6 +1216,13 @@ void Sema::InstantiateStaticDataMemberDefinition(      // so we won't perform any instantiation. Rather, we rely on the user to      // instantiate this definition (or provide a specialization for it) in      // another translation unit. +    if (DefinitionRequired) { +      Diag(PointOfInstantiation,  +           diag::err_explicit_instantiation_undefined_member) +        << 2 << Var->getDeclName() << Var->getDeclContext(); +      Diag(Def->getLocation(), diag::note_explicit_instantiation_here); +    }     +          return;    } @@ -1225,7 +1261,10 @@ void Sema::InstantiateStaticDataMemberDefinition(    if (Var) {      Var->setPreviousDeclaration(OldVar); -    Var->setTemplateSpecializationKind(OldVar->getTemplateSpecializationKind()); +    MemberSpecializationInfo *MSInfo = OldVar->getMemberSpecializationInfo(); +    assert(MSInfo && "Missing member specialization information?"); +    Var->setTemplateSpecializationKind(MSInfo->getTemplateSpecializationKind(), +                                       MSInfo->getPointOfInstantiation());      DeclGroupRef DG(Var);      Consumer.HandleTopLevelDecl(DG);    } diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 9603ca8a51c4..49f7119c8b06 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -17,6 +17,7 @@  #include "clang/AST/DeclObjC.h"  #include "clang/AST/DeclTemplate.h"  #include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeLocVisitor.h"  #include "clang/AST/Expr.h"  #include "clang/Basic/PartialDiagnostic.h"  #include "clang/Parse/DeclSpec.h" @@ -51,16 +52,14 @@ QualType Sema::adjustParameterType(QualType T) {  /// object.  /// \param DS  the declaration specifiers  /// \param DeclLoc The location of the declarator identifier or invalid if none. -/// \param SourceTy QualType representing the type as written in source form.  /// \returns The type described by the declaration specifiers.  This function  /// never returns null.  QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,                                       SourceLocation DeclLoc, -                                     bool &isInvalid, QualType &SourceTy) { +                                     bool &isInvalid) {    // FIXME: Should move the logic from DeclSpec::Finish to here for validity    // checking.    QualType Result; -  SourceTy = Result;    switch (DS.getTypeSpecType()) {    case DeclSpec::TST_void: @@ -105,9 +104,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,    case DeclSpec::TST_unspecified:      // "<proto1,proto2>" is an objc qualified ID with a missing id.      if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { -      SourceTy = Context.getObjCProtocolListType(QualType(), -                                                 (ObjCProtocolDecl**)PQ, -                                                 DS.getNumProtocolQualifiers());        Result = Context.getObjCObjectPointerType(Context.ObjCBuiltinIdTy,                                                  (ObjCProtocolDecl**)PQ,                                                  DS.getNumProtocolQualifiers()); @@ -225,9 +221,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,      Result = GetTypeFromParser(DS.getTypeRep());      if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) { -      SourceTy = Context.getObjCProtocolListType(Result, -                                                 (ObjCProtocolDecl**)PQ, -                                                 DS.getNumProtocolQualifiers());        if (const ObjCInterfaceType *              Interface = Result->getAs<ObjCInterfaceType>()) {          // It would be nice if protocol qualifiers were only stored with the @@ -384,8 +377,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS,      Result = Context.getQualifiedType(Result, Quals);    } -  if (SourceTy.isNull()) -    SourceTy = Result;    return Result;  } @@ -449,36 +440,32 @@ QualType Sema::BuildPointerType(QualType T, unsigned Quals,  ///  /// \returns A suitable reference type, if there are no  /// errors. Otherwise, returns a NULL type. -QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR, -                                  SourceLocation Loc, DeclarationName Entity) { +QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue, +                                  unsigned CVR, SourceLocation Loc, +                                  DeclarationName Entity) {    Qualifiers Quals = Qualifiers::fromCVRMask(CVR); -  if (LValueRef) { -    if (const RValueReferenceType *R = T->getAs<RValueReferenceType>()) { -      // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a -      //   reference to a type T, and attempt to create the type "lvalue -      //   reference to cv TD" creates the type "lvalue reference to T". -      // We use the qualifiers (restrict or none) of the original reference, -      // not the new ones. This is consistent with GCC. -      QualType LVRT = Context.getLValueReferenceType(R->getPointeeType()); -      return Context.getQualifiedType(LVRT, T.getQualifiers()); -    } -  } -  if (T->isReferenceType()) { -    // C++ [dcl.ref]p4: There shall be no references to references. -    // -    // According to C++ DR 106, references to references are only -    // diagnosed when they are written directly (e.g., "int & &"), -    // but not when they happen via a typedef: -    // -    //   typedef int& intref; -    //   typedef intref& intref2; -    // -    // Parser::ParseDeclaratorInternal diagnoses the case where -    // references are written directly; here, we handle the -    // collapsing of references-to-references as described in C++ -    // DR 106 and amended by C++ DR 540. -    return T; -  } + +  bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>(); + +  // C++0x [dcl.typedef]p9: If a typedef TD names a type that is a +  //   reference to a type T, and attempt to create the type "lvalue +  //   reference to cv TD" creates the type "lvalue reference to T". +  // We use the qualifiers (restrict or none) of the original reference, +  // not the new ones. This is consistent with GCC. + +  // C++ [dcl.ref]p4: There shall be no references to references. +  // +  // According to C++ DR 106, references to references are only +  // diagnosed when they are written directly (e.g., "int & &"), +  // but not when they happen via a typedef: +  // +  //   typedef int& intref; +  //   typedef intref& intref2; +  // +  // Parser::ParseDeclaratorInternal diagnoses the case where +  // references are written directly; here, we handle the +  // collapsing of references-to-references as described in C++ +  // DR 106 and amended by C++ DR 540.    // C++ [dcl.ref]p1:    //   A declarator that specifies the type "reference to cv void" @@ -510,7 +497,8 @@ QualType Sema::BuildReferenceType(QualType T, bool LValueRef, unsigned CVR,    // Handle restrict on references.    if (LValueRef) -    return Context.getQualifiedType(Context.getLValueReferenceType(T), Quals); +    return Context.getQualifiedType( +               Context.getLValueReferenceType(T, SpelledAsLValue), Quals);    return Context.getQualifiedType(Context.getRValueReferenceType(T), Quals);  } @@ -610,8 +598,7 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,            << ArraySize->getSourceRange();        }      } -    T = Context.getConstantArrayWithExprType(T, ConstVal, ArraySize, -                                             ASM, Quals, Brackets); +    T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);    }    // If this is not C99, extwarn about VLA's and C99 array size modifiers.    if (!getLangOptions().C99) { @@ -717,7 +704,7 @@ QualType Sema::BuildFunctionType(QualType T,        Invalid = true;      } -    ParamTypes[Idx] = adjustFunctionParamType(ParamType); +    ParamTypes[Idx] = ParamType;    }    if (Invalid) @@ -856,9 +843,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,    // Determine the type of the declarator. Not all forms of declarator    // have a type.    QualType T; -  // The QualType referring to the type as written in source code. We can't use -  // T because it can change due to semantic analysis. -  QualType SourceTy;    switch (D.getKind()) {    case Declarator::DK_Abstract: @@ -872,7 +856,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,        T = Context.DependentTy;      } else {        bool isInvalid = false; -      T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid, SourceTy); +      T = ConvertDeclSpecToType(DS, D.getIdentifierLoc(), isInvalid);        if (isInvalid)          D.setInvalidType(true);        else if (OwnedDecl && DS.isTypeSpecOwned()) @@ -891,9 +875,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,      break;    } -  if (SourceTy.isNull()) -    SourceTy = T; -    if (T == Context.UndeducedAutoTy) {      int Error = -1; @@ -942,8 +923,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,    if (D.getIdentifier())      Name = D.getIdentifier(); -  bool ShouldBuildInfo = DInfo != 0; -    // Walk the DeclTypeInfo, building the recursive type as we go.    // DeclTypeInfos are ordered from the identifier out, which is    // opposite of what we want :). @@ -952,17 +931,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,      switch (DeclType.Kind) {      default: assert(0 && "Unknown decltype!");      case DeclaratorChunk::BlockPointer: -      if (ShouldBuildInfo) { -        if (SourceTy->isFunctionType()) -          SourceTy -            = Context.getQualifiedType(Context.getBlockPointerType(SourceTy), -                             Qualifiers::fromCVRMask(DeclType.Cls.TypeQuals)); -        else -          // If not function type Context::getBlockPointerType asserts, -          // so just give up. -          ShouldBuildInfo = false; -      } -        // If blocks are disabled, emit an error.        if (!LangOpts.Blocks)          Diag(DeclType.Loc, diag::err_blocks_disable); @@ -971,10 +939,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,                                  Name);        break;      case DeclaratorChunk::Pointer: -      //FIXME: Use ObjCObjectPointer for info when appropriate. -      if (ShouldBuildInfo) -        SourceTy = Context.getQualifiedType(Context.getPointerType(SourceTy), -                             Qualifiers::fromCVRMask(DeclType.Ptr.TypeQuals));        // Verify that we're not building a pointer to pointer to function with        // exception specification.        if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { @@ -995,14 +959,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,        Qualifiers Quals;        if (DeclType.Ref.HasRestrict) Quals.addRestrict(); -      if (ShouldBuildInfo) { -        if (DeclType.Ref.LValueRef) -          SourceTy = Context.getLValueReferenceType(SourceTy); -        else -          SourceTy = Context.getRValueReferenceType(SourceTy); -        SourceTy = Context.getQualifiedType(SourceTy, Quals); -      } -        // Verify that we're not building a reference to pointer to function with        // exception specification.        if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { @@ -1015,11 +971,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,        break;      }      case DeclaratorChunk::Array: { -      if (ShouldBuildInfo) -        // We just need to get an array type, the exact type doesn't matter. -        SourceTy = Context.getIncompleteArrayType(SourceTy, ArrayType::Normal, -                                                  DeclType.Arr.TypeQuals); -        // Verify that we're not building an array of pointers to function with        // exception specification.        if (getLangOptions().CPlusPlus && CheckDistantExceptionSpec(T)) { @@ -1051,24 +1002,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,        break;      }      case DeclaratorChunk::Function: { -      if (ShouldBuildInfo) { -        const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; -        llvm::SmallVector<QualType, 16> ArgTys; - -        for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { -          ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>(); -          if (Param) { -            QualType ArgTy = adjustFunctionParamType(Param->getType()); - -            ArgTys.push_back(ArgTy); -          } -        } -        SourceTy = Context.getFunctionType(SourceTy, ArgTys.data(), -                                           ArgTys.size(), -                                           FTI.isVariadic, -                                           FTI.TypeQuals); -      } -        // If the function declarator has a prototype (i.e. it is not () and        // does not have a K&R-style identifier list), then the arguments are part        // of the type, otherwise the argument list is (). @@ -1137,6 +1070,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,        } else if (FTI.ArgInfo[0].Param == 0) {          // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function definition.          Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration); +        D.setInvalidType(true);        } else {          // Otherwise, we have a function with an argument list that is          // potentially variadic. @@ -1185,7 +1119,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,              }            } -          ArgTys.push_back(adjustFunctionParamType(ArgTy)); +          ArgTys.push_back(ArgTy);          }          llvm::SmallVector<QualType, 4> Exceptions; @@ -1234,13 +1168,6 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,          D.setInvalidType(true);        } -      if (ShouldBuildInfo) { -        QualType cls = !ClsType.isNull() ? ClsType : Context.IntTy; -        SourceTy = Context.getQualifiedType( -                      Context.getMemberPointerType(SourceTy, cls.getTypePtr()), -                      Qualifiers::fromCVRMask(DeclType.Mem.TypeQuals)); -      } -        if (!ClsType.isNull())          T = BuildMemberPointerType(T, ClsType, DeclType.Mem.TypeQuals,                                     DeclType.Loc, D.getIdentifier()); @@ -1293,106 +1220,162 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S,    if (const AttributeList *Attrs = D.getAttributes())      ProcessTypeAttributeList(T, Attrs); -  if (ShouldBuildInfo) -    *DInfo = GetDeclaratorInfoForDeclarator(D, SourceTy, Skip); +  if (DInfo) { +    if (D.isInvalidType()) +      *DInfo = 0; +    else +      *DInfo = GetDeclaratorInfoForDeclarator(D, T, Skip); +  }    return T;  } -static void FillTypeSpecLoc(TypeLoc TSL, const DeclSpec &DS) { -  if (TSL.isNull()) return; +namespace { +  class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> { +    const DeclSpec &DS; -  if (TypedefLoc *TL = dyn_cast<TypedefLoc>(&TSL)) { -    TL->setNameLoc(DS.getTypeSpecTypeLoc()); +  public: +    TypeSpecLocFiller(const DeclSpec &DS) : DS(DS) {} -  } else if (ObjCInterfaceLoc *TL = dyn_cast<ObjCInterfaceLoc>(&TSL)) { -    TL->setNameLoc(DS.getTypeSpecTypeLoc()); +    void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { +      Visit(TL.getUnqualifiedLoc()); +    } +    void VisitTypedefTypeLoc(TypedefTypeLoc TL) { +      TL.setNameLoc(DS.getTypeSpecTypeLoc()); +    } +    void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { +      TL.setNameLoc(DS.getTypeSpecTypeLoc()); + +      if (DS.getProtocolQualifiers()) { +        assert(TL.getNumProtocols() > 0); +        assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); +        TL.setLAngleLoc(DS.getProtocolLAngleLoc()); +        TL.setRAngleLoc(DS.getSourceRange().getEnd()); +        for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i) +          TL.setProtocolLoc(i, DS.getProtocolLocs()[i]); +      } else { +        assert(TL.getNumProtocols() == 0); +        TL.setLAngleLoc(SourceLocation()); +        TL.setRAngleLoc(SourceLocation()); +      } +    } +    void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { +      assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); -  } else if (ObjCProtocolListLoc *PLL = dyn_cast<ObjCProtocolListLoc>(&TSL)) { -    assert(PLL->getNumProtocols() == DS.getNumProtocolQualifiers()); -    PLL->setLAngleLoc(DS.getProtocolLAngleLoc()); -    PLL->setRAngleLoc(DS.getSourceRange().getEnd()); -    for (unsigned i = 0; i != DS.getNumProtocolQualifiers(); ++i) -      PLL->setProtocolLoc(i, DS.getProtocolLocs()[i]); -    FillTypeSpecLoc(PLL->getBaseTypeLoc(), DS); +      TL.setStarLoc(SourceLocation()); -  } else { -    //FIXME: Other typespecs. -    DefaultTypeSpecLoc &DTL = cast<DefaultTypeSpecLoc>(TSL); -    DTL.setStartLoc(DS.getSourceRange().getBegin()); -  } -} +      if (DS.getProtocolQualifiers()) { +        assert(TL.getNumProtocols() > 0); +        assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); +        TL.setHasProtocolsAsWritten(true); +        TL.setLAngleLoc(DS.getProtocolLAngleLoc()); +        TL.setRAngleLoc(DS.getSourceRange().getEnd()); +        for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i) +          TL.setProtocolLoc(i, DS.getProtocolLocs()[i]); -/// \brief Create and instantiate a DeclaratorInfo with type source information. -/// -/// \param T QualType referring to the type as written in source code. -DeclaratorInfo * -Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) { -  DeclaratorInfo *DInfo = Context.CreateDeclaratorInfo(T); -  TypeLoc CurrTL = DInfo->getTypeLoc(); +      } else { +        assert(TL.getNumProtocols() == 0); +        TL.setHasProtocolsAsWritten(false); +        TL.setLAngleLoc(SourceLocation()); +        TL.setRAngleLoc(SourceLocation()); +      } -  for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) { -    assert(!CurrTL.isNull()); -     -    // Don't bother recording source locations for qualifiers. -    CurrTL = CurrTL.getUnqualifiedLoc(); +      // This might not have been written with an inner type. +      if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { +        TL.setHasBaseTypeAsWritten(false); +        TL.getBaseTypeLoc().initialize(SourceLocation()); +      } else { +        TL.setHasBaseTypeAsWritten(true); +        Visit(TL.getBaseTypeLoc()); +      } +    } +    void VisitTypeLoc(TypeLoc TL) { +      // FIXME: add other typespec types and change this to an assert. +      TL.initialize(DS.getTypeSpecTypeLoc()); +    } +  }; -    DeclaratorChunk &DeclType = D.getTypeObject(i); -    switch (DeclType.Kind) { -    default: assert(0 && "Unknown decltype!"); -    case DeclaratorChunk::BlockPointer: { -      BlockPointerLoc &BPL = cast<BlockPointerLoc>(CurrTL); -      BPL.setCaretLoc(DeclType.Loc); -      break; +  class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> { +    const DeclaratorChunk &Chunk; + +  public: +    DeclaratorLocFiller(const DeclaratorChunk &Chunk) : Chunk(Chunk) {} + +    void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { +      llvm::llvm_unreachable("qualified type locs not expected here!");      } -    case DeclaratorChunk::Pointer: { -      //FIXME: ObjCObject pointers. -      PointerLoc &PL = cast<PointerLoc>(CurrTL); -      PL.setStarLoc(DeclType.Loc); -      break; + +    void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) { +      assert(Chunk.Kind == DeclaratorChunk::BlockPointer); +      TL.setCaretLoc(Chunk.Loc);      } -    case DeclaratorChunk::Reference: { -      ReferenceLoc &RL = cast<ReferenceLoc>(CurrTL); -      RL.setAmpLoc(DeclType.Loc); -      break; +    void VisitPointerTypeLoc(PointerTypeLoc TL) { +      assert(Chunk.Kind == DeclaratorChunk::Pointer); +      TL.setStarLoc(Chunk.Loc);      } -    case DeclaratorChunk::Array: { -      DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr; -      ArrayLoc &AL = cast<ArrayLoc>(CurrTL); -      AL.setLBracketLoc(DeclType.Loc); -      AL.setRBracketLoc(DeclType.EndLoc); -      AL.setSizeExpr(static_cast<Expr*>(ATI.NumElts)); -      //FIXME: Star location for [*]. -      break; +    void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { +      assert(Chunk.Kind == DeclaratorChunk::Pointer); +      TL.setStarLoc(Chunk.Loc); +      TL.setHasBaseTypeAsWritten(true); +      TL.setHasProtocolsAsWritten(false); +      TL.setLAngleLoc(SourceLocation()); +      TL.setRAngleLoc(SourceLocation());      } -    case DeclaratorChunk::Function: { -      const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; -      FunctionLoc &FL = cast<FunctionLoc>(CurrTL); -      FL.setLParenLoc(DeclType.Loc); -      FL.setRParenLoc(DeclType.EndLoc); -      for (unsigned i = 0, e = FTI.NumArgs, tpi = 0; i != e; ++i) { +    void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { +      assert(Chunk.Kind == DeclaratorChunk::MemberPointer); +      TL.setStarLoc(Chunk.Loc); +      // FIXME: nested name specifier +    } +    void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { +      assert(Chunk.Kind == DeclaratorChunk::Reference); +      // 'Amp' is misleading: this might have been originally +      /// spelled with AmpAmp. +      TL.setAmpLoc(Chunk.Loc); +    } +    void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { +      assert(Chunk.Kind == DeclaratorChunk::Reference); +      assert(!Chunk.Ref.LValueRef); +      TL.setAmpAmpLoc(Chunk.Loc); +    } +    void VisitArrayTypeLoc(ArrayTypeLoc TL) { +      assert(Chunk.Kind == DeclaratorChunk::Array); +      TL.setLBracketLoc(Chunk.Loc); +      TL.setRBracketLoc(Chunk.EndLoc); +      TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts)); +    } +    void VisitFunctionTypeLoc(FunctionTypeLoc TL) { +      assert(Chunk.Kind == DeclaratorChunk::Function); +      TL.setLParenLoc(Chunk.Loc); +      TL.setRParenLoc(Chunk.EndLoc); + +      const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; +      for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {          ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>(); -        if (Param) { -          assert(tpi < FL.getNumArgs()); -          FL.setArg(tpi++, Param); -        } +        TL.setArg(tpi++, Param);        } -      break; -      //FIXME: Exception specs. -    } -    case DeclaratorChunk::MemberPointer: { -      MemberPointerLoc &MPL = cast<MemberPointerLoc>(CurrTL); -      MPL.setStarLoc(DeclType.Loc); -      //FIXME: Class location. -      break; +      // FIXME: exception specs      } +    void VisitTypeLoc(TypeLoc TL) { +      llvm::llvm_unreachable("unsupported TypeLoc kind in declarator!");      } +  }; +} + +/// \brief Create and instantiate a DeclaratorInfo with type source information. +/// +/// \param T QualType referring to the type as written in source code. +DeclaratorInfo * +Sema::GetDeclaratorInfoForDeclarator(Declarator &D, QualType T, unsigned Skip) { +  DeclaratorInfo *DInfo = Context.CreateDeclaratorInfo(T); +  UnqualTypeLoc CurrTL = DInfo->getTypeLoc().getUnqualifiedLoc(); -    CurrTL = CurrTL.getNextTypeLoc(); +  for (unsigned i = Skip, e = D.getNumTypeObjects(); i != e; ++i) { +    DeclaratorLocFiller(D.getTypeObject(i)).Visit(CurrTL); +    CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();    } -  FillTypeSpecLoc(CurrTL, D.getDeclSpec()); +  TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);    return DInfo;  } @@ -1655,6 +1638,8 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,                                           PartialDiagnostic> Note) {    unsigned diag = PD.getDiagID(); +  // FIXME: Add this assertion to make sure we always get instantiation points. +  //  assert(!Loc.isInvalid() && "Invalid location in RequireCompleteType");    // FIXME: Add this assertion to help us flush out problems with    // checking for dependent types and type-dependent expressions.    // diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index ec5c6676f5d2..7e0972fe03c4 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -1,4 +1,4 @@ -//===------- TreeTransform.h - Semantic Tree Transformation ---------------===/ +//===------- TreeTransform.h - Semantic Tree Transformation -----*- C++ -*-===/  //  //                     The LLVM Compiler Infrastructure  // @@ -22,9 +22,11 @@  #include "clang/AST/Stmt.h"  #include "clang/AST/StmtCXX.h"  #include "clang/AST/StmtObjC.h" +#include "clang/AST/TypeLocBuilder.h"  #include "clang/Parse/Ownership.h"  #include "clang/Parse/Designator.h"  #include "clang/Lex/Preprocessor.h" +#include "llvm/Support/ErrorHandling.h"  #include <algorithm>  namespace clang { @@ -170,25 +172,30 @@ public:    /// \brief Transforms the given type into another type.    /// -  /// By default, this routine transforms a type by delegating to the -  /// appropriate TransformXXXType to build a new type, then applying -  /// the qualifiers on \p T to the resulting type with AddTypeQualifiers. -  /// Subclasses may override this function (to take over all type -  /// transformations), some set of the TransformXXXType functions, or -  /// the AddTypeQualifiers function to alter the transformation. +  /// By default, this routine transforms a type by creating a +  /// DeclaratorInfo for it and delegating to the appropriate +  /// function.  This is expensive, but we don't mind, because +  /// this method is deprecated anyway;  all users should be +  /// switched to storing DeclaratorInfos.    ///    /// \returns the transformed type.    QualType TransformType(QualType T); -  /// \brief Transform the given type by adding the given set of qualifiers -  /// and returning the result. +  /// \brief Transforms the given type-with-location into a new +  /// type-with-location. +  /// +  /// By default, this routine transforms a type by delegating to the +  /// appropriate TransformXXXType to build a new type.  Subclasses +  /// may override this function (to take over all type +  /// transformations) or some set of the TransformXXXType functions +  /// to alter the transformation. +  DeclaratorInfo *TransformType(DeclaratorInfo *DI); + +  /// \brief Transform the given type-with-location into a new +  /// type, collecting location information in the given builder +  /// as necessary.    /// -  /// FIXME: By default, this routine adds type qualifiers only to types that -  /// can have qualifiers, and silently suppresses those qualifiers that are -  /// not permitted (e.g., qualifiers on reference or function types). This -  /// is the right thing for template instantiation, but probably not for -  /// other clients. -  QualType AddTypeQualifiers(QualType T, Qualifiers Qs); +  QualType TransformType(TypeLocBuilder &TLB, TypeLoc TL);    /// \brief Transform the given statement.    /// @@ -236,6 +243,19 @@ public:    /// Subclasses may override this function to provide alternate behavior.    Decl *TransformDefinition(Decl *D) { return getDerived().TransformDecl(D); } +  /// \brief Transform the given declaration, which was the first part of a +  /// nested-name-specifier in a member access expression. +  /// +  /// This specific declaration transformation only applies to the first  +  /// identifier in a nested-name-specifier of a member access expression, e.g., +  /// the \c T in \c x->T::member +  /// +  /// By default, invokes TransformDecl() to transform the declaration. +  /// Subclasses may override this function to provide alternate behavior. +  NamedDecl *TransformFirstQualifierInScope(NamedDecl *D, SourceLocation Loc) {  +    return cast_or_null<NamedDecl>(getDerived().TransformDecl(D));  +  } +      /// \brief Transform the given nested-name-specifier.    ///    /// By default, transforms all of the types and declarations within the @@ -253,7 +273,8 @@ public:    /// Identifiers and selectors are returned unmodified. Sublcasses may    /// override this function to provide alternate behavior.    DeclarationName TransformDeclarationName(DeclarationName Name, -                                           SourceLocation Loc); +                                           SourceLocation Loc, +                                           QualType ObjectType = QualType());    /// \brief Transform the given template name.    /// @@ -271,11 +292,15 @@ public:    /// override this function to provide alternate behavior.    TemplateArgument TransformTemplateArgument(const TemplateArgument &Arg); -#define ABSTRACT_TYPE(CLASS, PARENT) -#define TYPE(CLASS, PARENT)                                   \ -  QualType Transform##CLASS##Type(const CLASS##Type *T); -#include "clang/AST/TypeNodes.def" +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT)                                   \ +  QualType Transform##CLASS##Type(TypeLocBuilder &TLB, CLASS##TypeLoc T); +#include "clang/AST/TypeLocNodes.def" +  QualType  +  TransformTemplateSpecializationType(const TemplateSpecializationType *T, +                                      QualType ObjectType); +      OwningStmtResult TransformCompoundStmt(CompoundStmt *S, bool IsStmtExpr);  #define STMT(Node, Parent)                        \ @@ -316,6 +341,9 @@ public:    /// type. Subclasses may override this routine to provide different behavior.    QualType RebuildMemberPointerType(QualType PointeeType, QualType ClassType); +  /// \brief Build a new Objective C object pointer type. +  QualType RebuildObjCObjectPointerType(QualType PointeeType); +    /// \brief Build a new array type given the element type, size    /// modifier, size of the array (if known), size expression, and index type    /// qualifiers. @@ -340,29 +368,6 @@ public:                                      const llvm::APInt &Size,                                      unsigned IndexTypeQuals); -  /// \brief Build a new constant array type given the element type, size -  /// modifier, (known) size of the array, size expression, and index type -  /// qualifiers. -  /// -  /// By default, performs semantic analysis when building the array type. -  /// Subclasses may override this routine to provide different behavior. -  QualType RebuildConstantArrayWithExprType(QualType ElementType, -                                            ArrayType::ArraySizeModifier SizeMod, -                                            const llvm::APInt &Size, -                                            Expr *SizeExpr, -                                            unsigned IndexTypeQuals, -                                            SourceRange BracketsRange); - -  /// \brief Build a new constant array type given the element type, size -  /// modifier, (known) size of the array, and index type qualifiers. -  /// -  /// By default, performs semantic analysis when building the array type. -  /// Subclasses may override this routine to provide different behavior. -  QualType RebuildConstantArrayWithoutExprType(QualType ElementType, -                                               ArrayType::ArraySizeModifier SizeMod, -                                               const llvm::APInt &Size, -                                               unsigned IndexTypeQuals); -    /// \brief Build a new incomplete array type given the element type, size    /// modifier, and index type qualifiers.    /// @@ -427,6 +432,9 @@ public:                                      unsigned NumParamTypes,                                      bool Variadic, unsigned Quals); +  /// \brief Build a new unprototyped function type. +  QualType RebuildFunctionNoProtoType(QualType ResultType); +    /// \brief Build a new typedef type.    QualType RebuildTypedefType(TypedefDecl *Typedef) {      return SemaRef.Context.getTypeDeclType(Typedef); @@ -1429,13 +1437,16 @@ public:    ///    /// By default, performs semantic analysis to build the new expression.    /// Subclasses may override this routine to provide different behavior. -  OwningExprResult RebuildTemplateIdExpr(TemplateName Template, +  OwningExprResult RebuildTemplateIdExpr(NestedNameSpecifier *Qualifier, +                                         SourceRange QualifierRange, +                                         TemplateName Template,                                           SourceLocation TemplateLoc,                                           SourceLocation LAngleLoc,                                           TemplateArgument *TemplateArgs,                                           unsigned NumTemplateArgs,                                           SourceLocation RAngleLoc) { -    return getSema().BuildTemplateIdExpr(Template, TemplateLoc, +    return getSema().BuildTemplateIdExpr(Qualifier, QualifierRange, +                                         Template, TemplateLoc,                                           LAngleLoc,                                           TemplateArgs, NumTemplateArgs,                                           RAngleLoc); @@ -1757,7 +1768,8 @@ TreeTransform<Derived>::TransformNestedNameSpecifier(NestedNameSpecifier *NNS,  template<typename Derived>  DeclarationName  TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name, -                                                 SourceLocation Loc) { +                                                 SourceLocation Loc, +                                                 QualType ObjectType) {    if (!Name)      return Name; @@ -1774,7 +1786,14 @@ TreeTransform<Derived>::TransformDeclarationName(DeclarationName Name,    case DeclarationName::CXXDestructorName:    case DeclarationName::CXXConversionFunctionName: {      TemporaryBase Rebase(*this, Loc, Name); -    QualType T = getDerived().TransformType(Name.getCXXNameType()); +    QualType T; +    if (!ObjectType.isNull() &&  +        isa<TemplateSpecializationType>(Name.getCXXNameType())) { +      TemplateSpecializationType *SpecType +        = cast<TemplateSpecializationType>(Name.getCXXNameType()); +      T = TransformTemplateSpecializationType(SpecType, ObjectType); +    } else +      T = getDerived().TransformType(Name.getCXXNameType());      if (T.isNull())        return DeclarationName(); @@ -1837,7 +1856,8 @@ TreeTransform<Derived>::TransformTemplateName(TemplateName Name,        return TemplateName();      if (!getDerived().AlwaysRebuild() && -        NNS == DTN->getQualifier()) +        NNS == DTN->getQualifier() && +        ObjectType.isNull())        return Name;      return getDerived().RebuildTemplateName(NNS, *DTN->getName(), ObjectType); @@ -1935,268 +1955,369 @@ QualType TreeTransform<Derived>::TransformType(QualType T) {    if (getDerived().AlreadyTransformed(T))      return T; -  QualifierCollector Qs; -  const Type *Ty = Qs.strip(T); +  // Temporary workaround.  All of these transformations should +  // eventually turn into transformations on TypeLocs. +  DeclaratorInfo *DI = getSema().Context.CreateDeclaratorInfo(T); +  DI->getTypeLoc().initialize(getDerived().getBaseLocation()); +   +  DeclaratorInfo *NewDI = getDerived().TransformType(DI); -  QualType Result; -  switch (Ty->getTypeClass()) { -#define ABSTRACT_TYPE(CLASS, PARENT) -#define TYPE(CLASS, PARENT)                                                  \ -    case Type::CLASS:                                                        \ -      Result = getDerived().Transform##CLASS##Type(                          \ -                                       static_cast<const CLASS##Type*>(Ty)); \ -      break; -#include "clang/AST/TypeNodes.def" -  } - -  if (Result.isNull() || T == Result) -    return Result; +  if (!NewDI) +    return QualType(); -  return getDerived().AddTypeQualifiers(Result, Qs); +  return NewDI->getType();  }  template<typename Derived> -QualType -TreeTransform<Derived>::AddTypeQualifiers(QualType T, Qualifiers Quals) { -  if (!Quals.empty() && !T->isFunctionType() && !T->isReferenceType()) -    return SemaRef.Context.getQualifiedType(T, Quals); +DeclaratorInfo *TreeTransform<Derived>::TransformType(DeclaratorInfo *DI) { +  if (getDerived().AlreadyTransformed(DI->getType())) +    return DI; -  return T; -} +  TypeLocBuilder TLB; -template<typename Derived> -QualType TreeTransform<Derived>::TransformBuiltinType(const BuiltinType *T) { -  // Nothing to do -  return QualType(T, 0); -} +  TypeLoc TL = DI->getTypeLoc(); +  TLB.reserve(TL.getFullDataSize()); -template<typename Derived> -QualType TreeTransform<Derived>::TransformFixedWidthIntType( -                                                  const FixedWidthIntType *T) { -  // FIXME: Implement -  return QualType(T, 0); -} +  QualType Result = getDerived().TransformType(TLB, TL); +  if (Result.isNull()) +    return 0; -template<typename Derived> -QualType TreeTransform<Derived>::TransformComplexType(const ComplexType *T) { -  // FIXME: Implement -  return QualType(T, 0); +  return TLB.getDeclaratorInfo(SemaRef.Context, Result);  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformPointerType(const PointerType *T) { -  QualType PointeeType = getDerived().TransformType(T->getPointeeType()); -  if (PointeeType.isNull()) -    return QualType(); - -  if (!getDerived().AlwaysRebuild() && -      PointeeType == T->getPointeeType()) -    return QualType(T, 0); +QualType +TreeTransform<Derived>::TransformType(TypeLocBuilder &TLB, TypeLoc T) { +  switch (T.getTypeLocClass()) { +#define ABSTRACT_TYPELOC(CLASS, PARENT) +#define TYPELOC(CLASS, PARENT) \ +  case TypeLoc::CLASS: \ +    return getDerived().Transform##CLASS##Type(TLB, cast<CLASS##TypeLoc>(T)); +#include "clang/AST/TypeLocNodes.def" +  } -  return getDerived().RebuildPointerType(PointeeType); +  llvm::llvm_unreachable("unhandled type loc!"); +  return QualType();  } +/// FIXME: By default, this routine adds type qualifiers only to types +/// that can have qualifiers, and silently suppresses those qualifiers +/// that are not permitted (e.g., qualifiers on reference or function +/// types). This is the right thing for template instantiation, but +/// probably not for other clients.  template<typename Derived>  QualType -TreeTransform<Derived>::TransformBlockPointerType(const BlockPointerType *T) { -  QualType PointeeType = getDerived().TransformType(T->getPointeeType()); -  if (PointeeType.isNull()) +TreeTransform<Derived>::TransformQualifiedType(TypeLocBuilder &TLB, +                                               QualifiedTypeLoc T) { +  Qualifiers Quals = T.getType().getQualifiers(); + +  QualType Result = getDerived().TransformType(TLB, T.getUnqualifiedLoc()); +  if (Result.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      PointeeType == T->getPointeeType()) -    return QualType(T, 0); +  // Silently suppress qualifiers if the result type can't be qualified. +  // FIXME: this is the right thing for template instantiation, but +  // probably not for other clients. +  if (Result->isFunctionType() || Result->isReferenceType()) +    return Result; -  return getDerived().RebuildBlockPointerType(PointeeType); +  Result = SemaRef.Context.getQualifiedType(Result, Quals); + +  TLB.push<QualifiedTypeLoc>(Result); + +  // No location information to preserve. + +  return Result; +} + +template <class TyLoc> static inline +QualType TransformTypeSpecType(TypeLocBuilder &TLB, TyLoc T) { +  TyLoc NewT = TLB.push<TyLoc>(T.getType()); +  NewT.setNameLoc(T.getNameLoc()); +  return T.getType(); +} + +// Ugly metaprogramming macros because I couldn't be bothered to make +// the equivalent template version work. +#define TransformPointerLikeType(TypeClass) do { \ +  QualType PointeeType                                       \ +    = getDerived().TransformType(TLB, TL.getPointeeLoc());   \ +  if (PointeeType.isNull())                                  \ +    return QualType();                                       \ +                                                             \ +  QualType Result = TL.getType();                            \ +  if (getDerived().AlwaysRebuild() ||                        \ +      PointeeType != TL.getPointeeLoc().getType()) {         \ +    Result = getDerived().Rebuild##TypeClass(PointeeType);   \ +    if (Result.isNull())                                     \ +      return QualType();                                     \ +  }                                                          \ +                                                             \ +  TypeClass##Loc NewT = TLB.push<TypeClass##Loc>(Result);    \ +  NewT.setSigilLoc(TL.getSigilLoc());                        \ +                                                             \ +  return Result;                                             \ +} while(0) + +// Reference collapsing forces us to transform reference types +// differently from the other pointer-like types. +#define TransformReferenceType(TypeClass) do { \ +  QualType PointeeType                                       \ +    = getDerived().TransformType(TLB, TL.getPointeeLoc());   \ +  if (PointeeType.isNull())                                  \ +    return QualType();                                       \ +                                                             \ +  QualType Result = TL.getType();                            \ +  if (getDerived().AlwaysRebuild() ||                        \ +      PointeeType != TL.getPointeeLoc().getType()) {         \ +    Result = getDerived().Rebuild##TypeClass(PointeeType);   \ +    if (Result.isNull())                                     \ +      return QualType();                                     \ +  }                                                          \ +                                                             \ +  /* Workaround: rebuild doesn't always change the type */   \ +  /* FIXME: avoid losing this location information. */       \ +  if (Result == PointeeType)                                 \ +    return Result;                                           \ +  ReferenceTypeLoc NewTL;                                    \ +  if (isa<LValueReferenceType>(Result))                      \ +    NewTL = TLB.push<LValueReferenceTypeLoc>(Result);        \ +  else                                                       \ +    NewTL = TLB.push<RValueReferenceTypeLoc>(Result);        \ +  NewTL.setSigilLoc(TL.getSigilLoc());                       \ +  return Result;                                             \ +} while (0) + +template<typename Derived> +QualType TreeTransform<Derived>::TransformBuiltinType(TypeLocBuilder &TLB, +                                                      BuiltinTypeLoc T) { +  return TransformTypeSpecType(TLB, T);  }  template<typename Derived>  QualType -TreeTransform<Derived>::TransformLValueReferenceType( -                                               const LValueReferenceType *T) { -  QualType PointeeType = getDerived().TransformType(T->getPointeeType()); -  if (PointeeType.isNull()) -    return QualType(); +TreeTransform<Derived>::TransformFixedWidthIntType(TypeLocBuilder &TLB, +                                                   FixedWidthIntTypeLoc T) { +  return TransformTypeSpecType(TLB, T); +} -  if (!getDerived().AlwaysRebuild() && -      PointeeType == T->getPointeeType()) -    return QualType(T, 0); +template<typename Derived> +QualType TreeTransform<Derived>::TransformComplexType(TypeLocBuilder &TLB, +                                                      ComplexTypeLoc T) { +  // FIXME: recurse? +  return TransformTypeSpecType(TLB, T); +} -  return getDerived().RebuildLValueReferenceType(PointeeType); +template<typename Derived> +QualType TreeTransform<Derived>::TransformPointerType(TypeLocBuilder &TLB, +                                                      PointerTypeLoc TL) { +  TransformPointerLikeType(PointerType);  }  template<typename Derived>  QualType -TreeTransform<Derived>::TransformRValueReferenceType( -                                              const RValueReferenceType *T) { -  QualType PointeeType = getDerived().TransformType(T->getPointeeType()); -  if (PointeeType.isNull()) -    return QualType(); - -  if (!getDerived().AlwaysRebuild() && -      PointeeType == T->getPointeeType()) -    return QualType(T, 0); - -  return getDerived().RebuildRValueReferenceType(PointeeType); +TreeTransform<Derived>::TransformBlockPointerType(TypeLocBuilder &TLB, +                                                  BlockPointerTypeLoc TL) { +  TransformPointerLikeType(BlockPointerType);  }  template<typename Derived>  QualType -TreeTransform<Derived>::TransformMemberPointerType(const MemberPointerType *T) { -  QualType PointeeType = getDerived().TransformType(T->getPointeeType()); -  if (PointeeType.isNull()) -    return QualType(); - -  QualType ClassType = getDerived().TransformType(QualType(T->getClass(), 0)); -  if (ClassType.isNull()) -    return QualType(); - -  if (!getDerived().AlwaysRebuild() && -      PointeeType == T->getPointeeType() && -      ClassType == QualType(T->getClass(), 0)) -    return QualType(T, 0); - -  return getDerived().RebuildMemberPointerType(PointeeType, ClassType); +TreeTransform<Derived>::TransformLValueReferenceType(TypeLocBuilder &TLB, +                                                 LValueReferenceTypeLoc TL) { +  TransformReferenceType(LValueReferenceType);  }  template<typename Derived>  QualType -TreeTransform<Derived>::TransformConstantArrayType(const ConstantArrayType *T) { -  QualType ElementType = getDerived().TransformType(T->getElementType()); -  if (ElementType.isNull()) -    return QualType(); - -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType()) -    return QualType(T, 0); - -  return getDerived().RebuildConstantArrayType(ElementType, -                                               T->getSizeModifier(), -                                               T->getSize(), -                                               T->getIndexTypeCVRQualifiers()); +TreeTransform<Derived>::TransformRValueReferenceType(TypeLocBuilder &TLB, +                                                 RValueReferenceTypeLoc TL) { +  TransformReferenceType(RValueReferenceType);  }  template<typename Derived>  QualType -TreeTransform<Derived>::TransformConstantArrayWithExprType( -                                      const ConstantArrayWithExprType *T) { -  QualType ElementType = getDerived().TransformType(T->getElementType()); -  if (ElementType.isNull()) -    return QualType(); +TreeTransform<Derived>::TransformMemberPointerType(TypeLocBuilder &TLB, +                                                   MemberPointerTypeLoc TL) { +  MemberPointerType *T = TL.getTypePtr(); -  // Array bounds are not potentially evaluated contexts -  EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); +  QualType PointeeType = getDerived().TransformType(TLB, TL.getPointeeLoc()); +  if (PointeeType.isNull()) +    return QualType(); -  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); -  if (Size.isInvalid()) +  // TODO: preserve source information for this. +  QualType ClassType +    = getDerived().TransformType(QualType(T->getClass(), 0)); +  if (ClassType.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType() && -      Size.get() == T->getSizeExpr()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      PointeeType != T->getPointeeType() || +      ClassType != QualType(T->getClass(), 0)) { +    Result = getDerived().RebuildMemberPointerType(PointeeType, ClassType); +    if (Result.isNull()) +      return QualType(); +  } -  return getDerived().RebuildConstantArrayWithExprType(ElementType, -                                                       T->getSizeModifier(), -                                                       T->getSize(), -                                                       Size.takeAs<Expr>(), -                                               T->getIndexTypeCVRQualifiers(), -                                                       T->getBracketsRange()); +  MemberPointerTypeLoc NewTL = TLB.push<MemberPointerTypeLoc>(Result); +  NewTL.setSigilLoc(TL.getSigilLoc()); + +  return Result;  }  template<typename Derived>  QualType -TreeTransform<Derived>::TransformConstantArrayWithoutExprType( -                                      const ConstantArrayWithoutExprType *T) { -  QualType ElementType = getDerived().TransformType(T->getElementType()); +TreeTransform<Derived>::TransformConstantArrayType(TypeLocBuilder &TLB, +                                                   ConstantArrayTypeLoc TL) { +  ConstantArrayType *T = TL.getTypePtr(); +  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());    if (ElementType.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType()) -    return QualType(T, 0); - -  return getDerived().RebuildConstantArrayWithoutExprType(ElementType, -                                                       T->getSizeModifier(), -                                                       T->getSize(), +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      ElementType != T->getElementType()) { +    Result = getDerived().RebuildConstantArrayType(ElementType, +                                                   T->getSizeModifier(), +                                                   T->getSize(),                                               T->getIndexTypeCVRQualifiers()); +    if (Result.isNull()) +      return QualType(); +  } +   +  ConstantArrayTypeLoc NewTL = TLB.push<ConstantArrayTypeLoc>(Result); +  NewTL.setLBracketLoc(TL.getLBracketLoc()); +  NewTL.setRBracketLoc(TL.getRBracketLoc()); + +  Expr *Size = TL.getSizeExpr(); +  if (Size) { +    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); +    Size = getDerived().TransformExpr(Size).template takeAs<Expr>(); +  } +  NewTL.setSizeExpr(Size); + +  return Result;  }  template<typename Derived>  QualType TreeTransform<Derived>::TransformIncompleteArrayType( -                                              const IncompleteArrayType *T) { -  QualType ElementType = getDerived().TransformType(T->getElementType()); +                                              TypeLocBuilder &TLB, +                                              IncompleteArrayTypeLoc TL) { +  IncompleteArrayType *T = TL.getTypePtr(); +  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());    if (ElementType.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      ElementType != T->getElementType()) { +    Result = getDerived().RebuildIncompleteArrayType(ElementType, +                                                     T->getSizeModifier(), +                                             T->getIndexTypeCVRQualifiers()); +    if (Result.isNull()) +      return QualType(); +  } +   +  IncompleteArrayTypeLoc NewTL = TLB.push<IncompleteArrayTypeLoc>(Result); +  NewTL.setLBracketLoc(TL.getLBracketLoc()); +  NewTL.setRBracketLoc(TL.getRBracketLoc()); +  NewTL.setSizeExpr(0); -  return getDerived().RebuildIncompleteArrayType(ElementType, -                                                 T->getSizeModifier(), -                                               T->getIndexTypeCVRQualifiers()); +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformVariableArrayType( -                                                  const VariableArrayType *T) { -  QualType ElementType = getDerived().TransformType(T->getElementType()); +QualType +TreeTransform<Derived>::TransformVariableArrayType(TypeLocBuilder &TLB, +                                                   VariableArrayTypeLoc TL) { +  VariableArrayType *T = TL.getTypePtr(); +  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());    if (ElementType.isNull())      return QualType();    // Array bounds are not potentially evaluated contexts    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); -  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); -  if (Size.isInvalid()) +  Sema::OwningExprResult SizeResult +    = getDerived().TransformExpr(T->getSizeExpr()); +  if (SizeResult.isInvalid())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType() && -      Size.get() == T->getSizeExpr()) { -    Size.take(); -    return QualType(T, 0); +  Expr *Size = static_cast<Expr*>(SizeResult.get()); + +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      ElementType != T->getElementType() || +      Size != T->getSizeExpr()) { +    Result = getDerived().RebuildVariableArrayType(ElementType, +                                                   T->getSizeModifier(), +                                                   move(SizeResult), +                                             T->getIndexTypeCVRQualifiers(), +                                                   T->getBracketsRange()); +    if (Result.isNull()) +      return QualType();    } +  else SizeResult.take(); +   +  VariableArrayTypeLoc NewTL = TLB.push<VariableArrayTypeLoc>(Result); +  NewTL.setLBracketLoc(TL.getLBracketLoc()); +  NewTL.setRBracketLoc(TL.getRBracketLoc()); +  NewTL.setSizeExpr(Size); -  return getDerived().RebuildVariableArrayType(ElementType, -                                               T->getSizeModifier(), -                                               move(Size), -                                               T->getIndexTypeCVRQualifiers(), -                                               T->getBracketsRange()); +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformDependentSizedArrayType( -                                          const DependentSizedArrayType *T) { -  QualType ElementType = getDerived().TransformType(T->getElementType()); +QualType +TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB, +                                             DependentSizedArrayTypeLoc TL) { +  DependentSizedArrayType *T = TL.getTypePtr(); +  QualType ElementType = getDerived().TransformType(TLB, TL.getElementLoc());    if (ElementType.isNull())      return QualType();    // Array bounds are not potentially evaluated contexts    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); -  Sema::OwningExprResult Size = getDerived().TransformExpr(T->getSizeExpr()); -  if (Size.isInvalid()) +  Sema::OwningExprResult SizeResult +    = getDerived().TransformExpr(T->getSizeExpr()); +  if (SizeResult.isInvalid())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType() && -      Size.get() == T->getSizeExpr()) { -    Size.take(); -    return QualType(T, 0); +  Expr *Size = static_cast<Expr*>(SizeResult.get()); + +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      ElementType != T->getElementType() || +      Size != T->getSizeExpr()) { +    Result = getDerived().RebuildDependentSizedArrayType(ElementType, +                                                         T->getSizeModifier(), +                                                         move(SizeResult), +                                                T->getIndexTypeCVRQualifiers(), +                                                        T->getBracketsRange()); +    if (Result.isNull()) +      return QualType();    } +  else SizeResult.take(); -  return getDerived().RebuildDependentSizedArrayType(ElementType, -                                                     T->getSizeModifier(), -                                                     move(Size), -                                            T->getIndexTypeCVRQualifiers(), -                                                     T->getBracketsRange()); +  // We might have any sort of array type now, but fortunately they +  // all have the same location layout. +  ArrayTypeLoc NewTL = TLB.push<ArrayTypeLoc>(Result); +  NewTL.setLBracketLoc(TL.getLBracketLoc()); +  NewTL.setRBracketLoc(TL.getRBracketLoc()); +  NewTL.setSizeExpr(Size); + +  return Result;  }  template<typename Derived>  QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType( -                                      const DependentSizedExtVectorType *T) { +                                      TypeLocBuilder &TLB, +                                      DependentSizedExtVectorTypeLoc TL) { +  DependentSizedExtVectorType *T = TL.getTypePtr(); + +  // FIXME: ext vector locs should be nested    QualType ElementType = getDerived().TransformType(T->getElementType());    if (ElementType.isNull())      return QualType(); @@ -2208,98 +2329,201 @@ QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(    if (Size.isInvalid())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType() && -      Size.get() == T->getSizeExpr()) { -    Size.take(); -    return QualType(T, 0); -  } - -  return getDerived().RebuildDependentSizedExtVectorType(ElementType, +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      (ElementType != T->getElementType() && Size.get() != T->getSizeExpr())) { +    Result = getDerived().RebuildDependentSizedExtVectorType(ElementType,                                                           move(Size),                                                           T->getAttributeLoc()); +    if (Result.isNull()) +      return QualType(); +  } +  else Size.take(); + +  // Result might be dependent or not. +  if (isa<DependentSizedExtVectorType>(Result)) { +    DependentSizedExtVectorTypeLoc NewTL +      = TLB.push<DependentSizedExtVectorTypeLoc>(Result); +    NewTL.setNameLoc(TL.getNameLoc()); +  } else { +    ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result); +    NewTL.setNameLoc(TL.getNameLoc()); +  } + +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformVectorType(const VectorType *T) { +QualType TreeTransform<Derived>::TransformVectorType(TypeLocBuilder &TLB, +                                                     VectorTypeLoc TL) { +  VectorType *T = TL.getTypePtr();    QualType ElementType = getDerived().TransformType(T->getElementType());    if (ElementType.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      ElementType != T->getElementType()) { +    Result = getDerived().RebuildVectorType(ElementType, T->getNumElements()); +    if (Result.isNull()) +      return QualType(); +  } +   +  VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); -  return getDerived().RebuildVectorType(ElementType, T->getNumElements()); +  return Result;  }  template<typename Derived> -QualType -TreeTransform<Derived>::TransformExtVectorType(const ExtVectorType *T) { +QualType TreeTransform<Derived>::TransformExtVectorType(TypeLocBuilder &TLB, +                                                        ExtVectorTypeLoc TL) { +  VectorType *T = TL.getTypePtr();    QualType ElementType = getDerived().TransformType(T->getElementType());    if (ElementType.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      ElementType == T->getElementType()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      ElementType != T->getElementType()) { +    Result = getDerived().RebuildExtVectorType(ElementType, +                                               T->getNumElements(), +                                               /*FIXME*/ SourceLocation()); +    if (Result.isNull()) +      return QualType(); +  } +   +  ExtVectorTypeLoc NewTL = TLB.push<ExtVectorTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); -  return getDerived().RebuildExtVectorType(ElementType, T->getNumElements(), -                                           /*FIXME*/SourceLocation()); +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformFunctionProtoType( -                                                  const FunctionProtoType *T) { -  QualType ResultType = getDerived().TransformType(T->getResultType()); +QualType +TreeTransform<Derived>::TransformFunctionProtoType(TypeLocBuilder &TLB, +                                                   FunctionProtoTypeLoc TL) { +  FunctionProtoType *T = TL.getTypePtr(); +  QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc());    if (ResultType.isNull())      return QualType(); +  // Transform the parameters.    llvm::SmallVector<QualType, 4> ParamTypes; -  for (FunctionProtoType::arg_type_iterator Param = T->arg_type_begin(), -                                         ParamEnd = T->arg_type_end(); -       Param != ParamEnd; ++Param) { -    QualType P = getDerived().TransformType(*Param); -    if (P.isNull()) -      return QualType(); +  llvm::SmallVector<ParmVarDecl*, 4> ParamDecls; +  for (unsigned i = 0, e = TL.getNumArgs(); i != e; ++i) { +    ParmVarDecl *OldParm = TL.getArg(i); + +    QualType NewType; +    ParmVarDecl *NewParm; + +    if (OldParm) { +      DeclaratorInfo *OldDI = OldParm->getDeclaratorInfo(); +      assert(OldDI->getType() == T->getArgType(i)); + +      DeclaratorInfo *NewDI = getDerived().TransformType(OldDI); +      if (!NewDI) +        return QualType(); + +      if (NewDI == OldDI) +        NewParm = OldParm; +      else +        NewParm = ParmVarDecl::Create(SemaRef.Context, +                                      OldParm->getDeclContext(), +                                      OldParm->getLocation(), +                                      OldParm->getIdentifier(), +                                      NewDI->getType(), +                                      NewDI, +                                      OldParm->getStorageClass(), +                                      /* DefArg */ NULL); +      NewType = NewParm->getType(); + +    // Deal with the possibility that we don't have a parameter +    // declaration for this parameter. +    } else { +      NewParm = 0; + +      QualType OldType = T->getArgType(i); +      NewType = getDerived().TransformType(OldType); +      if (NewType.isNull()) +        return QualType(); +    } -    ParamTypes.push_back(P); +    ParamTypes.push_back(NewType); +    ParamDecls.push_back(NewParm);    } -  if (!getDerived().AlwaysRebuild() && -      ResultType == T->getResultType() && -      std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      ResultType != T->getResultType() || +      !std::equal(T->arg_type_begin(), T->arg_type_end(), ParamTypes.begin())) { +    Result = getDerived().RebuildFunctionProtoType(ResultType, +                                                   ParamTypes.data(), +                                                   ParamTypes.size(), +                                                   T->isVariadic(), +                                                   T->getTypeQuals()); +    if (Result.isNull()) +      return QualType(); +  } + +  FunctionProtoTypeLoc NewTL = TLB.push<FunctionProtoTypeLoc>(Result); +  NewTL.setLParenLoc(TL.getLParenLoc()); +  NewTL.setRParenLoc(TL.getRParenLoc()); +  for (unsigned i = 0, e = NewTL.getNumArgs(); i != e; ++i) +    NewTL.setArg(i, ParamDecls[i]); -  return getDerived().RebuildFunctionProtoType(ResultType, ParamTypes.data(), -                                               ParamTypes.size(), T->isVariadic(), -                                               T->getTypeQuals()); +  return Result;  }  template<typename Derived>  QualType TreeTransform<Derived>::TransformFunctionNoProtoType( -                                                const FunctionNoProtoType *T) { -  // FIXME: Implement -  return QualType(T, 0); +                                                 TypeLocBuilder &TLB, +                                                 FunctionNoProtoTypeLoc TL) { +  FunctionNoProtoType *T = TL.getTypePtr(); +  QualType ResultType = getDerived().TransformType(TLB, TL.getResultLoc()); +  if (ResultType.isNull()) +    return QualType(); + +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      ResultType != T->getResultType()) +    Result = getDerived().RebuildFunctionNoProtoType(ResultType); + +  FunctionNoProtoTypeLoc NewTL = TLB.push<FunctionNoProtoTypeLoc>(Result); +  NewTL.setLParenLoc(TL.getLParenLoc()); +  NewTL.setRParenLoc(TL.getRParenLoc()); + +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformTypedefType(const TypedefType *T) { +QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB, +                                                      TypedefTypeLoc TL) { +  TypedefType *T = TL.getTypePtr();    TypedefDecl *Typedef      = cast_or_null<TypedefDecl>(getDerived().TransformDecl(T->getDecl()));    if (!Typedef)      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      Typedef == T->getDecl()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      Typedef != T->getDecl()) { +    Result = getDerived().RebuildTypedefType(Typedef); +    if (Result.isNull()) +      return QualType(); +  } + +  TypedefTypeLoc NewTL = TLB.push<TypedefTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); -  return getDerived().RebuildTypedefType(Typedef); +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformTypeOfExprType( -                                                    const TypeOfExprType *T) { +QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB, +                                                      TypeOfExprTypeLoc TL) { +  TypeOfExprType *T = TL.getTypePtr(); +    // typeof expressions are not potentially evaluated contexts    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); @@ -2307,30 +2531,50 @@ QualType TreeTransform<Derived>::TransformTypeOfExprType(    if (E.isInvalid())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      E.get() == T->getUnderlyingExpr()) { -    E.take(); -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      E.get() != T->getUnderlyingExpr()) { +    Result = getDerived().RebuildTypeOfExprType(move(E)); +    if (Result.isNull()) +      return QualType();    } +  else E.take(); -  return getDerived().RebuildTypeOfExprType(move(E)); +  TypeOfExprTypeLoc NewTL = TLB.push<TypeOfExprTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); + +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformTypeOfType(const TypeOfType *T) { +QualType TreeTransform<Derived>::TransformTypeOfType(TypeLocBuilder &TLB, +                                                     TypeOfTypeLoc TL) { +  TypeOfType *T = TL.getTypePtr(); + +  // FIXME: should be an inner type, or at least have a DeclaratorInfo.    QualType Underlying = getDerived().TransformType(T->getUnderlyingType());    if (Underlying.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      Underlying == T->getUnderlyingType()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      Underlying != T->getUnderlyingType()) { +    Result = getDerived().RebuildTypeOfType(Underlying); +    if (Result.isNull()) +      return QualType(); +  } -  return getDerived().RebuildTypeOfType(Underlying); +  TypeOfTypeLoc NewTL = TLB.push<TypeOfTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); + +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) { +QualType TreeTransform<Derived>::TransformDecltypeType(TypeLocBuilder &TLB, +                                                       DecltypeTypeLoc TL) { +  DecltypeType *T = TL.getTypePtr(); +    // decltype expressions are not potentially evaluated contexts    EnterExpressionEvaluationContext Unevaluated(SemaRef, Action::Unevaluated); @@ -2338,70 +2582,130 @@ QualType TreeTransform<Derived>::TransformDecltypeType(const DecltypeType *T) {    if (E.isInvalid())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      E.get() == T->getUnderlyingExpr()) { -    E.take(); -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      E.get() != T->getUnderlyingExpr()) { +    Result = getDerived().RebuildDecltypeType(move(E)); +    if (Result.isNull()) +      return QualType();    } +  else E.take(); -  return getDerived().RebuildDecltypeType(move(E)); +  DecltypeTypeLoc NewTL = TLB.push<DecltypeTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); + +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformRecordType(const RecordType *T) { +QualType TreeTransform<Derived>::TransformRecordType(TypeLocBuilder &TLB, +                                                     RecordTypeLoc TL) { +  RecordType *T = TL.getTypePtr();    RecordDecl *Record -  = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl())); +    = cast_or_null<RecordDecl>(getDerived().TransformDecl(T->getDecl()));    if (!Record)      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      Record == T->getDecl()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      Record != T->getDecl()) { +    Result = getDerived().RebuildRecordType(Record); +    if (Result.isNull()) +      return QualType(); +  } + +  RecordTypeLoc NewTL = TLB.push<RecordTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); -  return getDerived().RebuildRecordType(Record); +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformEnumType(const EnumType *T) { +QualType TreeTransform<Derived>::TransformEnumType(TypeLocBuilder &TLB, +                                                   EnumTypeLoc TL) { +  EnumType *T = TL.getTypePtr();    EnumDecl *Enum -  = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl())); +    = cast_or_null<EnumDecl>(getDerived().TransformDecl(T->getDecl()));    if (!Enum)      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      Enum == T->getDecl()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      Enum != T->getDecl()) { +    Result = getDerived().RebuildEnumType(Enum); +    if (Result.isNull()) +      return QualType(); +  } + +  EnumTypeLoc NewTL = TLB.push<EnumTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); -  return getDerived().RebuildEnumType(Enum); +  return Result;  }  template <typename Derived> -QualType TreeTransform<Derived>::TransformElaboratedType( -                                                    const ElaboratedType *T) { +QualType TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, +                                                      ElaboratedTypeLoc TL) { +  ElaboratedType *T = TL.getTypePtr(); + +  // FIXME: this should be a nested type.    QualType Underlying = getDerived().TransformType(T->getUnderlyingType());    if (Underlying.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      Underlying == T->getUnderlyingType()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      Underlying != T->getUnderlyingType()) { +    Result = getDerived().RebuildElaboratedType(Underlying, T->getTagKind()); +    if (Result.isNull()) +      return QualType(); +  } + +  ElaboratedTypeLoc NewTL = TLB.push<ElaboratedTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); -  return getDerived().RebuildElaboratedType(Underlying, T->getTagKind()); +  return Result;  }  template<typename Derived>  QualType TreeTransform<Derived>::TransformTemplateTypeParmType( -                                              const TemplateTypeParmType *T) { -  // Nothing to do -  return QualType(T, 0); +                                                TypeLocBuilder &TLB, +                                                TemplateTypeParmTypeLoc TL) { +  return TransformTypeSpecType(TLB, TL);  }  template<typename Derived> +QualType TreeTransform<Derived>::TransformSubstTemplateTypeParmType( +                                         TypeLocBuilder &TLB, +                                         SubstTemplateTypeParmTypeLoc TL) { +  return TransformTypeSpecType(TLB, TL); +} + +template<typename Derived> +inline QualType  +TreeTransform<Derived>::TransformTemplateSpecializationType( +                                          TypeLocBuilder &TLB, +                                          TemplateSpecializationTypeLoc TL) { +  // TODO: figure out how make this work with an ObjectType. +  QualType Result +    = TransformTemplateSpecializationType(TL.getTypePtr(), QualType()); +  if (Result.isNull()) +    return QualType(); + +  TemplateSpecializationTypeLoc NewTL +    = TLB.push<TemplateSpecializationTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); + +  return Result; +} +   +template<typename Derived>  QualType TreeTransform<Derived>::TransformTemplateSpecializationType( -                                        const TemplateSpecializationType *T) { +                                        const TemplateSpecializationType *T, +                                                          QualType ObjectType) {    TemplateName Template -    = getDerived().TransformTemplateName(T->getTemplateName()); +    = getDerived().TransformTemplateName(T->getTemplateName(), ObjectType);    if (Template.isNull())      return QualType(); @@ -2426,8 +2730,10 @@ QualType TreeTransform<Derived>::TransformTemplateSpecializationType(  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformQualifiedNameType( -                                                  const QualifiedNameType *T) { +QualType +TreeTransform<Derived>::TransformQualifiedNameType(TypeLocBuilder &TLB, +                                                   QualifiedNameTypeLoc TL) { +  QualifiedNameType *T = TL.getTypePtr();    NestedNameSpecifier *NNS      = getDerived().TransformNestedNameSpecifier(T->getQualifier(),                                                  SourceRange()); @@ -2438,22 +2744,33 @@ QualType TreeTransform<Derived>::TransformQualifiedNameType(    if (Named.isNull())      return QualType(); -  if (!getDerived().AlwaysRebuild() && -      NNS == T->getQualifier() && -      Named == T->getNamedType()) -    return QualType(T, 0); +  QualType Result = TL.getType(); +  if (getDerived().AlwaysRebuild() || +      NNS != T->getQualifier() || +      Named != T->getNamedType()) { +    Result = getDerived().RebuildQualifiedNameType(NNS, Named); +    if (Result.isNull()) +      return QualType(); +  } + +  QualifiedNameTypeLoc NewTL = TLB.push<QualifiedNameTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); -  return getDerived().RebuildQualifiedNameType(NNS, Named); +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformTypenameType(const TypenameType *T) { +QualType TreeTransform<Derived>::TransformTypenameType(TypeLocBuilder &TLB, +                                                       TypenameTypeLoc TL) { +  TypenameType *T = TL.getTypePtr();    NestedNameSpecifier *NNS      = getDerived().TransformNestedNameSpecifier(T->getQualifier(),                          SourceRange(/*FIXME:*/getDerived().getBaseLocation()));    if (!NNS)      return QualType(); +  QualType Result; +    if (const TemplateSpecializationType *TemplateId = T->getTemplateId()) {      QualType NewTemplateId        = getDerived().TransformType(QualType(TemplateId, 0)); @@ -2465,31 +2782,33 @@ QualType TreeTransform<Derived>::TransformTypenameType(const TypenameType *T) {          NewTemplateId == QualType(TemplateId, 0))        return QualType(T, 0); -    return getDerived().RebuildTypenameType(NNS, NewTemplateId); +    Result = getDerived().RebuildTypenameType(NNS, NewTemplateId); +  } else { +    Result = getDerived().RebuildTypenameType(NNS, T->getIdentifier());    } +  if (Result.isNull()) +    return QualType(); -  return getDerived().RebuildTypenameType(NNS, T->getIdentifier()); -} +  TypenameTypeLoc NewTL = TLB.push<TypenameTypeLoc>(Result); +  NewTL.setNameLoc(TL.getNameLoc()); -template<typename Derived> -QualType TreeTransform<Derived>::TransformObjCInterfaceType( -                                                  const ObjCInterfaceType *T) { -  // FIXME: Implement -  return QualType(T, 0); +  return Result;  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformObjCObjectPointerType( -                                             const ObjCObjectPointerType *T) { -  // FIXME: Implement -  return QualType(T, 0); +QualType +TreeTransform<Derived>::TransformObjCInterfaceType(TypeLocBuilder &TLB, +                                                   ObjCInterfaceTypeLoc TL) { +  assert(false && "TransformObjCInterfaceType unimplemented"); +  return QualType();  }  template<typename Derived> -QualType TreeTransform<Derived>::TransformObjCProtocolListType( -                                                const ObjCProtocolListType *T) { -  assert(false && "Should not see ObjCProtocolList types"); -  return QualType(T, 0); +QualType +TreeTransform<Derived>::TransformObjCObjectPointerType(TypeLocBuilder &TLB, +                                               ObjCObjectPointerTypeLoc TL) { +  assert(false && "TransformObjCObjectPointerType unimplemented"); +  return QualType();  }  //===----------------------------------------------------------------------===// @@ -4010,8 +4329,8 @@ Sema::OwningExprResult  TreeTransform<Derived>::TransformUnresolvedDeclRefExpr(                                                      UnresolvedDeclRefExpr *E) {    NestedNameSpecifier *NNS -  = getDerived().TransformNestedNameSpecifier(E->getQualifier(), -                                              E->getQualifierRange()); +    = getDerived().TransformNestedNameSpecifier(E->getQualifier(), +                                                E->getQualifierRange());    if (!NNS)      return SemaRef.ExprError(); @@ -4040,6 +4359,14 @@ TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) {    if (Template.isNull())      return SemaRef.ExprError(); +  NestedNameSpecifier *Qualifier = 0; +  if (E->getQualifier()) { +    Qualifier = getDerived().TransformNestedNameSpecifier(E->getQualifier(), +                                                      E->getQualifierRange()); +    if (!Qualifier) +      return SemaRef.ExprError(); +  } +      llvm::SmallVector<TemplateArgument, 4> TransArgs;    for (unsigned I = 0, N = E->getNumTemplateArgs(); I != N; ++I) {      TemplateArgument TransArg @@ -4056,7 +4383,8 @@ TreeTransform<Derived>::TransformTemplateIdRefExpr(TemplateIdRefExpr *E) {    // FIXME: It's possible that we'll find out now that the template name    // actually refers to a type, in which case the caller is actually dealing    // with a functional cast. Give a reasonable error message! -  return getDerived().RebuildTemplateIdExpr(Template, E->getTemplateNameLoc(), +  return getDerived().RebuildTemplateIdExpr(Qualifier, E->getQualifierRange(), +                                            Template, E->getTemplateNameLoc(),                                              E->getLAngleLoc(),                                              TransArgs.data(),                                              TransArgs.size(), @@ -4235,6 +4563,7 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(    if (Base.isInvalid())      return SemaRef.ExprError(); +  // Start the member reference and compute the object's type.    Sema::TypeTy *ObjectType = 0;    Base = SemaRef.ActOnStartCXXMemberReference(0, move(Base),                                                E->getOperatorLoc(), @@ -4243,12 +4572,12 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(    if (Base.isInvalid())      return SemaRef.ExprError(); -  // FIXME: The first qualifier found might be a template type parameter, -  // in which case there is no transformed declaration to refer to (it might -  // refer to a built-in type!). +  // Transform the first part of the nested-name-specifier that qualifies +  // the member name.    NamedDecl *FirstQualifierInScope -    = cast_or_null<NamedDecl>( -              getDerived().TransformDecl(E->getFirstQualifierFoundInScope())); +    = getDerived().TransformFirstQualifierInScope( +                                          E->getFirstQualifierFoundInScope(), +                                          E->getQualifierRange().getBegin());    NestedNameSpecifier *Qualifier = 0;    if (E->getQualifier()) { @@ -4261,7 +4590,8 @@ TreeTransform<Derived>::TransformCXXUnresolvedMemberExpr(    }    DeclarationName Name -    = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc()); +    = getDerived().TransformDeclarationName(E->getMember(), E->getMemberLoc(), +                                       QualType::getFromOpaquePtr(ObjectType));    if (!Name)      return SemaRef.ExprError(); @@ -4504,6 +4834,14 @@ QualType TreeTransform<Derived>::RebuildMemberPointerType(QualType PointeeType,  template<typename Derived>  QualType +TreeTransform<Derived>::RebuildObjCObjectPointerType(QualType PointeeType) { +  return SemaRef.BuildPointerType(PointeeType, Qualifiers(), +                                  getDerived().getBaseLocation(), +                                  getDerived().getBaseEntity()); +} + +template<typename Derived> +QualType  TreeTransform<Derived>::RebuildArrayType(QualType ElementType,                                           ArrayType::ArraySizeModifier SizeMod,                                           const llvm::APInt *Size, @@ -4549,29 +4887,6 @@ TreeTransform<Derived>::RebuildConstantArrayType(QualType ElementType,  template<typename Derived>  QualType -TreeTransform<Derived>::RebuildConstantArrayWithExprType(QualType ElementType, -                                          ArrayType::ArraySizeModifier SizeMod, -                                                      const llvm::APInt &Size, -                                                         Expr *SizeExpr, -                                                      unsigned IndexTypeQuals, -                                                    SourceRange BracketsRange) { -  return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, SizeExpr, -                                       IndexTypeQuals, BracketsRange); -} - -template<typename Derived> -QualType -TreeTransform<Derived>::RebuildConstantArrayWithoutExprType( -                                                        QualType ElementType, -                                          ArrayType::ArraySizeModifier SizeMod, -                                                       const llvm::APInt &Size, -                                                     unsigned IndexTypeQuals) { -  return getDerived().RebuildArrayType(ElementType, SizeMod, &Size, 0, -                                       IndexTypeQuals, SourceRange()); -} - -template<typename Derived> -QualType  TreeTransform<Derived>::RebuildIncompleteArrayType(QualType ElementType,                                            ArrayType::ArraySizeModifier SizeMod,                                                   unsigned IndexTypeQuals) { @@ -4644,6 +4959,11 @@ QualType TreeTransform<Derived>::RebuildFunctionProtoType(QualType T,  }  template<typename Derived> +QualType TreeTransform<Derived>::RebuildFunctionNoProtoType(QualType T) { +  return SemaRef.Context.getFunctionNoProtoType(T); +} + +template<typename Derived>  QualType TreeTransform<Derived>::RebuildTypeOfExprType(ExprArg E) {    return SemaRef.BuildTypeofExprType(E.takeAs<Expr>());  } diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index e849042b3d3d..b6fff102a701 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -141,9 +141,11 @@ again:    }  } +//===----------------------------------------------------------------------===//  // Reduced test case from <rdar://problem/7114618>.  // Basically a null check is performed on the field value, which is then  // assigned to a variable and then checked again. +//===----------------------------------------------------------------------===//  struct s_7114618 { int *p; };  void test_rdar_7114618(struct s_7114618 *s) {    if (s->p) { @@ -168,9 +170,11 @@ void f() {    }  } +//===----------------------------------------------------------------------===//  // <rdar://problem/7185607>  // Bit-fields of a struct should be invalidated when blasting the entire  // struct with an integer constant. +//===----------------------------------------------------------------------===//  struct test_7185607 {    int x : 10;    int y : 22; @@ -181,9 +185,11 @@ int rdar_test_7185607() {    return s.x; // no-warning  } +//===----------------------------------------------------------------------===//  // <rdar://problem/7242006> [RegionStore] compound literal assignment with  //  floats not honored  // This test case is mirrored in misc-ps.m, but this case is a negative. +//===----------------------------------------------------------------------===//  typedef float CGFloat;  typedef struct _NSSize {      CGFloat width; @@ -195,9 +201,11 @@ CGFloat rdar7242006_negative(CGFloat x) {    return y.width; // expected-warning{{garbage}}  } +//===----------------------------------------------------------------------===//  // <rdar://problem/7249340> - Allow binding of values to symbolic regions.  // This test case shows how RegionStore tracks the value bound to 'x'  // after the assignment. +//===----------------------------------------------------------------------===//  typedef int* ptr_rdar_7249340;  void rdar_7249340(ptr_rdar_7249340 x) {    *x = 1; @@ -207,11 +215,13 @@ void rdar_7249340(ptr_rdar_7249340 x) {    *p = 0xDEADBEEF; // no-warning  } +//===----------------------------------------------------------------------===//  // <rdar://problem/7249327> - This test case tests both value tracking of  // array values and that we handle symbolic values that are casted  // between different integer types.  Note the assignment 'n = *a++'; here  // 'n' is and 'int' and '*a' is 'unsigned'.  Previously we got a false positive  // at 'x += *b++' (undefined value) because we got a false path. +//===----------------------------------------------------------------------===//  int rdar_7249327_aux(void);  void rdar_7249327(unsigned int A[2*32]) { @@ -237,8 +247,10 @@ void rdar_7249327(unsigned int A[2*32]) {      x += *b++; // no-warning  } +//===----------------------------------------------------------------------===//  // <rdar://problem/6914474> - Check that 'x' is invalidated because its  // address is passed in as a value to a struct. +//===----------------------------------------------------------------------===//  struct doodad_6914474 { int *v; };  extern void prod_6914474(struct doodad_6914474 *d);  int rdar_6914474(void) { @@ -278,8 +290,11 @@ int test_handle_array_wrapper() {    return p->z;  // no-warning  } +//===----------------------------------------------------------------------===//  // <rdar://problem/7261075> [RegionStore] crash when   //   handling load: '*((unsigned int *)"????")' +//===----------------------------------------------------------------------===// +  int rdar_7261075(void) {    unsigned int var = 0;    if (var == *((unsigned int *)"????")) @@ -287,8 +302,11 @@ int rdar_7261075(void) {    return 0;  } +//===----------------------------------------------------------------------===//  // <rdar://problem/7275774> false path due to limited pointer   //                          arithmetic constraints +//===----------------------------------------------------------------------===// +  void rdar_7275774(void *data, unsigned n) {    if (!(data || n == 0))      return; @@ -303,3 +321,54 @@ void rdar_7275774(void *data, unsigned n) {    }  } +//===----------------------------------------------------------------------===// +// <rdar://problem/7312221> +// +//  Test that Objective-C instance variables aren't prematurely pruned +//  from the analysis state. +//===----------------------------------------------------------------------===// + +struct rdar_7312221_value { int x; }; + +@interface RDar7312221 +{ +  struct rdar_7312221_value *y; +} +- (void) doSomething_7312221; +@end + +extern struct rdar_7312221_value *rdar_7312221_helper(); +extern int rdar_7312221_helper_2(id o); +extern void rdar_7312221_helper_3(int z); + +@implementation RDar7312221 +- (void) doSomething_7312221 { +  if (y == 0) { +    y = rdar_7312221_helper(); +    if (y != 0) { +      y->x = rdar_7312221_helper_2(self); +      // The following use of 'y->x' previously triggered a null dereference, as the value of 'y' +      // before 'y = rdar_7312221_helper()' would be used. +      rdar_7312221_helper_3(y->x); // no-warning +    } +  } +} +@end + +struct rdar_7312221_container { +  struct rdar_7312221_value *y; +}; + +extern int rdar_7312221_helper_4(struct rdar_7312221_container *s); + +// This test case essentially matches the one in [RDar7312221 doSomething_7312221]. +void doSomething_7312221_with_struct(struct rdar_7312221_container *Self) { +  if (Self->y == 0) { +    Self->y = rdar_7312221_helper(); +    if (Self->y != 0) { +      Self->y->x = rdar_7312221_helper_4(Self); +      rdar_7312221_helper_3(Self->y->x); // no-warning +    } +  } +} + diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 10e5823c206c..fcc13a39a461 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -681,14 +681,40 @@ void *rdar7152418_bar();    return 1;  } +//===----------------------------------------------------------------------===//  // Test constant-folding of symbolic values, automatically handling type -// conversions of the symbol as necessary.  Previously this would crash -// once we started eagerly evaluating symbols whose values were constrained -// to a single value. -void test_constant_symbol(signed char x) { +// conversions of the symbol as necessary. +//===----------------------------------------------------------------------===// + + +// Previously this would crash once we started eagerly evaluating symbols whose  +// values were constrained to a single value. +void test_symbol_fold_1(signed char x) {    while (1) {      if (x == ((signed char) 0)) {}    }  } +// This previously caused a crash because it triggered an assertion in APSInt. +void test_symbol_fold_2(unsigned int * p, unsigned int n, +                        const unsigned int * grumpkin, unsigned int dn) { +  unsigned int i; +  unsigned int tempsub[8]; +  unsigned int *solgrumpkin = tempsub + n; +  for (i = 0; i < n; i++) +    solgrumpkin[i] = (i < dn) ? ~grumpkin[i] : 0xFFFFFFFF; +  for (i <<= 5; i < (n << 5); i++) {} +} + +// This previously caused a crash because it triggered an assertion in APSInt. +// 'x' would evaluate to a 8-bit constant (because of the return value of +// test_symbol_fold_3_aux()) which would not get properly promoted to an +// integer. +char test_symbol_fold_3_aux(void); +unsigned test_symbol_fold_3(void) { +  unsigned x = test_symbol_fold_3_aux(); +  if (x == 54) +    return (x << 8) | 0x5; +  return 0; +}   diff --git a/test/Analysis/refcnt_naming.m b/test/Analysis/refcnt_naming.m index bea404799ba3..2ce00b2a8cca 100644 --- a/test/Analysis/refcnt_naming.m +++ b/test/Analysis/refcnt_naming.m @@ -15,7 +15,7 @@ typedef signed char BOOL;  -(NSObject*)photoCopy;    // read as "photo Copy"  -(NSObject*)__blebPRCopy; // read as "bleb PRCopy"  -(NSObject*)__blebPRcopy; // read as "bleb P Rcopy" --(NSObject*)new_theprefixdoesnotcount; // read as "theprefixdoesnotcount" +-(NSObject*)new_theprefixdoescount; // read as "new theprefixdoescount"  -(NSObject*)newestAwesomeStuff; // read as "newest awesome stuff"  @end @@ -49,7 +49,7 @@ void testNames(NamingTest* x) {    [x photoCopy]; // expected-warning{{leak}}    [x __blebPRCopy]; // expected-warning{{leak}}    [x __blebPRcopy]; // no-warning -  [x new_theprefixdoesnotcount]; // no-warning +  [x new_theprefixdoescount]; // expected-warning{{leak}}    [x newestAwesomeStuff]; // no-warning  } diff --git a/test/Analysis/retain-release-region-store.m b/test/Analysis/retain-release-region-store.m index 7a696833f92d..eacac49c8127 100644 --- a/test/Analysis/retain-release-region-store.m +++ b/test/Analysis/retain-release-region-store.m @@ -1,5 +1,4 @@  // RUN: clang-cc -analyze -checker-cfref -analyzer-store=region -verify %s -// XFAIL  //===----------------------------------------------------------------------===//  // The following code is reduced using delta-debugging from @@ -43,14 +42,19 @@ typedef mach_port_name_t mach_port_t;  typedef signed char BOOL;  typedef struct _NSZone NSZone;  @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; -@protocol NSObject  - (BOOL)isEqual:(id)object; +@protocol NSObject +- (BOOL)isEqual:(id)object;  - (id)retain;  - (oneway void)release;  @end  @protocol NSCopying  - (id)copyWithZone:(NSZone *)zone;  @end  @protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; -@end    @interface NSObject <NSObject> { -} -@end  typedef float CGFloat; +@end +@interface NSObject <NSObject> {} ++ (id)allocWithZone:(NSZone *)zone; ++ (id)alloc; +- (void)dealloc; +@end +typedef float CGFloat;  typedef double NSTimeInterval;  @interface NSDate : NSObject <NSCopying, NSCoding>  - (NSTimeInterval)timeIntervalSinceReferenceDate;  @end      enum { @@ -74,6 +78,13 @@ kDAReturnSuccess = 0,     kDAReturnError = (((0x3e)&0x3f)<<26) | (((0x368)&0xfff  typedef mach_error_t DAReturn;  typedef const struct __DADissenter * DADissenterRef;  extern DADissenterRef DADissenterCreate( CFAllocatorRef allocator, DAReturn status, CFStringRef string ); +@interface NSNumber : NSObject +- (id)initWithInt:(int)value; +@end +typedef unsigned long NSUInteger; +@interface NSArray : NSObject +-(id) initWithObjects:(const id *)objects count:(NSUInteger) cnt; +@end  //===----------------------------------------------------------------------===//  // Test cases. @@ -116,15 +127,14 @@ CFAbsoluteTime f4() {  }  @end -//===----------------------------------------------------------------------===// -// <rdar://problem/7257223> - False positive due to not invalidating the -// reference count of a tracked region that was itself invalidated. -//===----------------------------------------------------------------------===// +//===------------------------------------------------------------------------------------------===// +// <rdar://problem/7257223> (also <rdar://problem/7283470>) - False positive due to not invalidating +//  the reference count of a tracked region that was itself invalidated. +//===------------------------------------------------------------------------------------------===//  typedef struct __rdar_7257223 { CFDateRef x; } RDar7257223;  void rdar_7257223_aux(RDar7257223 *p); -// THIS CASE CURRENTLY FAILS.  CFDateRef rdar7257223_Create(void) {    RDar7257223 s;    CFAbsoluteTime t = CFAbsoluteTimeGetCurrent(); @@ -140,3 +150,58 @@ CFDateRef rdar7257223_Create_2(void) {    return s.x;  } +void rdar7283470(void) { +  NSNumber *numbers[] = { +    [[NSNumber alloc] initWithInt:1], // no-warning +    [[NSNumber alloc] initWithInt:2], // no-warning +    [[NSNumber alloc] initWithInt:3], // no-warning +    [[NSNumber alloc] initWithInt:4], // no-warning +    [[NSNumber alloc] initWithInt:5]  // no-warning +  }; +   +  for (unsigned i = 0 ; i < sizeof(numbers) / sizeof(numbers[0]) ; ++i) +    [numbers[i] release]; +} + +void rdar7283470_positive(void) { +  NSNumber *numbers[] = { +    [[NSNumber alloc] initWithInt:1], // expected-warning{{leak}} +    [[NSNumber alloc] initWithInt:2], // expected-warning{{leak}} +    [[NSNumber alloc] initWithInt:3], // expected-warning{{leak}} +    [[NSNumber alloc] initWithInt:4], // expected-warning{{leak}} +    [[NSNumber alloc] initWithInt:5]  // expected-warning{{leak}}  +  }; +} + +void rdar7283470_2(void) { +  NSNumber *numbers[] = { +    [[NSNumber alloc] initWithInt:1], // no-warning +    [[NSNumber alloc] initWithInt:2], // no-warning +    [[NSNumber alloc] initWithInt:3], // no-warning +    [[NSNumber alloc] initWithInt:4], // no-warning +    [[NSNumber alloc] initWithInt:5]  // no-warning +  }; +   +  NSArray *s_numbers =[[NSArray alloc] initWithObjects:&numbers[0] count:sizeof(numbers) / sizeof(numbers[0])]; +   +  for (unsigned i = 0 ; i < sizeof(numbers) / sizeof(numbers[0]) ; ++i) +    [numbers[i] release]; +   +  [s_numbers release]; +} + +void rdar7283470_2_positive(void) { +  NSNumber *numbers[] = { +    [[NSNumber alloc] initWithInt:1], // no-warning +    [[NSNumber alloc] initWithInt:2], // no-warning +    [[NSNumber alloc] initWithInt:3], // no-warning +    [[NSNumber alloc] initWithInt:4], // no-warning +    [[NSNumber alloc] initWithInt:5]  // no-warning +  }; +   +  NSArray *s_numbers =[[NSArray alloc] initWithObjects: &numbers[0] count:sizeof(numbers) / sizeof(numbers[0])]; // expected-warning{{leak}} +   +  for (unsigned i = 0 ; i < sizeof(numbers) / sizeof(numbers[0]) ; ++i) +    [numbers[i] release]; +} + diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 7076bb294254..e620037b2c14 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -1098,6 +1098,44 @@ CVReturn rdar_7283567_2(CFAllocatorRef allocator, size_t width, size_t height,  }  //===----------------------------------------------------------------------===// +// <rdar://problem/7265711> allow 'new', 'copy', 'alloc', 'init' prefix to +//  start before '_' when determining Cocoa fundamental rule +// +// Previously the retain/release checker just skipped prefixes before the +// first '_' entirely.  Now the checker honors the prefix if it results in a +// recognizable naming convention (e.g., 'new', 'init'). +//===----------------------------------------------------------------------===// + +@interface RDar7265711 {} +- (id) new_stuff; +@end + +void rdar7265711_a(RDar7265711 *x) { +  id y = [x new_stuff]; // expected-warning{{leak}} +} + +void rdar7265711_b(RDar7265711 *x) { +  id y = [x new_stuff]; // no-warning +  [y release]; +} + +//===----------------------------------------------------------------------===// +// <rdar://problem/7306898> clang thinks [NSCursor dragCopyCursor] returns a +//                          retained reference +//===----------------------------------------------------------------------===// + +@interface NSCursor : NSObject ++ (NSCursor *)dragCopyCursor; +@end + +void rdar7306898(void) { +  // 'dragCopyCursor' does not follow Cocoa's fundamental rule.  It is a noun, not an sentence +  // implying a 'copy' of something. +  NSCursor *c =  [NSCursor dragCopyCursor]; // no-warning +  NSNumber *number = [[NSNumber alloc] initWithInt:5]; // expected-warning{{leak}} +} + +//===----------------------------------------------------------------------===//  // Tests of ownership attributes.  //===----------------------------------------------------------------------===// diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 2a7f132fb5df..66f05bff6994 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -45,7 +45,7 @@ if(PYTHONINTERP_FOUND)                    ${LLVM_SOURCE_DIR}/utils/lit/lit.py                    -sv ${CLANG_TEST_EXTRA_ARGS}                    ${CMAKE_CURRENT_BINARY_DIR}/${testdir} -                  DEPENDS clang clang-cc index-test +                  DEPENDS clang clang-cc index-test c-index-test                    COMMENT "Running Clang regression tests in ${testdir}")    endforeach() @@ -62,7 +62,7 @@ if(PYTHONINTERP_FOUND)                  ${LLVM_SOURCE_DIR}/utils/lit/lit.py                  -sv ${CLANG_TEST_EXTRA_ARGS}                  ${CMAKE_CURRENT_BINARY_DIR} -                DEPENDS clang clang-cc index-test +                DEPENDS clang clang-cc index-test c-index-test                  COMMENT "Running Clang regression tests")    add_custom_target(clang-c++tests @@ -78,6 +78,6 @@ if(PYTHONINTERP_FOUND)                  ${LLVM_SOURCE_DIR}/utils/lit/lit.py                  -sv ${CLANG_TEST_EXTRA_ARGS}                  ${CMAKE_CURRENT_SOURCE_DIR}/../utils/C++Tests -                DEPENDS clang clang-cc index-test +                DEPENDS clang clang-cc index-test c-index-test                  COMMENT "Running Clang regression tests")  endif()   diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp new file mode 100644 index 000000000000..4d0319e58dfb --- /dev/null +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.aggr/p4.cpp @@ -0,0 +1,18 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 -pedantic -Werror  %s +int a1[] = { 1, 3, 5 }; +void f() { +  int a2[] = { 1, 3, 5 }; +} +template <typename T> +void tf() { +  T t; +  // Element type may be dependent +  T a3[] = { 1, 3, 5 }; +  // As might be the initializer list, value +  int a5[] = { sizeof(T) }; +  // or even type. +  int a6[] = { t.get() }; +} + +// Allowed by GNU extension +int a4[] = {}; // expected-warning {{zero size arrays}} diff --git a/test/CXX/temp/temp.spec/p5.cpp b/test/CXX/temp/temp.spec/p5.cpp new file mode 100644 index 000000000000..d5632e7f341d --- /dev/null +++ b/test/CXX/temp/temp.spec/p5.cpp @@ -0,0 +1,29 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> inline void f(T) { } +template void f(int); // expected-note{{previous explicit instantiation}} +template void f(int); // expected-error{{duplicate explicit instantiation}} + +template<typename T> +struct X0 { +  union Inner { }; +   +  void f(T) { } +   +  static T value; +}; + +template<typename T> +T X0<T>::value = 3.14; + +template struct X0<int>; // expected-note{{previous explicit instantiation}} +template struct X0<int>; // expected-error{{duplicate explicit instantiation}} + +template void X0<float>::f(float); // expected-note{{previous explicit instantiation}} +template void X0<float>::f(float); // expected-error{{duplicate explicit instantiation}} + +template union X0<float>::Inner; // expected-note{{previous explicit instantiation}} +template union X0<float>::Inner; // expected-error{{duplicate explicit instantiation}} + +template float X0<float>::value; // expected-note{{previous explicit instantiation}} +template float X0<float>::value; // expected-error{{duplicate explicit instantiation}} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp b/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp new file mode 100644 index 000000000000..d7731f17637c --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp @@ -0,0 +1,10 @@ +// RUN: clang-cc -fsyntax-only -std=c++0x -verify %s + +template<typename T> +struct X { +  void f() {} +}; + +template inline void X<int>::f(); // expected-error{{'inline'}} + +// FIXME: test constexpr diff --git a/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp b/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp new file mode 100644 index 000000000000..3938509961b4 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp @@ -0,0 +1,29 @@ +// RUN: clang-cc -emit-llvm -triple x86_64-apple-darwin10 -o - %s | FileCheck %s +template<typename T> +struct X { +  static T member1; +  static T member2; +  static T member3; +}; + +template<typename T> +T X<T>::member1; + +template<typename T> +T X<T>::member2 = 17; + +// CHECK: @_ZN1XIiE7member1E = global i32 0 +template int X<int>::member1; + +// CHECK: @_ZN1XIiE7member2E = global i32 17 +template int X<int>::member2; + +// For implicit instantiation of  +long& get(bool Cond1, bool Cond2) { +  // CHECK: @_ZN1XIlE7member1E = weak global i64 0 +  // CHECK: @_ZN1XIlE7member2E = weak global i64 17 +  // CHECK: @_ZN1XIlE7member3E = external global i64 +  return Cond1? X<long>::member1  +       : Cond2? X<long>::member2 +              : X<long>::member3; +} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p1.cpp b/test/CXX/temp/temp.spec/temp.explicit/p1.cpp new file mode 100644 index 000000000000..896e30efb886 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.explicit/p1.cpp @@ -0,0 +1,89 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +struct C { }; + +template<typename T> +struct X0 { +  T value; // expected-error{{incomplete}} +}; + +// Explicitly instantiate a class template specialization +template struct X0<int>; +template struct X0<void>; // expected-note{{instantiation}} + +// Explicitly instantiate a function template specialization +template<typename T> +void f0(T t) { +  ++t; // expected-error{{cannot modify}} +} + +template void f0(int); +template void f0<long>(long); +template void f0<>(unsigned); +template void f0(int C::*); // expected-note{{instantiation}} + +// Explicitly instantiate a member template specialization +template<typename T> +struct X1 { +  template<typename U> +  struct Inner { +    T member1; +    U member2; // expected-error{{incomplete}} +  }; +   +  template<typename U> +  void f(T& t, U u) { +    t = u; // expected-error{{incompatible}} +  } +}; + +template struct X1<int>::Inner<float>; +template struct X1<int>::Inner<double>; +template struct X1<int>::Inner<void>; // expected-note{{instantiation}} + +template void X1<int>::f(int&, float); +template void X1<int>::f<long>(int&, long); +template void X1<int>::f<>(int&, double); +template void X1<int>::f<>(int&, int*); // expected-note{{instantiation}} + +// Explicitly instantiate members of a class template +struct Incomplete; // expected-note{{forward declaration}} +struct NonDefaultConstructible { +  NonDefaultConstructible(int); +}; + +template<typename T, typename U> +struct X2 { +  void f(T &t, U u) {  +    t = u; // expected-error{{incompatible}} +  } +   +  struct Inner { +    T member1; +    U member2; // expected-error{{incomplete}} +  }; +   +  static T static_member1; +  static U static_member2; +}; + +template<typename T, typename U> +T X2<T, U>::static_member1 = 17; // expected-error{{incompatible type}} + +template<typename T, typename U> +U X2<T, U>::static_member2; // expected-error{{no matching}} + +template void X2<int, float>::f(int &, float); +template void X2<int, float>::f(int &, double); // expected-error{{does not refer}} +template void X2<int, int*>::f(int&, int*); // expected-note{{instantiation}} + +template struct X2<int, float>::Inner; +template struct X2<int, Incomplete>::Inner; // expected-note{{instantiation}} + +template int X2<int, float>::static_member1; +template int* X2<int*, float>::static_member1; // expected-note{{instantiation}} +template  +  NonDefaultConstructible X2<NonDefaultConstructible, int>::static_member1; + +template  +  NonDefaultConstructible X2<int, NonDefaultConstructible>::static_member2; // expected-note{{instantiation}} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p2.cpp b/test/CXX/temp/temp.spec/temp.explicit/p2.cpp new file mode 100644 index 000000000000..f3d2c955cb5b --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.explicit/p2.cpp @@ -0,0 +1,43 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// Example from the standard +template<class T> class Array { void mf() { } };  + +template class Array<char>;  +template void Array<int>::mf(); +template<class T> void sort(Array<T>& v) { /* ... */ } +template void sort(Array<char>&); +namespace N {  +  template<class T> void f(T&) { } +}  +template void N::f<int>(int&); + + +template<typename T> +struct X0 { +  struct Inner {}; +  void f() { } +  static T value; +}; + +template<typename T> +T X0<T>::value = 17; + +typedef X0<int> XInt; + +template struct XInt::Inner; // expected-error{{template-id}} +template void XInt::f(); // expected-error{{template-id}} +template int XInt::value; // expected-error{{template-id}} + +namespace N { +  template<typename T> +  struct X1 { // expected-note{{explicit instantiation refers here}} +  }; +   +  template<typename T> +  void f1(T) {}; // expected-note{{explicit instantiation refers here}} +} +using namespace N; + +template struct X1<int>; // expected-error{{must occur in}} +template void f1(int); // expected-error{{must occur in}} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp new file mode 100644 index 000000000000..2bd781bbed28 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.explicit/p3.cpp @@ -0,0 +1,55 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +// A declaration of a function template shall be in scope at the point of the  +// explicit instantiation of the function template. +template<typename T> void f0(T) { } +template void f0(int); // okay + +// A definition of the class or class template containing a member function  +// template shall be in scope at the point of the explicit instantiation of  +// the member function template. +struct X0; // expected-note 2{{forward declaration}} +template<typename> struct X1; // expected-note 2{{declared here}} \ +                              // expected-note 3{{forward declaration}} + +// FIXME: Repeated diagnostics here! +template void X0::f0<int>(int); // expected-error 2{{incomplete type}} \ +  // expected-error{{invalid token after}} +template void X1<int>::f0<int>(int); // expected-error{{implicit instantiation of undefined template}} \ +  // expected-error{{incomplete type}} \\ +  // expected-error{{invalid token}} + +// A definition of a class template or class member template shall be in scope  +// at the point of the explicit instantiation of the class template or class  +// member template. +template struct X1<float>; // expected-error{{explicit instantiation of undefined template}} + +template<typename T> +struct X2 { // expected-note 4{{refers here}} +  template<typename U> +  struct Inner; // expected-note{{declared here}} +   +  struct InnerClass; // expected-note{{forward declaration}} +}; + +template struct X2<int>::Inner<float>; // expected-error{{explicit instantiation of undefined template}} + +// A definition of a class template shall be in scope at the point of an  +// explicit instantiation of a member function or a static data member of the +// class template. +template void X1<int>::f1(int); // expected-error{{incomplete type}} \ +                                // expected-error{{does not refer}} + +template int X1<int>::member; // expected-error{{incomplete type}} \ +                              // expected-error{{does not refer}} + +// A definition of a member class of a class template shall be in scope at the  +// point of an explicit instantiation of the member class. +template struct X2<float>::InnerClass; // expected-error{{undefined member}} + +// If the declaration of the explicit instantiation names an implicitly-declared  +// special member function (Clause 12), the program is ill-formed. +template X2<int>::X2(); // expected-error{{not an instantiation}} +template X2<int>::X2(const X2&); // expected-error{{not an instantiation}} +template X2<int>::~X2(); // expected-error{{not an instantiation}} +template X2<int> &X2<int>::operator=(const X2<int>&); // expected-error{{not an instantiation}} diff --git a/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp new file mode 100644 index 000000000000..04e511b0b2d5 --- /dev/null +++ b/test/CXX/temp/temp.spec/temp.explicit/p4.cpp @@ -0,0 +1,32 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +template<typename T> void f0(T); // expected-note{{here}} +template void f0(int); // expected-error{{explicit instantiation of undefined function template}} + +template<typename T> +struct X0 { +  struct Inner; +   +  void f1(); // expected-note{{here}} +   +  static T value; // expected-note{{here}} +}; + +template void X0<int>::f1(); // expected-error{{explicit instantiation of undefined member function}} + +template int X0<int>::value; // expected-error{{explicit instantiation of undefined static data member}} + +template<> void f0(long); +template void f0(long); // okay + +template<> void X0<long>::f1(); +template void X0<long>::f1(); + +template<> struct X0<long>::Inner; +template struct X0<long>::Inner; + +template<> long X0<long>::value; +template long X0<long>::value; + +template<> struct X0<double>; +template struct X0<double>; diff --git a/test/CodeGen/2009-10-20-GlobalDebug.c b/test/CodeGen/2009-10-20-GlobalDebug.c new file mode 100644 index 000000000000..eea3fb5307b4 --- /dev/null +++ b/test/CodeGen/2009-10-20-GlobalDebug.c @@ -0,0 +1,4 @@ +// RUN: clang -ccc-host-triple i386-apple-darwin10 -S -g -dA %s -o - | FileCheck %s +int global; +// CHECK: asciz  "global"                                    ## DW_AT_MIPS_linkage_name +int main() { return 0;} diff --git a/test/CodeGen/builtins.c b/test/CodeGen/builtins.c index ac59b274958a..359d5070ccc1 100644 --- a/test/CodeGen/builtins.c +++ b/test/CodeGen/builtins.c @@ -117,7 +117,7 @@ int main() { -char *strcat(char *a, char const *b) {} +void strcat() {}  void foo() {   __builtin_strcat(0, 0); diff --git a/test/CodeGen/debug-info.c b/test/CodeGen/debug-info.c index beee7ac9b61a..85ad988bc216 100644 --- a/test/CodeGen/debug-info.c +++ b/test/CodeGen/debug-info.c @@ -1,10 +1,12 @@ -// RUN: clang-cc -o %t --emit-llvm -g %s +// RUN: clang-cc -o %t --emit-llvm -g %s && +// RUN: FileCheck --input-file=%t %s  // PR3023  void convert(void) {    struct { typeof(0) f0; } v0;  } +  // PR2784  struct OPAQUE;  typedef struct OPAQUE *PTR; @@ -19,9 +21,11 @@ struct s0 *f0(struct s0 *a0) {    return a0->p;  } +  // PR3134  char xpto[]; +  // PR3427  struct foo {    int a; @@ -29,9 +33,17 @@ struct foo {  };  struct foo bar; +  // PR4143  struct foo2 {    enum bar *bar;  };  struct foo2 foo2; + + +// Radar 7325611 +// CHECK: "barfoo" +typedef int barfoo; +barfoo foo() { +} diff --git a/test/CodeGen/ext-vector-shuffle.c b/test/CodeGen/ext-vector-shuffle.c index f53db945da03..765551596401 100644 --- a/test/CodeGen/ext-vector-shuffle.c +++ b/test/CodeGen/ext-vector-shuffle.c @@ -1,6 +1,6 @@ -// RUN: clang-cc %s -emit-llvm -o - | not grep 'extractelement' && -// RUN: clang-cc %s -emit-llvm -o - | not grep 'insertelement' && -// RUN: clang-cc %s -emit-llvm -o - | grep 'shufflevector' +// RUN: clang-cc %s -x cl -emit-llvm -o - | not grep 'extractelement' && +// RUN: clang-cc %s -x cl -emit-llvm -o - | not grep 'insertelement' && +// RUN: clang-cc %s -x cl -emit-llvm -o - | grep 'shufflevector'  typedef __attribute__(( ext_vector_type(2) )) float float2;  typedef __attribute__(( ext_vector_type(4) )) float float4; @@ -13,3 +13,5 @@ float4 test2(float4 V) {    float2 W = V.ww;    return W.xyxy + W.yxyx;  } + +float4 test3(float4 V1, float4 V2) { return (float4)(V1.zw, V2.xy); } diff --git a/test/CodeGen/vector.c b/test/CodeGen/vector.c index 5e48fd42b1d0..2945ebaa4d05 100644 --- a/test/CodeGen/vector.c +++ b/test/CodeGen/vector.c @@ -1,7 +1,7 @@ -// RUN: clang-cc -emit-llvm %s -o - +// RUN: clang-cc -triple i386-apple-darwin9 -mcpu=pentium4 -g -emit-llvm %s -o -  typedef short __v4hi __attribute__ ((__vector_size__ (8))); -void f() { +void test1() {    __v4hi A = (__v4hi)0LL;  } @@ -9,11 +9,34 @@ __v4hi x = {1,2,3};  __v4hi y = {1,2,3,4};  typedef int vty __attribute((vector_size(16))); -int a() { vty b; return b[2LL]; } +int test2() { vty b; return b[2LL]; }  // PR4339  typedef float vec4 __attribute__((vector_size(16))); -void vac ( vec4* a, char b, float c ) { +void test3 ( vec4* a, char b, float c ) {    (*a)[b] = c;  } + + + + +#include <mmintrin.h> + +int test4(int argc, char *argv[]) { +  int array[16] = { 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 }; +  __m64 *p = (__m64 *)array; + +  __m64 accum = _mm_setzero_si64(); + +  for (int i=0; i<8; ++i) +     accum = _mm_add_pi32(p[i], accum); + +  __m64 accum2 = _mm_unpackhi_pi32(accum, accum); +  accum = _mm_add_pi32(accum, accum2); + +  int result = _mm_cvtsi64_si32(accum); +  _mm_empty(); + +  return result; +} diff --git a/test/CodeGenCXX/address-of-fntemplate.cpp b/test/CodeGenCXX/address-of-fntemplate.cpp new file mode 100644 index 000000000000..1f0c8f38630b --- /dev/null +++ b/test/CodeGenCXX/address-of-fntemplate.cpp @@ -0,0 +1,13 @@ +// RUN: clang-cc %s -emit-llvm -o - | FileCheck %s +template <typename T> void f(T) {} +template <typename T> void f() { } + +void test() { +  // CHECK: @_Z1fIiEvT_ +  void (*p)(int) = &f; +   +  // CHECK: @_Z1fIiEvv +  void (*p2)() = f<int>; +} +// CHECK: define linkonce_odr void @_Z1fIiEvT_ +// CHECK: define linkonce_odr void @_Z1fIiEvv diff --git a/test/CodeGenCXX/call-arg-zero-temp.cpp b/test/CodeGenCXX/call-arg-zero-temp.cpp new file mode 100644 index 000000000000..2c44f69d975e --- /dev/null +++ b/test/CodeGenCXX/call-arg-zero-temp.cpp @@ -0,0 +1,23 @@ +// RUN: clang-cc -triple x86_64-apple-darwin -S %s -o %t-64.s && +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s && +// RUN: clang-cc -triple i386-apple-darwin -S %s -o %t-32.s && +// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s && +// RUN: true + + +extern "C" int printf(...); + +struct obj{ int a; float b; double d; }; + +void foo(obj o) { +  printf("%d  %f  %f\n", o.a, o.b, o.d); +} + +int main() { +  obj o = obj(); +  foo(obj()); +} + +// CHECK-LP64: call     __Z3foo3obj + +// CHECK-LP32: call     __Z3foo3obj diff --git a/test/CodeGenCXX/casts.cpp b/test/CodeGenCXX/casts.cpp new file mode 100644 index 000000000000..045f2d4fe031 --- /dev/null +++ b/test/CodeGenCXX/casts.cpp @@ -0,0 +1,14 @@ +// RUN: clang-cc %s -emit-llvm -o %t + +// PR5248 +namespace PR5248 { +struct A { +  void copyFrom(const A &src); +  void addRef(void); +}; + +void A::copyFrom(const A &src) { +  ((A &)src).addRef(); +} +} + diff --git a/test/CodeGenCXX/default-arg-temps.cpp b/test/CodeGenCXX/default-arg-temps.cpp index 2651446669b8..8385aff6291c 100644 --- a/test/CodeGenCXX/default-arg-temps.cpp +++ b/test/CodeGenCXX/default-arg-temps.cpp @@ -15,7 +15,7 @@ public:  void g() {    // RUN: grep "call void @_ZN1TC1Ev" %t | count 4 && -  // RUN: grep "call void @_ZN1TD1Ev" %t | count 4 +  // RUN: grep "call void @_ZN1TD1Ev" %t | count 4 &&    f();    f(); @@ -23,3 +23,10 @@ void g() {    X b(a);    X c = a;  } + + +// RUN: grep memset %t +class obj{ int a; float b; double d; }; +void h() { +  obj o = obj(); +} diff --git a/test/CodeGenCXX/derived-to-base-conv.cpp b/test/CodeGenCXX/derived-to-base-conv.cpp new file mode 100644 index 000000000000..0c890195119f --- /dev/null +++ b/test/CodeGenCXX/derived-to-base-conv.cpp @@ -0,0 +1,79 @@ +// RUN: clang-cc -triple x86_64-apple-darwin -std=c++0x -S %s -o %t-64.s && +// RUN: FileCheck -check-prefix LP64 --input-file=%t-64.s %s && +// RUN: clang-cc -triple i386-apple-darwin -std=c++0x -S %s -o %t-32.s && +// RUN: FileCheck -check-prefix LP32 --input-file=%t-32.s %s && +// RUN: true + +extern "C" int printf(...); +extern "C" void exit(int); + +struct A { + A (const A&) { printf("A::A(const A&)\n"); } + A() {}; +};  + +struct B : public A { +  B() {}; +};  + +struct C : public B { +  C() {}; +};  + +struct X { +	operator B&() {printf("X::operator B&()\n"); return b; } +	operator C&() {printf("X::operator C&()\n"); return c; } + 	X (const X&) { printf("X::X(const X&)\n"); } + 	X () { printf("X::X()\n"); } +	B b; +	C c; +}; + +void f(A) { +  printf("f(A)\n"); +} + + +void func(X x)  +{ +  f (x); +} + +int main() +{ +    X x; +    func(x); +} + +struct Base; + +struct Root { +  operator Base&() { exit(1); } +}; + +struct Derived; + +struct Base : Root { +  Base(const Base&) { printf("Base::(const Base&)\n"); } +  Base() { printf("Base::Base()\n"); } +  operator Derived&() { exit(1); } +}; + +struct Derived : Base { +}; + +void foo(Base) {} + +void test(Derived bb) +{ +	// CHECK-LP64-NOT: call     __ZN4BasecvR7DerivedEv +	// CHECK-LP32-NOT: call     L__ZN4BasecvR7DerivedEv +        foo(bb); +} +// CHECK-LP64: call     __ZN1XcvR1BEv +// CHECK-LP64: call     __ZN1AC1ERKS_ + +// CHECK-LP32: call     L__ZN1XcvR1BEv +// CHECK-LP32: call     L__ZN1AC1ERKS_ + + diff --git a/test/CodeGenCXX/expr.cpp b/test/CodeGenCXX/expr.cpp index ae5b0e644f27..4dc97c47aa26 100644 --- a/test/CodeGenCXX/expr.cpp +++ b/test/CodeGenCXX/expr.cpp @@ -1,5 +1,12 @@  // RUN: clang-cc -emit-llvm -x c++ < %s -void f(int x) { +void test0(int x) {            if (x != 0) return;  } + + +// PR5211 +void test1() { +  char *xpto; +  while ( true && xpto[0] ); +} diff --git a/test/CodeGenCXX/mangle-subst.cpp b/test/CodeGenCXX/mangle-subst.cpp index c53a6300aa19..46a21b62b515 100644 --- a/test/CodeGenCXX/mangle-subst.cpp +++ b/test/CodeGenCXX/mangle-subst.cpp @@ -54,3 +54,8 @@ template<typename T> void ft3(S1<T>, S1<char>) {  }  // CHECK: @_ZN2NS3ft3IiEEvNS_2S1IT_EENS1_IcEE  template void ft3<int>(S1<int>, S1<char>);  } + +// PR5196 +// CHECK: @_Z1fPKcS0_ +void f(const char*, const char*) {} + diff --git a/test/CodeGenCXX/member-function-pointers.cpp b/test/CodeGenCXX/member-function-pointers.cpp index 13f7de5a631b..a7c21133d051 100644 --- a/test/CodeGenCXX/member-function-pointers.cpp +++ b/test/CodeGenCXX/member-function-pointers.cpp @@ -71,3 +71,19 @@ namespace PR5177 {    void bar(B1 b2) { while (b2()) ; }  } + +// PR5138 +namespace PR5138 { +  struct foo { +      virtual void bar(foo *); +  }; + +  extern "C" { +    void baz(foo *); +  } +   +  void (foo::*ptr1)(void *) = (void (foo::*)(void *))&foo::bar; +  void (*ptr2)(void *) = (void (*)(void *))&baz; + +  void (foo::*ptr3)(void) = (void (foo::*)(void))&foo::bar; +} diff --git a/test/CodeGenCXX/ptr-to-datamember.cpp b/test/CodeGenCXX/ptr-to-datamember.cpp new file mode 100644 index 000000000000..eee03c060f91 --- /dev/null +++ b/test/CodeGenCXX/ptr-to-datamember.cpp @@ -0,0 +1,70 @@ +// RUN: clang-cc -emit-llvm -o - %s + +extern "C" int printf(...); + +struct F { +  F() : iF(1), fF(2.0) {} +  int iF; +  float fF; +}; + +struct V { +  double d; +  int iV; +}; + +struct B  : virtual V{ +  double d; +  int iB; +}; + +struct B1  : virtual V{ +  double d; +  int iB1; +}; + +class A  : public B, public B1 { +public: +  A() : f(1.0), d(2.0), Ai(3) {} +  float f; +  double d; +  int Ai; +  F Af; +};  + +void pr(const F& b) { +  printf(" %d %f\n", b.iF, b.fF); +} + +void test_aggr_pdata(A& a1) { +  F A::* af = &A::Af; +  pr(a1.*af); + +  (a1.*af).iF = 100; +  (a1.*af).fF = 200.00; +  printf(" %d %f\n", (a1.*af).iF, (a1.*af).fF); +  pr(a1.*af); + +  (a1.*af).iF++; +  (a1.*af).fF--; +  --(a1.*af).fF; +  pr(a1.*af); +} + +int main()  +{ +  A a1; +  int A::* pa = &A::Ai; +  float A::* pf = &A::f; +  double A::* pd = &A::d; +  printf("%d %d %d\n", &A::Ai, &A::f, &A::d); +  printf("%d\n", &A::B::iB); +  printf("%d\n", &A::B1::iB1); +  printf("%d\n", &A::f); +  printf("%d\n", &A::B::iV); +  printf("%d\n", &A::B1::iV); +  printf("%d\n", &A::B::V::iV); +  printf("%d\n", &A::B1::V::iV); +  printf("%d, %f, %f  \n", a1.*pa, a1.*pf, a1.*pd); +  test_aggr_pdata(a1); +} diff --git a/test/CodeGenCXX/references.cpp b/test/CodeGenCXX/references.cpp index 32d46b3e104b..8e0e1cbe84e8 100644 --- a/test/CodeGenCXX/references.cpp +++ b/test/CodeGenCXX/references.cpp @@ -107,3 +107,32 @@ void h() {    const C& c = D();  } +namespace T { +  struct A { +    A(); +    ~A(); +  }; + +  struct B { +    B(); +    ~B(); +    A f(); +  }; + +  void f() { +    // CHECK: call void @_ZN1T1BC1Ev +    // CHECK: call void @_ZN1T1B1fEv +    // CHECK: call void @_ZN1T1BD1Ev +    const A& a = B().f(); +    // CHECK: call void @_ZN1T1fEv +    f(); +    // CHECK: call void @_ZN1T1AD1Ev +  } +} + +// PR5227. +namespace PR5227 { +void f(int &a) { +  (a = 10) = 20; +} +} diff --git a/test/CodeGenCXX/temporaries.cpp b/test/CodeGenCXX/temporaries.cpp new file mode 100644 index 000000000000..d622193f5986 --- /dev/null +++ b/test/CodeGenCXX/temporaries.cpp @@ -0,0 +1,117 @@ +// RUN: clang-cc -emit-llvm %s -o - -triple=x86_64-apple-darwin9 | FileCheck %s +struct A { +  A(); +  ~A(); +  void f(); +}; + +void f1() { +  // CHECK: call void @_ZN1AC1Ev +  // CHECK: call void @_ZN1AD1Ev +  (void)A(); + +  // CHECK: call void @_ZN1AC1Ev +  // CHECK: call void @_ZN1AD1Ev +  A().f(); +} + +// Function calls +struct B { +  B(); +  ~B(); +}; + +B g(); + +void f2() { +  // CHECK-NOT: call void @_ZN1BC1Ev +  // CHECK: call void @_ZN1BD1Ev +  (void)g(); +} + +// Member function calls +struct C { +  C(); +  ~C(); +   +  C f(); +}; + +void f3() { +  // CHECK: call void @_ZN1CC1Ev +  // CHECK: call void @_ZN1CD1Ev +  // CHECK: call void @_ZN1CD1Ev +  C().f(); +} + +// Function call operator +struct D { +  D(); +  ~D(); +   +  D operator()(); +}; + +void f4() { +  // CHECK call void @_ZN1DC1Ev +  // CHECK call void @_ZN1DD1Ev +  // CHECK call void @_ZN1DD1Ev +  D()(); +} + +// Overloaded operators +struct E { +  E(); +  ~E(); +  E operator+(const E&); +  E operator!(); +}; + +void f5() { +  // CHECK: call void @_ZN1EC1Ev +  // CHECK: call void @_ZN1EC1Ev +  // CHECK: call void @_ZN1ED1Ev +  // CHECK: call void @_ZN1ED1Ev +  // CHECK: call void @_ZN1ED1Ev +  E() + E(); +   +  // CHECK: call void @_ZN1EC1Ev +  // CHECK: call void @_ZN1ED1Ev +  // CHECK: call void @_ZN1ED1Ev +  !E(); +} + +struct F { +  F(); +  ~F(); +  F& f(); +}; + +void f6() { +  // CHECK: call void @_ZN1FC1Ev +  // CHECK: call void @_ZN1FD1Ev +  F().f(); +} + +struct G { +  G(); +  G(A); +  ~G(); +  operator A(); +}; + +void a(const A&); + +void f7() { +  // CHECK: call void @_ZN1AC1Ev +  // CHECK: call void @_Z1aRK1A +  // CHECK: call void @_ZN1AD1Ev +  a(A()); +   +  // CHECK: call void @_ZN1GC1Ev +  // CHECK: call void @_ZN1Gcv1AEv +  // CHECK: call void @_Z1aRK1A +  // CHECK: call void @_ZN1AD1Ev +  // CHECK: call void @_ZN1GD1Ev +  a(G()); +} diff --git a/test/Driver/cxx-pth.cpp b/test/Driver/cxx-pth.cpp new file mode 100644 index 000000000000..a06a25753869 --- /dev/null +++ b/test/Driver/cxx-pth.cpp @@ -0,0 +1,12 @@ +// Test forced PTH for CXX support. + +// RUN: clang -x c++-header %s -### 2> %t.log && +// RUN: FileCheck -check-prefix EMIT -input-file %t.log %s && + +// EMIT: "{{.*}}/clang-cc{{.*}}" {{.*}} "-emit-pth" "{{.*}}.cpp.gch" "-x" "c++-header" "{{.*}}.cpp" + +// RUN: touch %t.h.gch && +// RUN: clang -E -include %t.h %s -### 2> %t.log && +// RUN: FileCheck -check-prefix USE -input-file %t.log %s + +// USE: "{{.*}}/clang-cc{{.*}}" {{.*}}"-include-pth" "{{.*}}.h.gch" {{.*}}"-x" "c++" "{{.*}}.cpp" diff --git a/test/Driver/darwin-ld.c b/test/Driver/darwin-ld.c index d81605bbe93d..9165a4a9011f 100644 --- a/test/Driver/darwin-ld.c +++ b/test/Driver/darwin-ld.c @@ -33,7 +33,7 @@  // Note that at conception, this exactly matches gcc.  // RUN: clang -ccc-host-triple i386-apple-darwin9 -### -A ARG0 -F ARG1 -L ARG2 -Mach -T ARG4 -X -Z -all_load -allowable_client ARG8 -bind_at_load -compatibility_version ARG11 -current_version ARG12 -d -dead_strip -dylib_file ARG14 -dylinker -dylinker_install_name ARG16 -dynamic -dynamiclib -e ARG19 -exported_symbols_list ARG20 -fexceptions -flat_namespace -fnested-functions -fopenmp -force_cpusubtype_ALL -fpie -fprofile-arcs -headerpad_max_install_names -image_base ARG29 -init ARG30 -install_name ARG31 -m ARG33 -miphoneos-version-min=2.0 -mmacosx-version-min=10.3.2 -multi_module -multiply_defined ARG37 -multiply_defined_unused ARG38 -no_dead_strip_inits_and_terms -nodefaultlibs -nofixprebinding -nomultidefs -noprebind -noseglinkedit -nostartfiles -nostdlib -pagezero_size ARG54 -pg -prebind -prebind_all_twolevel_modules -preload -r -read_only_relocs ARG55 -s -sectalign ARG57_0 ARG57_1 ARG57_2 -sectcreate ARG58_0 ARG58_1 ARG58_2 -sectobjectsymbols ARG59_0 ARG59_1 -sectorder ARG60_0 ARG60_1 ARG60_2 -seg1addr ARG61 -seg_addr_table ARG62 -seg_addr_table_filename ARG63 -segaddr ARG64_0 ARG64_1 -segcreate ARG65_0 ARG65_1 ARG65_2 -seglinkedit -segprot ARG67_0 ARG67_1 ARG67_2 -segs_read_FOO -segs_read_only_addr ARG69 -segs_read_write_addr ARG70 -shared-libgcc -single_module -static -static-libgcc -sub_library ARG77 -sub_umbrella ARG78 -t -twolevel_namespace -twolevel_namespace_hints -u ARG82 -umbrella ARG83 -undefined ARG84 -unexported_symbols_list ARG85 -w -weak_reference_mismatches ARG87 -whatsloaded -whyload -y -filelist FOO 2> %t.log && -// RUN: grep '".*ld.*" "-static" "-dylib" "-dylib_compatibility_version" "ARG11" "-dylib_current_version" "ARG12" "-arch" "i386" "-dylib_install_name" "ARG31" "-all_load" "-allowable_client" "ARG8" "-bind_at_load" "-dead_strip" "-no_dead_strip_inits_and_terms" "-dylib_file" "ARG14" "-dynamic" "-exported_symbols_list" "ARG20" "-flat_namespace" "-headerpad_max_install_names" "-image_base" "ARG29" "-init" "ARG30" "-macosx_version_min" "10.3.2" "-iphoneos_version_min" "2.0" "-nomultidefs" "-multi_module" "-single_module" "-multiply_defined" "ARG37" "-multiply_defined_unused" "ARG38" "-pie" "-prebind" "-noprebind" "-nofixprebinding" "-prebind_all_twolevel_modules" "-read_only_relocs" "ARG55" "-sectcreate" "ARG58_0" "ARG58_1" "ARG58_2" "-sectorder" "ARG60_0" "ARG60_1" "ARG60_2" "-seg1addr" "ARG61" "-segprot" "ARG67_0" "ARG67_1" "ARG67_2" "-segaddr" "ARG64_0" "ARG64_1" "-segs_read_only_addr" "ARG69" "-segs_read_write_addr" "ARG70" "-seg_addr_table" "ARG62" "-seg_addr_table_filename" "ARG63" "-sub_library" "ARG77" "-sub_umbrella" "ARG78" "-twolevel_namespace" "-twolevel_namespace_hints" "-umbrella" "ARG83" "-undefined" "ARG84" "-unexported_symbols_list" "ARG85" "-weak_reference_mismatches" "ARG87" "-X" "-y" "-w" "-pagezero_size" "ARG54" "-segs_read_FOO" "-seglinkedit" "-noseglinkedit" "-sectalign" "ARG57_0" "ARG57_1" "ARG57_2" "-sectobjectsymbols" "ARG59_0" "ARG59_1" "-segcreate" "ARG65_0" "ARG65_1" "ARG65_2" "-whyload" "-whatsloaded" "-dylinker_install_name" "ARG16" "-dylinker" "-Mach" "-d" "-s" "-t" "-Z" "-u" "ARG82" "-undefined" "ARG84" "-A" "ARG0" "-e" "ARG19" "-m" "ARG33" "-r" "-o" "a.out" "-L" "ARG2" "-lgomp" "-L/usr/lib/i686-apple-darwin9/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin9/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin9/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin9/4.2.1/../../../i686-apple-darwin9/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin9/4.2.1/../../.." "-filelist" "FOO" "-lgcov" "-allow_stack_execute" "-T" "ARG4" "-F" "ARG1"' %t.log && +// RUN: grep '".*ld.*" "-static" "-dylib" "-dylib_compatibility_version" "ARG11" "-dylib_current_version" "ARG12" "-arch" "i386" "-dylib_install_name" "ARG31" "-all_load" "-allowable_client" "ARG8" "-bind_at_load" "-dead_strip" "-no_dead_strip_inits_and_terms" "-dylib_file" "ARG14" "-dynamic" "-exported_symbols_list" "ARG20" "-flat_namespace" "-headerpad_max_install_names" "-image_base" "ARG29" "-init" "ARG30" "-macosx_version_min" "10.3.2" "-iphoneos_version_min" "2.0" "-nomultidefs" "-multi_module" "-single_module" "-multiply_defined" "ARG37" "-multiply_defined_unused" "ARG38" "-pie" "-prebind" "-noprebind" "-nofixprebinding" "-prebind_all_twolevel_modules" "-read_only_relocs" "ARG55" "-sectcreate" "ARG58_0" "ARG58_1" "ARG58_2" "-sectorder" "ARG60_0" "ARG60_1" "ARG60_2" "-seg1addr" "ARG61" "-segprot" "ARG67_0" "ARG67_1" "ARG67_2" "-segaddr" "ARG64_0" "ARG64_1" "-segs_read_only_addr" "ARG69" "-segs_read_write_addr" "ARG70" "-seg_addr_table" "ARG62" "-seg_addr_table_filename" "ARG63" "-sub_library" "ARG77" "-sub_umbrella" "ARG78" "-twolevel_namespace" "-twolevel_namespace_hints" "-umbrella" "ARG83" "-undefined" "ARG84" "-unexported_symbols_list" "ARG85" "-weak_reference_mismatches" "ARG87" "-X" "-y" "-w" "-pagezero_size" "ARG54" "-segs_read_FOO" "-seglinkedit" "-noseglinkedit" "-sectalign" "ARG57_0" "ARG57_1" "ARG57_2" "-sectobjectsymbols" "ARG59_0" "ARG59_1" "-segcreate" "ARG65_0" "ARG65_1" "ARG65_2" "-whyload" "-whatsloaded" "-dylinker_install_name" "ARG16" "-dylinker" "-Mach" "-d" "-s" "-t" "-Z" "-u" "ARG82" "-undefined" "ARG84" "-A" "ARG0" "-e" "ARG19" "-m" "ARG33" "-r" "-o" "a.out" "-L" "ARG2" "-lgomp" "-L/usr/lib/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1/../../../i686-apple-darwin.*/4.2.1" "-L/usr/lib/gcc/i686-apple-darwin.*/4.2.1/../../.." "-filelist" "FOO" "-lgcov" "-allow_stack_execute" "-T" "ARG4" "-F" "ARG1"' %t.log &&  // Don't run dsymutil on a fat build of an executable.  // RUN: clang -ccc-host-triple i386-apple-darwin9 -### -arch i386 -arch x86_64 -g %s 2> %t.log && diff --git a/test/Index/c-index-pch.c b/test/Index/c-index-pch.c new file mode 100644 index 000000000000..aae4eb3669fc --- /dev/null +++ b/test/Index/c-index-pch.c @@ -0,0 +1,14 @@ +// RUN: clang-cc -emit-pch -x c -o %t.pch %S/c-index-pch.h && +// RUN: clang-cc -include-pch %t.pch -x c -emit-pch -o %t.ast %s && +// RUN: c-index-test %t.ast all | FileCheck -check-prefix=ALL %s && +// RUN: c-index-test %t.ast local | FileCheck -check-prefix=LOCAL %s +// ALL: FunctionDecl=foo +// ALL: VarDecl=bar +// ALL: FunctionDecl=wibble +// ALL: FunctionDecl=wonka +// LOCAL-NOT: FunctionDecl=foo +// LOCAL-NOT: VarDecl=bar +// LOCAL: FunctionDecl=wibble +// LOCAL: FunctionDecl=wonka +void wibble(int i); +void wonka(float); diff --git a/test/Index/c-index-pch.h b/test/Index/c-index-pch.h new file mode 100644 index 000000000000..6dda18000c2f --- /dev/null +++ b/test/Index/c-index-pch.h @@ -0,0 +1,7 @@ +#ifndef C_INDEX_PCH_H +#define C_INDEX_PCH_H + +void foo(int i, float f); +extern int bar; + +#endif // C_INDEX_PCH_H diff --git a/test/Misc/message-length.c b/test/Misc/message-length.c index ac5dab99ca52..9f4d66fe71c0 100644 --- a/test/Misc/message-length.c +++ b/test/Misc/message-length.c @@ -1,14 +1,7 @@ -// RUN: clang -fsyntax-only -fmessage-length=72 %s 2> %t && - -// RUN: grep -A4 "FILE:23" %t > %t.msg && -// FIXME: This diagnostic is getting truncated very poorly. -// RUN: grep -e '^  ...// some long comment text and a brace, eh {} ' %t.msg && -// RUN: grep -e '^                                                 \^' %t.msg && -// RUN: clang -fsyntax-only -fmessage-length=1 %s && -// RUN: true +// RUN: clang -fsyntax-only -fmessage-length=72 %s 2>&1 | FileCheck -strict-whitespace %s && +// RUN: clang -fsyntax-only -fmessage-length=1 %s  // Hack so we can check things better, force the file name and line. -  # 1 "FILE" 1  /* It's tough to verify the results of this test mechanically, since @@ -33,3 +26,7 @@ void a_very_long_line(int *ip, float *FloatPointer) {  }  #pragma STDC CX_LIMITED_RANGE    // some long comment text and a brace, eh {} + + +// CHECK: FILE:23:78 +// CHECK: {{^  ...// some long comment text and a brace, eh {} $}} diff --git a/test/Preprocessor/macro_paste_bcpl_comment.c b/test/Preprocessor/macro_paste_bcpl_comment.c index 8bbee5dc2dd9..0637a8721739 100644 --- a/test/Preprocessor/macro_paste_bcpl_comment.c +++ b/test/Preprocessor/macro_paste_bcpl_comment.c @@ -1,4 +1,4 @@ -// RUN: clang-cc %s -Eonly 2>&1 | grep error +// RUN: clang-cc %s -Eonly -fms-extensions=0 2>&1 | grep error  #define COMM1 / ## /  COMM1 diff --git a/test/Sema/attr-noreturn.c b/test/Sema/attr-noreturn.c index b83eb94e0582..14011bedca1a 100644 --- a/test/Sema/attr-noreturn.c +++ b/test/Sema/attr-noreturn.c @@ -15,14 +15,14 @@ int f2() __attribute__((noreturn(1, 2))); // expected-error {{attribute requires  void f3() __attribute__((noreturn));  void f3() { -  return;  // expected-error {{function 'f3' declared 'noreturn' should not return}} +  return;  // expected-warning {{function 'f3' declared 'noreturn' should not return}}  } -#pragma clang diagnostic warning "-Winvalid-noreturn" +#pragma clang diagnostic error "-Winvalid-noreturn"  void f4() __attribute__((noreturn));  void f4() { -  return;  // expected-warning {{function 'f4' declared 'noreturn' should not return}} +  return;  // expected-error {{function 'f4' declared 'noreturn' should not return}}  }  // PR4685 diff --git a/test/Sema/exprs.c b/test/Sema/exprs.c index 69a2320397fd..2bcc0f8a2ca0 100644 --- a/test/Sema/exprs.c +++ b/test/Sema/exprs.c @@ -103,3 +103,12 @@ void test14() {    __m64 mask = (__m64)((__v4hi)a > (__v4hi)a);  } + +// PR5242 +typedef unsigned long *test15_t; + +test15_t test15(void) { +  return (test15_t)0 + (test15_t)0;  // expected-error {{invalid operands to binary expression ('test15_t' (aka 'unsigned long *') and 'test15_t')}} +} + + diff --git a/test/Sema/switch.c b/test/Sema/switch.c index 5999f342aefa..122947e7ce5c 100644 --- a/test/Sema/switch.c +++ b/test/Sema/switch.c @@ -68,3 +68,10 @@ void test5(int z) {    }  }  +void test6() { +  const char ch = 'a'; +  switch(ch) { +    case 1234:  // expected-warning {{overflow converting case value}} +      break; +  } +} diff --git a/test/Sema/vector-assign.c b/test/Sema/vector-assign.c index 5162e1a41c21..bf9c7f37ca6d 100644 --- a/test/Sema/vector-assign.c +++ b/test/Sema/vector-assign.c @@ -5,7 +5,7 @@ typedef signed int v1s __attribute__ ((vector_size (4)));  typedef float v2f __attribute__ ((vector_size(8)));  typedef signed short v4ss __attribute__ ((vector_size (8))); -void f() { +void test1() {    v2s v1;    v2u v2;    v1s v3; @@ -39,7 +39,15 @@ void f() {  }  // PR2263 -float f2(__attribute__((vector_size(16))) float a, int b) { +float test2(__attribute__((vector_size(16))) float a, int b) {     return a[b];  } +// PR4838 +typedef long long __attribute__((__vector_size__(2 * sizeof(long long)))) +longlongvec; + +void test3a(longlongvec *); +void test3(const unsigned *src) { +  test3a(src);  // expected-warning {{incompatible pointer types passing 'unsigned int const *', expected 'longlongvec *'}} +} diff --git a/test/Sema/vector-init.c b/test/Sema/vector-init.c index 6eab32425adf..18104d871d6c 100644 --- a/test/Sema/vector-init.c +++ b/test/Sema/vector-init.c @@ -21,3 +21,10 @@ float4 array3[2] = { {1.0, 2.0, 3.0}, 5.0, 6.0, 7.0, 8.0,  __attribute__((vector_size(16))) // expected-error {{unsupported type 'float (void)' for vector_size attribute, please use on typedef}}  float f1(void) {  } + + + +// PR5265 +typedef float __attribute__((ext_vector_type (3))) float3; +int test2[(sizeof(float3) == sizeof(float4))*2-1]; + diff --git a/test/SemaCXX/abstract.cpp b/test/SemaCXX/abstract.cpp index e14304a26fe3..42b8d7febe65 100644 --- a/test/SemaCXX/abstract.cpp +++ b/test/SemaCXX/abstract.cpp @@ -123,3 +123,18 @@ struct K {  struct L : public K {   void f();  }; + +// PR5222 +namespace PR5222 { +  struct A { +    virtual A *clone() = 0; +  }; +  struct B : public A { +    virtual B *clone() = 0; +  }; +  struct C : public B { +    virtual C *clone(); +  }; + +  C c;   +} diff --git a/test/SemaCXX/ambiguous-builtin-unary-operator.cpp b/test/SemaCXX/ambiguous-builtin-unary-operator.cpp index 042546af6902..5affd19a2fdf 100644 --- a/test/SemaCXX/ambiguous-builtin-unary-operator.cpp +++ b/test/SemaCXX/ambiguous-builtin-unary-operator.cpp @@ -2,17 +2,33 @@  struct A {    operator int&(); +  operator long*& ();  };  struct B {    operator long&(); +  operator int*& ();  };  struct C : B, A { };  void test(C c) {    ++c; // expected-error {{use of overloaded operator '++' is ambiguous}}\ -       // expected-note 4 {{built-in candidate operator ++ (}} +       // expected-note {{built-in candidate operator++(int &)}} \ +       // expected-note {{built-in candidate operator++(long &)}} \ +       // expected-note {{built-in candidate operator++(long *&)}} \ +       // expected-note {{built-in candidate operator++(int *&)}}  } +struct A1 { operator volatile int&(); }; + +struct B1 { operator volatile long&(); }; + +struct C1 : B1, A1 { }; + +void test(C1 c) { +  ++c;	// expected-error {{use of overloaded operator '++' is ambiguous}} \ +	// expected-note {{built-in candidate operator++(int volatile &)}} \ +	// expected-note {{built-in candidate operator++(long volatile &)}} +} diff --git a/test/SemaCXX/bool.cpp b/test/SemaCXX/bool.cpp index bc44c73d8cac..259c09c6cb83 100644 --- a/test/SemaCXX/bool.cpp +++ b/test/SemaCXX/bool.cpp @@ -16,3 +16,15 @@ void test(bool b)    bool *b1 = (int *)0; // expected-error{{expected 'bool *'}}  } + +// static_assert_arg_is_bool(x) compiles only if x is a bool. +template <typename T> +void static_assert_arg_is_bool(T x) { +  bool* p = &x; +} + +void test2() { +  int n = 2; +  static_assert_arg_is_bool(n && 4); +  static_assert_arg_is_bool(n || 5); +} diff --git a/test/SemaCXX/builtin-ptrtomember-ambig.cpp b/test/SemaCXX/builtin-ptrtomember-ambig.cpp index 7e20af35394b..1b52651910d9 100644 --- a/test/SemaCXX/builtin-ptrtomember-ambig.cpp +++ b/test/SemaCXX/builtin-ptrtomember-ambig.cpp @@ -19,6 +19,9 @@ struct C : B {  void foo(C c, int A::* pmf) {         				// FIXME. Why so many built-in candidates?  	int i = c->*pmf; 	// expected-error {{use of overloaded operator '->*' is ambiguous}} \ -				// expected-note 40 {{built-in candidate operator ->* ('struct A}} +				// expected-note {{built-in candidate operator->*(struct A const *, int const struct A::*)}} \ +				// expected-note {{built-in candidate operator->*(struct A const *, int struct A::*)}} \ +				// expected-note {{built-in candidate operator->*(struct A *, int const struct A::*)}} \ +				// expected-note {{built-in candidate operator->*(struct A *, int struct A::*)}}  } diff --git a/test/SemaCXX/builtin-ptrtomember-overload.cpp b/test/SemaCXX/builtin-ptrtomember-overload.cpp index 718e981805aa..ed52d47f2cda 100644 --- a/test/SemaCXX/builtin-ptrtomember-overload.cpp +++ b/test/SemaCXX/builtin-ptrtomember-overload.cpp @@ -16,3 +16,15 @@ void foo(C c, B b, int A::* pmf) {  	int i = b->*pmf;  } +struct D { + operator const D *(); +}; + +struct DPtr { + operator volatile int D::*(); +}; + +int test(D d, DPtr dptr) { + return d->*dptr; +} + diff --git a/test/SemaCXX/exception-spec.cpp b/test/SemaCXX/exception-spec.cpp index 9b2a07d79654..56cc435f7db3 100644 --- a/test/SemaCXX/exception-spec.cpp +++ b/test/SemaCXX/exception-spec.cpp @@ -185,3 +185,6 @@ void mfnptr()  template <typename T> struct TEx; // expected-note {{template is declared here}}  void tf() throw(TEx<int>); // expected-error {{implicit instantiation of undefined template}} + +// DR 437, class throws itself. FIXME: See Sema::CheckSpecifiedExceptionType. +//struct DR437 { void f() throw(DR437); }; diff --git a/test/SemaCXX/incomplete-call.cpp b/test/SemaCXX/incomplete-call.cpp index 08bfdefd6247..3ce898a76f2c 100644 --- a/test/SemaCXX/incomplete-call.cpp +++ b/test/SemaCXX/incomplete-call.cpp @@ -40,3 +40,10 @@ void g() {    (b.*mfp)(); // expected-error {{calling function with incomplete return type 'struct A'}}  } + + +struct C; // expected-note{{forward declaration}} + +void test_incomplete_object_call(C& c) { +  c(); // expected-error{{incomplete type in call to object of type}} +} diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index 28b1224d8d8f..069f52605b92 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -31,3 +31,14 @@ int f0(B *b) {    return b->f0->f0; // expected-error{{member reference base type 'struct A *()' is not a structure or union}} \    // expected-note{{perhaps you meant to call this function}}  } + +int i; + +namespace C { +  int i; +} + +void test2(X *xp) { +  xp->::i = 7; // expected-error{{qualified member access refers to a member in the global namespace}} +  xp->C::i = 7; // expected-error{{qualified member access refers to a member in namespace 'C'}} +} diff --git a/test/SemaCXX/overloaded-builtin-operators.cpp b/test/SemaCXX/overloaded-builtin-operators.cpp index 0284b2929b3c..13777daf2d20 100644 --- a/test/SemaCXX/overloaded-builtin-operators.cpp +++ b/test/SemaCXX/overloaded-builtin-operators.cpp @@ -150,3 +150,28 @@ void test_with_ptrs(VolatileIntPtr vip, ConstIntPtr cip, ShortRef sr,  void test_assign_restrictions(ShortRef& sr) {    sr = (short)0; // expected-error{{no viable overloaded '='}}  } + +struct Base { }; +struct Derived1 : Base { }; +struct Derived2 : Base { }; + +template<typename T> +struct ConvertibleToPtrOf { +  operator T*(); +}; + +bool test_with_base_ptrs(ConvertibleToPtrOf<Derived1> d1,  +                         ConvertibleToPtrOf<Derived2> d2) { +  return d1 == d2; // expected-error{{invalid operands}} +} + +// DR425 +struct A { +  template< typename T > operator T() const; +}; + +void test_dr425(A a) { +  // FIXME: lots of candidates here! +  (void)(1.0f * a); // expected-error{{ambiguous}} \ +                    // expected-note 81{{candidate}} +} diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 8f71ad538138..10b0f5a76804 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -155,7 +155,7 @@ typedef INTREF Func1(FLOAT, double);  typedef float& Func2(int, double);  struct ConvertToFunc { -  operator Func1*(); // expected-note{{conversion candidate of type 'INTREF (*)(float, double)'}} +  operator Func1*(); // expected-note{{conversion candidate of type 'INTREF (*)(FLOAT, double)'}}    operator Func2&(); // expected-note{{conversion candidate of type 'float &(&)(int, double)'}}    void operator()();  }; diff --git a/test/SemaCXX/ptrtomember-overload-resolution.cpp b/test/SemaCXX/ptrtomember-overload-resolution.cpp new file mode 100644 index 000000000000..b3b65ce840cb --- /dev/null +++ b/test/SemaCXX/ptrtomember-overload-resolution.cpp @@ -0,0 +1,44 @@ +// RUN: clang-cc -fsyntax-only -verify %s -std=c++0x + +// 13.3.3.2 Ranking implicit conversion sequences +// conversion of A::* to B::* is better than conversion of A::* to C::*, +struct A { +int Ai; +};  + +struct B : public A {};  +struct C : public B {};  + +const char * f(int C::*){ return ""; }  +int f(int B::*) { return 1; }  + +struct D : public C {};  + +const char * g(int B::*){ return ""; }  +int g(int D::*) { return 1; }  + +void test()  +{ +  int i = f(&A::Ai); + +  const char * str = g(&A::Ai); +} + +// conversion of B::* to C::* is better than conversion of A::* to C::* +typedef void (A::*pmfa)(); +typedef void (B::*pmfb)(); +typedef void (C::*pmfc)(); + +struct X { +	operator pmfa(); +	operator pmfb(); +}; + + +void g(pmfc); + +void test2(X x)  +{ +    g(x); +} + diff --git a/test/SemaCXX/static-cast.cpp b/test/SemaCXX/static-cast.cpp index 8db8e33b93ce..d816c05e3ee3 100644 --- a/test/SemaCXX/static-cast.cpp +++ b/test/SemaCXX/static-cast.cpp @@ -133,3 +133,14 @@ void t_529_9()    (void)static_cast<int A::*>((int H::*)0); // expected-error {{ambiguous conversion from pointer to member of derived class 'struct H'}}    (void)static_cast<int A::*>((int F::*)0); // expected-error {{conversion from pointer to member of class 'struct F'}}  } + +// PR 5261 - static_cast should instantiate template if possible +namespace pr5261 { +  struct base {}; +  template<typename E> struct derived : public base {}; +  template<typename E> struct outer { +    base *pb; +    ~outer() { (void)static_cast<derived<E>*>(pb); } +  }; +  outer<int> EntryList; +} diff --git a/test/SemaCXX/switch.cpp b/test/SemaCXX/switch.cpp new file mode 100644 index 000000000000..b22adb749576 --- /dev/null +++ b/test/SemaCXX/switch.cpp @@ -0,0 +1,15 @@ +// RUN: clang-cc -fsyntax-only -verify %s + +void test() { +  bool x = true; +  switch (x) { // expected-warning {{bool}} +    case 0: +      break; +  } + +  int n = 3; +  switch (n && 1) { // expected-warning {{bool}} +    case 1: +      break; +  } +} diff --git a/test/SemaObjC/objc-string-constant.m b/test/SemaObjC/objc-string-constant.m index 98239229a2c7..d27a46a96632 100644 --- a/test/SemaObjC/objc-string-constant.m +++ b/test/SemaObjC/objc-string-constant.m @@ -29,7 +29,7 @@  @end  @implementation Subclass -- (NSString *)token; +- (NSString *)token;	// expected-warning {{semicolon before method body is ignored}}  {    NSMutableString *result = nil; diff --git a/test/SemaObjC/try-catch.m b/test/SemaObjC/try-catch.m index 076eff542968..453d80fd5996 100644 --- a/test/SemaObjC/try-catch.m +++ b/test/SemaObjC/try-catch.m @@ -30,7 +30,7 @@ typedef struct _NSZone NSZone;  @end  @implementation XCRefactoringTransformation -- (NSDictionary *)setUpInfoForTransformKey:(NSString *)transformKey outError:(NSError **)outError; { +- (NSDictionary *)setUpInfoForTransformKey:(NSString *)transformKey outError:(NSError **)outError {      @try {}      // the exception name is optional (weird)      @catch (NSException *) {} diff --git a/test/SemaTemplate/extern-templates.cpp b/test/SemaTemplate/extern-templates.cpp index 28fda1a11e6b..44728d188a24 100644 --- a/test/SemaTemplate/extern-templates.cpp +++ b/test/SemaTemplate/extern-templates.cpp @@ -29,16 +29,14 @@ void test_intptr(X0<int*> xi, X0<int*>::Inner xii) {    xii.g(0);  } -// FIXME: we would like the notes to point to the explicit instantiation at the -// bottom. -extern template class X0<long*>; // expected-note 2{{instantiation}} +extern template class X0<long*>;   void test_longptr(X0<long*> xl, X0<long*>::Inner xli) {    xl.f(0);    xli.g(0);  } -template class X0<long*>; +template class X0<long*>; // expected-note 2{{instantiation}}  template<typename T>  class X1 { diff --git a/test/SemaTemplate/fun-template-def.cpp b/test/SemaTemplate/fun-template-def.cpp index dee425007898..4d8aaa8d16f1 100644 --- a/test/SemaTemplate/fun-template-def.cpp +++ b/test/SemaTemplate/fun-template-def.cpp @@ -35,7 +35,7 @@ T f1(T t1, U u1, int i1)      dynamic_cast<U>(const_cast<T>(i1)))));    new U(i1, t1); -  new int(t1, u1); // expected-error {{initializer of a builtin type can only take one argument}} +  new int(t1, u1);    new (t1, u1) int;    delete t1; diff --git a/test/SemaTemplate/instantiate-expr-2.cpp b/test/SemaTemplate/instantiate-expr-2.cpp index 146e63c5bb00..194593ac4006 100644 --- a/test/SemaTemplate/instantiate-expr-2.cpp +++ b/test/SemaTemplate/instantiate-expr-2.cpp @@ -178,3 +178,18 @@ namespace N10 {    template class A<int>;  } + +namespace N12 { +  // PR5224 +  template<typename T> +  struct A { typedef int t0; }; +   +  struct C  { +    C(int); +     +    template<typename T> +    static C *f0(T a0) {return new C((typename A<T>::t0) 1);   } +  }; + +  void f0(int **a) { C::f0(a); } +} diff --git a/test/SemaTemplate/member-access-expr.cpp b/test/SemaTemplate/member-access-expr.cpp index f4922e8ff520..0a6a6bc0990e 100644 --- a/test/SemaTemplate/member-access-expr.cpp +++ b/test/SemaTemplate/member-access-expr.cpp @@ -74,4 +74,17 @@ void test_destruct(X2 *x2p, int *ip) {    destruct(x2p);    destruct(ip);    destruct_intptr<int>(ip); -}
\ No newline at end of file +} + +// PR5220 +class X3 { +protected: +  template <int> float* &f0(); +  template <int> const float* &f0() const; +  void f1() { +    (void)static_cast<float*>(f0<0>()); +  } +  void f1() const{ +    (void)f0<0>(); +  } +}; diff --git a/test/SemaTemplate/member-template-access-expr.cpp b/test/SemaTemplate/member-template-access-expr.cpp index 20437aee39dc..0f9f21f339d1 100644 --- a/test/SemaTemplate/member-template-access-expr.cpp +++ b/test/SemaTemplate/member-template-access-expr.cpp @@ -24,7 +24,29 @@ struct XDerived : public X {  };  void test_f1(XDerived xd) { -  // FIXME: Not quite functional yet. -//  int &ir = f1<X>(xd); +  int &ir = f1<X>(xd);  } +// PR5213 +template <class T> +struct A {}; + +template<class T> +class B +{ +  A<T> a_; +   +public: +  void destroy(); +}; + +template<class T> +void +B<T>::destroy() +{ +  a_.~A<T>(); +} + +void do_destroy_B(B<int> b) { +  b.destroy(); +} diff --git a/test/SemaTemplate/variadic-class-template-2.cpp b/test/SemaTemplate/variadic-class-template-2.cpp index eadea901c7fe..b1ac71b88bda 100644 --- a/test/SemaTemplate/variadic-class-template-2.cpp +++ b/test/SemaTemplate/variadic-class-template-2.cpp @@ -14,6 +14,6 @@ template struct TS2<int, int>;  template <typename = int, typename ...> struct TS3 {}; // expected-note{{template parameter is declared here}}  template struct TS3<>; // expected-note{{previous explicit instantiation is here}} -template struct TS3<int>; // expected-error{{duplicate explicit instantiation of 'TS3<>'}} +template struct TS3<int>; // expected-error{{duplicate explicit instantiation of 'TS3}}  template struct TS3<int, int>;  template struct TS3<10>; // expected-error{{template argument for template type parameter must be a type}} diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp index 9204d1863d67..64dfcfea5143 100644 --- a/tools/CIndex/CIndex.cpp +++ b/tools/CIndex/CIndex.cpp @@ -22,12 +22,27 @@  #include "clang/Basic/FileManager.h"  #include "clang/Basic/SourceManager.h"  #include "clang/Frontend/ASTUnit.h" +#include "llvm/Config/config.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/System/Path.h" +#include "llvm/System/Program.h" +#include "llvm/Support/raw_ostream.h" +  #include <cstdio> +#include <vector> + +#ifdef LLVM_ON_WIN32 +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#else +#include <dlfcn.h> +#endif +  using namespace clang;  using namespace idx;  namespace { -  static enum CXCursorKind TranslateDeclRefExpr(DeclRefExpr *DRE)   {    NamedDecl *D = DRE->getDecl(); @@ -76,6 +91,14 @@ public:    }  };  #endif +   +/// IgnoreDiagnosticsClient - A DiagnosticsClient that just ignores emitted +/// warnings and errors. +class VISIBILITY_HIDDEN IgnoreDiagnosticsClient : public DiagnosticClient { +public: +  virtual ~IgnoreDiagnosticsClient() {} +  virtual void HandleDiagnostic(Diagnostic::Level, const DiagnosticInfo &) {}   +};  // Translation Unit Visitor.  class TUVisitor : public DeclVisitor<TUVisitor> { @@ -83,14 +106,24 @@ class TUVisitor : public DeclVisitor<TUVisitor> {    CXTranslationUnitIterator Callback;    CXClientData CData; +  // MaxPCHLevel - the maximum PCH level of declarations that we will pass on +  // to the visitor. Declarations with a PCH level greater than this value will +  // be suppressed. +  unsigned MaxPCHLevel; +      void Call(enum CXCursorKind CK, NamedDecl *ND) { +    // Filter any declarations that have a PCH level greater than what we allow. +    if (ND->getPCHLevel() > MaxPCHLevel) +      return; +          CXCursor C = { CK, ND, 0 };      Callback(TUnit, C, CData);    }  public:    TUVisitor(CXTranslationUnit CTU,  -            CXTranslationUnitIterator cback, CXClientData D) :  -    TUnit(CTU), Callback(cback), CData(D) {} +            CXTranslationUnitIterator cback, CXClientData D, +            unsigned MaxPCHLevel) :  +    TUnit(CTU), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}    void VisitTranslationUnitDecl(TranslationUnitDecl *D) {      VisitDeclContext(dyn_cast<DeclContext>(D)); @@ -149,16 +182,27 @@ class CDeclVisitor : public DeclVisitor<CDeclVisitor> {    CXDeclIterator Callback;    CXClientData CData; +  // MaxPCHLevel - the maximum PCH level of declarations that we will pass on +  // to the visitor. Declarations with a PCH level greater than this value will +  // be suppressed. +  unsigned MaxPCHLevel; +      void Call(enum CXCursorKind CK, NamedDecl *ND) {      // Disable the callback when the context is equal to the visiting decl.      if (CDecl == ND && !clang_isReference(CK))        return; +     +    // Filter any declarations that have a PCH level greater than what we allow. +    if (ND->getPCHLevel() > MaxPCHLevel) +      return; +          CXCursor C = { CK, ND, 0 };      Callback(CDecl, C, CData);    }  public: -  CDeclVisitor(CXDecl C, CXDeclIterator cback, CXClientData D) :  -    CDecl(C), Callback(cback), CData(D) {} +  CDeclVisitor(CXDecl C, CXDeclIterator cback, CXClientData D,  +               unsigned MaxPCHLevel) :  +    CDecl(C), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}    void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {      // Issue callbacks for the containing class. @@ -237,20 +281,87 @@ public:    }  }; +class CIndexer : public Indexer { +public:   +  explicit CIndexer(Program *prog) : Indexer(*prog),  +                                     OnlyLocalDecls(false),  +                                     DisplayDiagnostics(false) {} + +  virtual ~CIndexer() { delete &getProgram(); } + +  /// \brief Whether we only want to see "local" declarations (that did not +  /// come from a previous precompiled header). If false, we want to see all +  /// declarations. +  bool getOnlyLocalDecls() const { return OnlyLocalDecls; } +  void setOnlyLocalDecls(bool Local = true) { OnlyLocalDecls = Local; } + +  void setDisplayDiagnostics(bool Display = true) {  +    DisplayDiagnostics = Display; +  } +  bool getDisplayDiagnostics() const { return DisplayDiagnostics; } +   +  /// \brief Get the path of the clang binary. +  const llvm::sys::Path& getClangPath(); +private: +  bool OnlyLocalDecls; +  bool DisplayDiagnostics; +   +  llvm::sys::Path ClangPath; +}; + +const llvm::sys::Path& CIndexer::getClangPath() { +  // Did we already compute the path? +  if (!ClangPath.empty()) +    return ClangPath; + +  // Find the location where this library lives (libCIndex.dylib). +#ifdef LLVM_ON_WIN32 +  MEMORY_BASIC_INFORMATION mbi; +  char path[MAX_PATH]; +  VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi, +               sizeof(mbi)); +  GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH); + +  llvm::sys::Path CIndexPath(path); +#else +  // This silly cast below avoids a C++ warning. +  Dl_info info; +  if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0) +    assert(0 && "Call to dladdr() failed"); + +  llvm::sys::Path CIndexPath(info.dli_fname); +#endif + +  // We now have the CIndex directory, locate clang relative to it. +  CIndexPath.eraseComponent(); +  CIndexPath.eraseComponent(); +  CIndexPath.appendComponent("bin"); +  CIndexPath.appendComponent("clang"); + +  // Cache our result. +  ClangPath = CIndexPath; +  return ClangPath; +} +  }  extern "C" { -CXIndex clang_createIndex()  -{ -  // FIXME: Program is leaked. -  return new Indexer(*new Program()); +CXIndex clang_createIndex(int excludeDeclarationsFromPCH, +                          int displayDiagnostics)  +{   +  CIndexer *CIdxr = new CIndexer(new Program()); +  if (excludeDeclarationsFromPCH) +    CIdxr->setOnlyLocalDecls(); +  if (displayDiagnostics) +    CIdxr->setDisplayDiagnostics(); +  return CIdxr;  }  void clang_disposeIndex(CXIndex CIdx)  {    assert(CIdx && "Passed null CXIndex"); -  delete static_cast<Indexer *>(CIdx); +  delete static_cast<CIndexer *>(CIdx);  }  // FIXME: need to pass back error info. @@ -258,12 +369,102 @@ CXTranslationUnit clang_createTranslationUnit(    CXIndex CIdx, const char *ast_filename)   {    assert(CIdx && "Passed null CXIndex"); -  Indexer *CXXIdx = static_cast<Indexer *>(CIdx); +  CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);    std::string astName(ast_filename);    std::string ErrMsg; -  return ASTUnit::LoadFromPCHFile(astName, CXXIdx->getDiagnostics(), -                                  CXXIdx->getFileManager(), &ErrMsg); +  CXTranslationUnit TU = +    ASTUnit::LoadFromPCHFile(astName, &ErrMsg,  +                           CXXIdx->getDisplayDiagnostics() ?  +                           NULL : new IgnoreDiagnosticsClient(), +                           CXXIdx->getOnlyLocalDecls(), +                           /* UseBumpAllocator = */ true); +   +  if (!ErrMsg.empty()) { +    (llvm::errs() << "clang_createTranslationUnit: " << ErrMsg  +                  << '\n').flush(); +  } +   +  return TU; +} + +CXTranslationUnit clang_createTranslationUnitFromSourceFile( +  CXIndex CIdx,  +  const char *source_filename, +  int num_command_line_args, const char **command_line_args)  { +  assert(CIdx && "Passed null CXIndex"); +  CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx); + +  // Build up the arguments for invoking 'clang'. +  std::vector<const char *> argv; +   +  // First add the complete path to the 'clang' executable. +  llvm::sys::Path ClangPath = static_cast<CIndexer *>(CIdx)->getClangPath(); +  argv.push_back(ClangPath.c_str()); +   +  // Add the '-emit-ast' option as our execution mode for 'clang'. +  argv.push_back("-emit-ast"); +   +  // The 'source_filename' argument is optional.  If the caller does not +  // specify it then it is assumed that the source file is specified +  // in the actual argument list. +  if (source_filename)   +    argv.push_back(source_filename);   + +  // Generate a temporary name for the AST file. +  argv.push_back("-o"); +  char astTmpFile[L_tmpnam]; +  argv.push_back(tmpnam(astTmpFile)); + +  // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'. +  for (int i = 0; i < num_command_line_args; ++i) +    if (const char *arg = command_line_args[i]) { +      if (strcmp(arg, "-o") == 0) { +        ++i; // Also skip the matching argument. +        continue; +      } +      if (strcmp(arg, "-emit-ast") == 0 || +          strcmp(arg, "-c") == 0 || +          strcmp(arg, "-fsyntax-only") == 0) { +        continue; +      } + +      // Keep the argument. +      argv.push_back(arg); +    } +     +  // Add the null terminator. +  argv.push_back(NULL); + +#ifndef LLVM_ON_WIN32 +  llvm::sys::Path DevNull("/dev/null"); +  std::string ErrMsg; +  const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DevNull, NULL }; +  llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL, +      /* redirects */ !CXXIdx->getDisplayDiagnostics() ? &Redirects[0] : NULL, +      /* secondsToWait */ 0, /* memoryLimits */ 0, &ErrMsg); +   +  if (!ErrMsg.empty()) { +    llvm::errs() << "clang_createTranslationUnitFromSourceFile: " << ErrMsg  +      << '\n' << "Arguments: \n"; +    for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end(); +         I!=E; ++I) +      if (*I) llvm::errs() << ' ' << *I << '\n'; +      +    (llvm::errs() << '\n').flush(); +  } +#else +  // FIXME: I don't know what is the equivalent '/dev/null' redirect for +  // Windows for this API. +  llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0]); +#endif + +  // Finally, we create the translation unit from the ast file. +  ASTUnit *ATU = static_cast<ASTUnit *>( +                   clang_createTranslationUnit(CIdx, astTmpFile)); +  if (ATU) +    ATU->unlinkTemporaryFile(); +  return ATU;  }  void clang_disposeTranslationUnit( @@ -272,7 +473,7 @@ void clang_disposeTranslationUnit(    assert(CTUnit && "Passed null CXTranslationUnit");    delete static_cast<ASTUnit *>(CTUnit);  } - +    const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)  {    assert(CTUnit && "Passed null CXTranslationUnit"); @@ -288,7 +489,8 @@ void clang_loadTranslationUnit(CXTranslationUnit CTUnit,    ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);    ASTContext &Ctx = CXXUnit->getASTContext(); -  TUVisitor DVisit(CTUnit, callback, CData); +  TUVisitor DVisit(CTUnit, callback, CData,  +                   CXXUnit->getOnlyLocalDecls()? 1 : Decl::MaxPCHLevel);    DVisit.Visit(Ctx.getTranslationUnitDecl());  } @@ -298,7 +500,8 @@ void clang_loadDeclaration(CXDecl Dcl,  {    assert(Dcl && "Passed null CXDecl"); -  CDeclVisitor DVisit(Dcl, callback, CData); +  CDeclVisitor DVisit(Dcl, callback, CData, +                      static_cast<Decl *>(Dcl)->getPCHLevel());    DVisit.Visit(static_cast<Decl *>(Dcl));  } @@ -349,7 +552,7 @@ const char *clang_getDeclSpelling(CXDecl AnonDecl)      return OMD->getSelector().getAsString().c_str();    }        if (ND->getIdentifier()) -    return ND->getIdentifier()->getName(); +    return ND->getIdentifier()->getNameStart();    else       return "";  } @@ -385,43 +588,38 @@ const char *clang_getCursorSpelling(CXCursor C)    if (clang_isReference(C.kind)) {      switch (C.kind) { -      case CXCursor_ObjCSuperClassRef:  -        { +      case CXCursor_ObjCSuperClassRef: {          ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);          assert(OID && "clang_getCursorLine(): Missing interface decl"); -        return OID->getSuperClass()->getIdentifier()->getName(); -        } -      case CXCursor_ObjCClassRef:  -        { +        return OID->getSuperClass()->getIdentifier()->getNameStart(); +      } +      case CXCursor_ObjCClassRef: {          if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND)) { -          return OID->getIdentifier()->getName(); +          return OID->getIdentifier()->getNameStart();          }          ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);          assert(OID && "clang_getCursorLine(): Missing category decl"); -        return OID->getClassInterface()->getIdentifier()->getName(); -        } -      case CXCursor_ObjCProtocolRef:  -        { +        return OID->getClassInterface()->getIdentifier()->getNameStart(); +      } +      case CXCursor_ObjCProtocolRef: {          ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);          assert(OID && "clang_getCursorLine(): Missing protocol decl"); -        return OID->getIdentifier()->getName(); -        } -      case CXCursor_ObjCSelectorRef: -        { +        return OID->getIdentifier()->getNameStart(); +      } +      case CXCursor_ObjCSelectorRef: {          ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(                                   static_cast<Stmt *>(C.stmt));          assert(OME && "clang_getCursorLine(): Missing message expr");          return OME->getSelector().getAsString().c_str(); -        } +      }        case CXCursor_VarRef:        case CXCursor_FunctionRef: -      case CXCursor_EnumConstantRef: -        { +      case CXCursor_EnumConstantRef: {          DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(                                   static_cast<Stmt *>(C.stmt));          assert(DRE && "clang_getCursorLine(): Missing decl ref expr"); -        return DRE->getDecl()->getIdentifier()->getName(); -        } +        return DRE->getDecl()->getIdentifier()->getNameStart(); +      }        default:          return "<not implemented>";      } @@ -497,12 +695,26 @@ static enum CXCursorKind TranslateKind(Decl *D) {  //  // CXCursor Operations.  // +void clang_initCXLookupHint(CXLookupHint *hint) { +  memset(hint, 0, sizeof(*hint)); +} +  CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name,  -                         unsigned line, unsigned column) +                         unsigned line, unsigned column) { +  return clang_getCursorWithHint(CTUnit, source_name, line, column, NULL); +} +   +CXCursor clang_getCursorWithHint(CXTranslationUnit CTUnit, +                                 const char *source_name,  +                                 unsigned line, unsigned column,  +                                 CXLookupHint *hint)  {    assert(CTUnit && "Passed null CXTranslationUnit");    ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit); +  // FIXME: Make this better. +  CXDecl RelativeToDecl = hint ? hint->decl : NULL; +      FileManager &FMgr = CXXUnit->getFileManager();    const FileEntry *File = FMgr.getFile(source_name,                                          source_name+strlen(source_name));   @@ -513,7 +725,8 @@ CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name,    SourceLocation SLoc =       CXXUnit->getSourceManager().getLocation(File, line, column); -  ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc); +  ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc, +                                      static_cast<NamedDecl *>(RelativeToDecl));    Decl *Dcl = ALoc.getParentDecl();    if (ALoc.isNamedRef()) @@ -623,8 +836,7 @@ static SourceLocation getLocationFromCursor(CXCursor C,                                              NamedDecl *ND) {    if (clang_isReference(C.kind)) {      switch (C.kind) { -      case CXCursor_ObjCClassRef:  -        { +      case CXCursor_ObjCClassRef: {          if (isa<ObjCInterfaceDecl>(ND)) {            // FIXME: This is a hack (storing the parent decl in the stmt slot).            NamedDecl *parentDecl = static_cast<NamedDecl *>(C.stmt); @@ -633,56 +845,49 @@ static SourceLocation getLocationFromCursor(CXCursor C,          ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);          assert(OID && "clang_getCursorLine(): Missing category decl");          return OID->getClassInterface()->getLocation(); -        } -      case CXCursor_ObjCSuperClassRef:  -        { +      } +      case CXCursor_ObjCSuperClassRef: {          ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);          assert(OID && "clang_getCursorLine(): Missing interface decl");          return OID->getSuperClassLoc(); -        } -      case CXCursor_ObjCProtocolRef:  -        { +      } +      case CXCursor_ObjCProtocolRef: {          ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);          assert(OID && "clang_getCursorLine(): Missing protocol decl");          return OID->getLocation(); -        } -      case CXCursor_ObjCSelectorRef: -        { +      } +      case CXCursor_ObjCSelectorRef: {          ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(                                   static_cast<Stmt *>(C.stmt));          assert(OME && "clang_getCursorLine(): Missing message expr");          return OME->getLeftLoc(); /* FIXME: should be a range */ -        } +      }        case CXCursor_VarRef:        case CXCursor_FunctionRef: -      case CXCursor_EnumConstantRef: -        { +      case CXCursor_EnumConstantRef: {          DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(                                   static_cast<Stmt *>(C.stmt));          assert(DRE && "clang_getCursorLine(): Missing decl ref expr");          return DRE->getLocation(); -        } +      }        default:          return SourceLocation();      }    } else { // We have a declaration or a definition.      SourceLocation SLoc;      switch (ND->getKind()) { -      case Decl::ObjCInterface:  -        { +      case Decl::ObjCInterface: {          SLoc = dyn_cast<ObjCInterfaceDecl>(ND)->getClassLoc();          break; -        } -      case Decl::ObjCProtocol:  -        { +      } +      case Decl::ObjCProtocol: {          SLoc = ND->getLocation(); /* FIXME: need to get the name location. */          break; -        } -      default:  -        { +      } +      default: {          SLoc = ND->getLocation();          break; -        } +      }      }      if (SLoc.isInvalid())        return SourceLocation(); @@ -716,7 +921,18 @@ const char *clang_getCursorSource(CXCursor C)    SourceManager &SourceMgr = ND->getASTContext().getSourceManager();    SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND); -  return SourceMgr.getBufferName(SLoc); +  if (SLoc.isFileID()) +    return SourceMgr.getBufferName(SLoc); + +  // Retrieve the file in which the macro was instantiated, then provide that +  // buffer name. +  // FIXME: Do we want to give specific macro-instantiation information? +  const llvm::MemoryBuffer *Buffer  +    = SourceMgr.getBuffer(SourceMgr.getDecomposedSpellingLoc(SLoc).first); +  if (!Buffer) +    return 0; + +  return Buffer->getBufferIdentifier();  }  void clang_getDefinitionSpellingAndExtent(CXCursor C,  diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports index c1ca0c773519..e9d44a0dc918 100644 --- a/tools/CIndex/CIndex.exports +++ b/tools/CIndex/CIndex.exports @@ -7,6 +7,7 @@ _clang_getCursorFromDecl  _clang_getCursorKind  _clang_getCursorLine  _clang_getCursorSource +_clang_getCursorWithHint  _clang_getDeclarationName  _clang_getDeclSpelling  _clang_getDeclLine @@ -18,7 +19,9 @@ _clang_getURI  _clang_loadDeclaration  _clang_loadTranslationUnit  _clang_createTranslationUnit +_clang_createTranslationUnitFromSourceFile  _clang_disposeTranslationUnit +_clang_initCXLookupHint  _clang_isDeclaration  _clang_isReference  _clang_isDefinition diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt index 71bbde546a6e..ee77c0398f72 100644 --- a/tools/CIndex/CMakeLists.txt +++ b/tools/CIndex/CMakeLists.txt @@ -22,6 +22,13 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")      )  endif() +if(MSVC) +  # windows.h doesn't compile with /Za +  get_target_property(NON_ANSI_COMPILE_FLAGS CIndex COMPILE_FLAGS) +  string(REPLACE /Za "" NON_ANSI_COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS}) +  set_target_properties(CIndex PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS}) +endif(MSVC) +  set_target_properties(CIndex    PROPERTIES    LINKER_LANGUAGE CXX) diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index c514b63d94be..cf2a706891e3 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -53,17 +53,23 @@ static void TranslationUnitVisitor(CXTranslationUnit Unit, CXCursor Cursor,          unsigned curLine = startLine, curColumn = startColumn;          CXCursor Ref; -        while (startBuf <= endBuf) { +        while (startBuf < endBuf) { +          CXLookupHint hint;            if (*startBuf == '\n') {              startBuf++;              curLine++;              curColumn = 1;            } else if (*startBuf != '\t')              curColumn++; +           +          clang_initCXLookupHint(&hint); +          hint.decl = Cursor.decl; -          Ref = clang_getCursor(Unit, clang_getCursorSource(Cursor), -                                curLine, curColumn); -          if (Ref.kind != CXCursor_FunctionDecl) { +          Ref = clang_getCursorWithHint(Unit, clang_getCursorSource(Cursor), +                                        curLine, curColumn, &hint); +          if (Ref.kind == CXCursor_NoDeclFound) { +            /* Nothing found here; that's fine. */ +          } else if (Ref.kind != CXCursor_FunctionDecl) {              printf("// CHECK: %s:%d:%d: ", basename(clang_getCursorSource(Ref)),                                               curLine, curColumn);              PrintCursor(Ref); @@ -85,12 +91,23 @@ int main(int argc, char **argv) {      return 0;    }    { -  CXIndex Idx = clang_createIndex(); -  CXTranslationUnit TU = clang_createTranslationUnit(Idx, argv[1]); +  CXIndex Idx; +  CXTranslationUnit TU;    enum CXCursorKind K = CXCursor_NotImplemented; +   +  Idx = clang_createIndex(/* excludeDeclsFromPCH */ !strcmp(argv[2], "local") ? 1 : 0,  +                          /* displayDiagnostics */ 1); +   +  TU = clang_createTranslationUnit(Idx, argv[1]); -  if (!strcmp(argv[2], "all")) { +  if (!TU) { +    fprintf(stderr, "Unable to load translation unit!\n"); +    return 1; +  } + +  if (!strcmp(argv[2], "all") || !strcmp(argv[2], "local")) {      clang_loadTranslationUnit(TU, TranslationUnitVisitor, 0); +    clang_disposeTranslationUnit(TU);      return 1;    }    /* Perform some simple filtering. */ @@ -101,6 +118,7 @@ int main(int argc, char **argv) {    else if (!strcmp(argv[2], "typedef")) K = CXCursor_TypedefDecl;    clang_loadTranslationUnit(TU, TranslationUnitVisitor, &K); +  clang_disposeTranslationUnit(TU);    return 1;    }  } diff --git a/tools/clang-cc/clang-cc.cpp b/tools/clang-cc/clang-cc.cpp index 0ad7efbc4839..f77767c150e9 100644 --- a/tools/clang-cc/clang-cc.cpp +++ b/tools/clang-cc/clang-cc.cpp @@ -1139,9 +1139,6 @@ isysroot("isysroot", llvm::cl::value_desc("dir"), llvm::cl::init("/"),  // Add the clang headers, which are relative to the clang binary.  void AddClangIncludePaths(const char *Argv0, InitHeaderSearch *Init) { -  if (nostdclanginc) -    return; -    llvm::sys::Path MainExecutablePath =       llvm::sys::Path::GetMainExecutable(Argv0,                                      (void*)(intptr_t)AddClangIncludePaths); @@ -1243,7 +1240,8 @@ void InitializeIncludePaths(const char *Argv0, HeaderSearch &Headers,    Init.AddDefaultEnvVarPaths(Lang); -  AddClangIncludePaths(Argv0, &Init); +  if (!nostdclanginc) +    AddClangIncludePaths(Argv0, &Init);    if (!nostdinc)      Init.AddDefaultSystemIncludePaths(Lang, triple); @@ -2190,8 +2188,7 @@ static void ProcessASTInputFile(const std::string &InFile, ProgActions PA,                                  Diagnostic &Diags, FileManager &FileMgr,                                  llvm::LLVMContext& Context) {    std::string Error; -  llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, Diags, FileMgr, -                                                        &Error)); +  llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, &Error));    if (!AST) {      Diags.Report(FullSourceLoc(), diag::err_fe_invalid_ast_file) << Error;      return; diff --git a/tools/index-test/index-test.cpp b/tools/index-test/index-test.cpp index 103874c77d7d..fce48edf26e0 100644 --- a/tools/index-test/index-test.cpp +++ b/tools/index-test/index-test.cpp @@ -225,8 +225,7 @@ int main(int argc, char **argv) {      std::string ErrMsg;      llvm::OwningPtr<ASTUnit> AST; -    AST.reset(ASTUnit::LoadFromPCHFile(InFile, Idxer.getDiagnostics(), -                                       Idxer.getFileManager(), &ErrMsg)); +    AST.reset(ASTUnit::LoadFromPCHFile(InFile, &ErrMsg));      if (!AST) {        llvm::errs() << "[" << InFile << "] Error: " << ErrMsg << '\n';        return 1; @@ -244,7 +243,7 @@ int main(int argc, char **argv) {    if (!PointAtLocation.empty()) {      const std::string &Filename = PointAtLocation[0].FileName; -    const FileEntry *File = Idxer.getFileManager().getFile(Filename); +    const FileEntry *File = FirstAST->getFileManager().getFile(Filename);      if (File == 0) {        llvm::errs() << "File '" << Filename << "' does not exist\n";        return 1; @@ -253,7 +252,7 @@ int main(int argc, char **argv) {      // Safety check. Using an out-of-date AST file will only lead to crashes      // or incorrect results.      // FIXME: Check all the source files that make up the AST file. -    const FileEntry *ASTFile = Idxer.getFileManager().getFile(FirstFile); +    const FileEntry *ASTFile = FirstAST->getFileManager().getFile(FirstFile);      if (File->getModificationTime() > ASTFile->getModificationTime()) {        llvm::errs() << "[" << FirstFile << "] Error: " <<          "Pointing at a source file which was modified after creating " diff --git a/www/OpenProjects.html b/www/OpenProjects.html index cdf31218bbeb..46d9716c7856 100644 --- a/www/OpenProjects.html +++ b/www/OpenProjects.html @@ -97,6 +97,18 @@ supported.</li>  that demonstrates the problem down to something small.  There are many ways to  do this; ask on cfe-dev for advice.</p> +<li><b>StringRef'ize APIs</b>: A thankless but incredibly useful project is +StringRef'izing (converting to use <tt>llvm::StringRef</tt> instead of <tt>const +char *</tt> or <tt>std::string</tt>) various clang interfaces. This generally +simplifies the code and makes it more efficient.</li> + +<li><b>Universal Driver</b>: Clang is inherently a cross compiler. We would like +to define a new model for cross compilation which provides a great user +experience -- it should be easy to cross compile applications, install support +for new architectures, access different compilers and tools, and be consistent +across different platforms. See the <a href="UniversalDriver.html">Universal +Driver</a> web page for more information.</li> +  </div>  </body>  </html> diff --git a/www/UniversalDriver.html b/www/UniversalDriver.html new file mode 100644 index 000000000000..f66151a49345 --- /dev/null +++ b/www/UniversalDriver.html @@ -0,0 +1,84 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" +          "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> +  <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" /> +  <title>Clang - Universal Driver</title> +  <link type="text/css" rel="stylesheet" href="menu.css" /> +  <link type="text/css" rel="stylesheet" href="content.css" /> +</head> +<body> + +<!--#include virtual="menu.html.incl"--> + +<div id="content"> + +<h1>The Clang Universal Driver Project</h1> + +<p>Clang is inherently a cross compiler, in that it is always capable of +building code for targets which are a different architecture or even operating +system from the one running the compiler. However, actually cross compiling in +practice involves much more than just generating the right assembly code for a +target, it also requires having an appropriate tool chain (assemblers, linkers), +access to header files and libraries for the target, and many other details (for +example, the calling convention or whether software floating point is in +use). Traditionally, compilers and development environments provide little +assistance with this process, so users do not have easy access to the powerful +underlying cross-compilation abilities of clang.</p> + +<p>We would like to solve this problem by defining a new model for how cross +compilation is done, based on the idea of a <i>universal driver</i>. The key +point of this model is that the user would always access the compiler through a +single entry point (e.g., <tt>/usr/bin/cc</tt>) and provide an argument +specifying the <i>configuration</i> they would like to target. Under the hood +this entry point (the universal driver) would have access to all the information +that the driver, compiler, and other tools need to build applications for that +target.</p> + +<p>This is a large and open-ended project. It's eventual success depends not +just on implementing the model, but also on getting buy-in from compiler +developers, operating system distribution vendors and the development community +at large. Our plan is to begin by defining a clear list of the problems we want +to solve and a proposed implementation (from the user perspective).</p> + +<p>This project is in the very early (i.e., thought experiment) stages of +development. Stay tuned for more information, and of course, patches +welcome!</p> + +<p>See also <a href="http://llvm.org/PR4127">PR4127</a>.</p> + +<h2>Existing Solutions and Related Work</h2> + +<ul> +  <li>gcc's command line arguments <tt>-V</tt>, <tt>-B</tt>, <tt>-b</tt> are +    generic but limited solutions to related problems. Similarly, <tt>-m32</tt> +    and <tt>-m64</tt> solve a small subset of the problem for specific +    architectures.</li> + +  <li>gcc's <a href="http://www.airs.com/ian/configure/configure_8.html">multilibs</a> +    solve the part of the problem that relates to finding appropriate libraries +    and include files based on particular feature support (soft float, +    etc.).</li> + +  <li>Apple's "driver driver" supported by gcc and clang solve a subset of the +    problem by supporting <tt>-arch</tt>. Apple also provides a tool chain which +    supports <a href="http://en.wikipedia.org/wiki/Universal_binary">universal +    binaries</a> and object files which may include data for multiple +    architectures. See <a href="http://developer.apple.com/mac/library/technotes/tn2005/tn2137.html">TN2137</a> +    for an example of how this is used.</li> + +  <li>Many operating systems and environments solve the problem by installing +    complete development environments (including the IDE, tools, header files, +    and libraries) for a single tool chain. This is cumbersome for users and +    does not match well with tools which are inherently capable of cross +    compiling.</li> + +  <li>The Debian <a href="http://wiki.debian.org/ArmEabiPort">ArmEabiPort</a> +    wiki page for their work to support the ARM EABI provide an interesting +    glimpse into how related issues impact the operating system distribution.</li> + +</ul> + +</div> +</body> +</html> diff --git a/www/analyzer/latest_checker.html.incl b/www/analyzer/latest_checker.html.incl index fa287b1ef4e2..4184ce6d4010 100644 --- a/www/analyzer/latest_checker.html.incl +++ b/www/analyzer/latest_checker.html.incl @@ -1 +1 @@ -<b><a href="http://checker.minormatter.com/checker-224.tar.bz2">checker-224.tar.bz2</a></b> (built October 6, 2009) +<b><a href="http://checker.minormatter.com/checker-225.tar.bz2">checker-225.tar.bz2</a></b> (built October 21, 2009) diff --git a/www/comparison.html b/www/comparison.html index f0d00bb497be..2462b89da283 100644 --- a/www/comparison.html +++ b/www/comparison.html @@ -179,7 +179,8 @@      <ul>      <li>PCC dates from the 1970's and has been dormant for most of that time.          The clang + llvm communities are very active.</li> -    <li>PCC doesn't support Objective-C or C++ and doesn't aim to</li> +    <li>PCC doesn't support Objective-C or C++ and doesn't aim to support +        C++.</li>      <li>PCC's code generation is very limited compared to LLVM.  It produces very          inefficient code and does not support many important targets.</li>      <li>Like Elsa, PCC's does not have an integrated preprocessor, making it diff --git a/www/cxx_status.html b/www/cxx_status.html index 2c1b79eae6a9..ecfc8a88dd73 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -24,7 +24,7 @@  <!--*************************************************************************-->  <h1>C++ Support in Clang</h1>  <!--*************************************************************************--> -<p>Last updated: $Date: 2009-10-13 21:41:44 +0200 (Tue, 13 Oct 2009) $</p> +<p>Last updated: $Date: 2009-10-20 23:10:15 +0200 (Tue, 20 Oct 2009) $</p>  <p>  This page tracks the status of C++ support in Clang.<br> @@ -1659,9 +1659,8 @@ welcome!</p>    <td>    13.3.3 [over.match.best]</td>    <td class="na" align="center">N/A</td>      <td class="advanced" align="center"></td> -  <td class="medium" align="center"></td> +  <td class="advanced" align="center"></td>    <td class="na" align="center">N/A</td>   -  <td>Missing support for member pointers</td>  </tr>  <tr>    <td>      13.3.3.1 [over.best.ics]</td> @@ -1789,8 +1788,7 @@ welcome!</p>    <td class="advanced" align="center"></td>    <td class="medium" align="center"></td>    <td class="na" align="center">N/A</td>   -  <td>Missing support for the ->* operator (p11, p16) and support for -  the ternary operator (p24, p25).</td> +  <td>Missing support for the ternary operator (p24, p25).</td>  </tr>  <tr>    <td>14 [temp]</td>  | 
