diff options
-rw-r--r-- | include/clang/AST/ASTContext.h | 13 | ||||
-rw-r--r-- | include/clang/AST/Type.h | 110 | ||||
-rw-r--r-- | include/clang/AST/TypeLoc.h | 181 | ||||
-rw-r--r-- | include/clang/AST/TypeNodes.def | 2 | ||||
-rw-r--r-- | include/clang/Frontend/PCHBitCodes.h | 8 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 141 | ||||
-rw-r--r-- | lib/AST/Type.cpp | 39 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 7 | ||||
-rw-r--r-- | lib/Frontend/PCHReader.cpp | 23 | ||||
-rw-r--r-- | lib/Frontend/PCHWriter.cpp | 23 | ||||
-rw-r--r-- | lib/Index/ResolveLocation.cpp | 45 | ||||
-rw-r--r-- | lib/Sema/Sema.h | 18 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 205 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 50 | ||||
-rw-r--r-- | test/SemaCXX/overloaded-operator.cpp | 2 |
16 files changed, 441 insertions, 429 deletions
diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index c3ac2ea82d..30896c91a1 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -87,7 +87,6 @@ class ASTContext { llvm::FoldingSet<TypenameType> TypenameTypes; llvm::FoldingSet<ObjCInterfaceType> ObjCInterfaceTypes; llvm::FoldingSet<ObjCObjectPointerType> ObjCObjectPointerTypes; - llvm::FoldingSet<ObjCProtocolListType> ObjCProtocolListTypes; llvm::FoldingSet<ElaboratedType> ElaboratedTypes; llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames; @@ -437,7 +436,7 @@ public: /// 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. @@ -547,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); @@ -847,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); diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 686d86c4bb..db02a68a98 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -444,6 +444,7 @@ public: } bool isCanonical() const; + bool isCanonicalAsParam() const; /// isNull - Return true if this QualType doesn't point to a type yet. bool isNull() const { @@ -1093,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) { @@ -1118,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, @@ -1139,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: @@ -2433,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: @@ -2481,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. @@ -2547,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; @@ -2633,6 +2624,13 @@ inline bool QualType::isCanonical() const { 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 b980f2bd0f..1d7181b531 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -375,48 +375,52 @@ class SubstTemplateTypeParmTypeLoc : SubstTemplateTypeParmType> { }; -/// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceTypeLoc : public TypeSpecTypeLoc<ObjCInterfaceTypeLoc, - ObjCInterfaceType> { -public: - ObjCInterfaceDecl *getIFaceDecl() const { - return getTypePtr()->getDecl(); - } -}; - struct ObjCProtocolListLocInfo { - SourceLocation LAngleLoc, RAngleLoc; + SourceLocation LAngleLoc; + SourceLocation RAngleLoc; }; -/// \brief Wrapper for source info for ObjC protocol lists. -class ObjCProtocolListTypeLoc - : public ConcreteTypeLoc<UnqualTypeLoc, - ObjCProtocolListTypeLoc, - 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 { @@ -430,33 +434,122 @@ 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()); } void initializeLocal(SourceLocation Loc) { - setLAngleLoc(Loc); - setRAngleLoc(Loc); - for (unsigned i = 0, e = getNumProtocols(); i != e; ++i) - setProtocolLoc(i, Loc); + initializeLocalBase(Loc); } - /// \brief Returns the size of the type source info data block that is - /// specific to this type. unsigned getExtraLocalDataSize() const { - return getNumProtocols() * sizeof(SourceLocation); + return this->getNumProtocols() * sizeof(SourceLocation); + } +}; + + +struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo { + SourceLocation NameLoc; +}; + +/// \brief Wrapper for source info for ObjC interfaces. +class ObjCInterfaceTypeLoc : + public ObjCProtocolListTypeLoc<ObjCInterfaceTypeLoc, + ObjCInterfaceType, + ObjCInterfaceLocInfo> { +public: + ObjCInterfaceDecl *getIFaceDecl() const { + return getTypePtr()->getDecl(); + } + + SourceLocation getNameLoc() const { + return getLocalData()->NameLoc; + } + + void setNameLoc(SourceLocation Loc) { + getLocalData()->NameLoc = Loc; + } + + SourceRange getSourceRange() const { + if (getNumProtocols()) + return SourceRange(getNameLoc(), getRAngleLoc()); + else + return SourceRange(getNameLoc(), getNameLoc()); + } + + void initializeLocal(SourceLocation Loc) { + initializeLocalBase(Loc); + setNameLoc(Loc); } +}; + - QualType getInnerType() const { return getTypePtr()->getBaseType(); } +struct ObjCObjectPointerLocInfo : ObjCProtocolListLocInfo { + SourceLocation StarLoc; + bool HasProtocols; + bool HasBaseType; }; +/// 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: + bool hasProtocolsAsWritten() const { + return getLocalData()->HasProtocols; + } + + void setHasProtocolsAsWritten(bool HasProtocols) { + getLocalData()->HasProtocols = HasProtocols; + } + + bool hasBaseTypeAsWritten() const { + return getLocalData()->HasBaseType; + } + + void setHasBaseTypeAsWritten(bool HasBaseType) { + getLocalData()->HasBaseType = HasBaseType; + } + + SourceLocation getStarLoc() const { + return getLocalData()->StarLoc; + } + + void setStarLoc(SourceLocation Loc) { + getLocalData()->StarLoc = Loc; + } + + SourceRange getSourceRange() const { + // 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(); + } + + QualType getInnerType() const { + return getTypePtr()->getPointeeType(); + } +}; struct PointerLikeLocInfo { @@ -534,6 +627,10 @@ public: class ReferenceTypeLoc : public PointerLikeTypeLoc<ReferenceTypeLoc, ReferenceType> { +public: + QualType getInnerType() const { + return getTypePtr()->getPointeeTypeAsWritten(); + } }; class LValueReferenceTypeLoc : @@ -562,20 +659,6 @@ public: } }; -/// Wraps an ObjCPointerType with source location information. Note -/// that not all ObjCPointerTypes actually have a star location. -class ObjCObjectPointerTypeLoc : - public PointerLikeTypeLoc<ObjCObjectPointerTypeLoc, - ObjCObjectPointerType> { -public: - SourceLocation getStarLoc() const { - return getSigilLoc(); - } - void setStarLoc(SourceLocation Loc) { - setSigilLoc(Loc); - } -}; - struct FunctionLocInfo { SourceLocation LParenLoc, RParenLoc; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 2615f14e8d..c2721236af 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -86,7 +86,6 @@ 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 @@ -94,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/Frontend/PCHBitCodes.h b/include/clang/Frontend/PCHBitCodes.h index d83a020ecf..1e953d6712 100644 --- a/include/clang/Frontend/PCHBitCodes.h +++ b/include/clang/Frontend/PCHBitCodes.h @@ -397,14 +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, + TYPE_DECLTYPE = 23, /// \brief An ElaboratedType record. - TYPE_ELABORATED = 25, + TYPE_ELABORATED = 24, /// \brief A SubstTemplateTypeParmType record. - TYPE_SUBST_TEMPLATE_TYPE_PARM = 26 + TYPE_SUBST_TEMPLATE_TYPE_PARM = 25 }; /// \brief The type IDs for special types constructed by semantic diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 292f2ac95d..7f5fa35842 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -555,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 @@ -1235,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 = @@ -1259,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); } @@ -1271,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 = @@ -1603,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; @@ -1622,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. @@ -1636,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, @@ -1920,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; @@ -1937,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); @@ -1949,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); @@ -1962,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); @@ -1974,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); } @@ -2155,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 diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index daa2bc04f1..5fb0178834 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -724,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: @@ -1059,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 { @@ -1070,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 { @@ -1463,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; diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 155f87a41d..2e6034bbcd 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); } |