From fc93cf97778ba12d624cb7e88159e2c1dbfc80e2 Mon Sep 17 00:00:00 2001 From: John McCall Date: Thu, 22 Oct 2009 22:37:11 +0000 Subject: [PATCH] When building types from declarators, instead of building two types (one for the DeclaratorInfo, one for semantic analysis), just build a single type whose canonical type will reflect the semantic analysis (assuming the type is well-formed, of course). To make that work, make a few changes to the type system: * allow the nominal pointee type of a reference type to be a (possibly sugared) reference type. Also, preserve the original spelling of the reference type. Both of these can be ignored on canonical reference types. * Remove ObjCProtocolListType and preserve the associated source information on the various ObjC TypeLocs. Preserve the spelling of protocol lists except in the canonical form. * Preserve some level of source type structure on parameter types, but canonicalize on the canonical function type. This is still a WIP. Drops code size, makes strides towards accurate source location representation, slight (~1.7%) progression on Cocoa.h because of complexity drop. llvm-svn: 84907 --- clang/include/clang/AST/ASTContext.h | 13 +- clang/include/clang/AST/Type.h | 110 ++++++----- clang/include/clang/AST/TypeLoc.h | 183 +++++++++++++----- clang/include/clang/AST/TypeNodes.def | 2 - clang/include/clang/Frontend/PCHBitCodes.h | 8 +- clang/lib/AST/ASTContext.cpp | 141 ++++++++------ clang/lib/AST/Type.cpp | 39 +--- clang/lib/CodeGen/Mangle.cpp | 7 +- clang/lib/Frontend/PCHReader.cpp | 25 +-- clang/lib/Frontend/PCHWriter.cpp | 25 +-- clang/lib/Index/ResolveLocation.cpp | 45 ++++- clang/lib/Sema/Sema.h | 18 +- clang/lib/Sema/SemaDeclCXX.cpp | 3 +- clang/lib/Sema/SemaType.cpp | 209 +++++++++------------ clang/lib/Sema/TreeTransform.h | 50 +---- clang/test/SemaCXX/overloaded-operator.cpp | 2 +- 16 files changed, 446 insertions(+), 434 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index c3ac2ea82d08..30896c91a143 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -87,7 +87,6 @@ class ASTContext { llvm::FoldingSet TypenameTypes; llvm::FoldingSet ObjCInterfaceTypes; llvm::FoldingSet ObjCObjectPointerTypes; - llvm::FoldingSet ObjCProtocolListTypes; llvm::FoldingSet ElaboratedTypes; llvm::FoldingSet 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/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 686d86c4bb5e..db02a68a984d 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/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(); + 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 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 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 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::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(T) && !isa(T); +} + inline void QualType::removeConst() { removeFastQualifiers(Qualifiers::Const); } diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index b980f2bd0ff8..1d7181b531f8 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -375,48 +375,52 @@ class SubstTemplateTypeParmTypeLoc : SubstTemplateTypeParmType> { }; -/// \brief Wrapper for source info for ObjC interfaces. -class ObjCInterfaceTypeLoc : public TypeSpecTypeLoc { -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 { +// A helper class for defining ObjC TypeLocs that can qualified with +// protocols. +// +// TypeClass basically has to be either ObjCInterfaceType or +// ObjCObjectPointerType. +template +class ObjCProtocolListTypeLoc : public ConcreteTypeLoc { // 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,34 +434,123 @@ 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); } - - QualType getInnerType() const { return getTypePtr()->getBaseType(); } }; +struct ObjCInterfaceLocInfo : ObjCProtocolListLocInfo { + SourceLocation NameLoc; +}; + +/// \brief Wrapper for source info for ObjC interfaces. +class ObjCInterfaceTypeLoc : + public ObjCProtocolListTypeLoc { +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); + } +}; + + +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 { +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 { SourceLocation StarLoc; @@ -534,6 +627,10 @@ public: class ReferenceTypeLoc : public PointerLikeTypeLoc { +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 { -public: - SourceLocation getStarLoc() const { - return getSigilLoc(); - } - void setStarLoc(SourceLocation Loc) { - setSigilLoc(Loc); - } -}; - struct FunctionLocInfo { SourceLocation LParenLoc, RParenLoc; diff --git a/clang/include/clang/AST/TypeNodes.def b/clang/include/clang/AST/TypeNodes.def index 2615f14e8d04..c2721236af02 100644 --- a/clang/include/clang/AST/TypeNodes.def +++ b/clang/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/clang/include/clang/Frontend/PCHBitCodes.h b/clang/include/clang/Frontend/PCHBitCodes.h index d83a020ecf17..1e953d671226 100644 --- a/clang/include/clang/Frontend/PCHBitCodes.h +++ b/clang/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/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 292f2ac95d04..7f5fa35842af 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/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(); + // 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(); + // 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 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 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,34 +1994,29 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); - // No Match; + // Sort the protocol list alphabetically to canonicalize it. + QualType Canonical; + if (NumProtocols && !areSortedAndUniqued(Protocols, NumProtocols)) { + llvm::SmallVector Sorted(NumProtocols); + std::copy(Protocols, Protocols + NumProtocols, Sorted.begin()); + + unsigned UniqueCount = NumProtocols; + SortAndUniqueProtocols(&Sorted[0], UniqueCount); + + Canonical = getObjCInterfaceType(Decl, &Sorted[0], UniqueCount); + + ObjCInterfaceTypes.FindNodeOrInsertPos(ID, InsertPos); + } + ObjCInterfaceType *QType = new (*this, TypeAlignment) - ObjCInterfaceType(const_cast(Decl), + ObjCInterfaceType(Canonical, const_cast(Decl), Protocols, NumProtocols); + Types.push_back(QType); ObjCInterfaceTypes.InsertNode(QType, InsertPos); return QualType(QType, 0); } -QualType ASTContext::getObjCProtocolListType(QualType T, - ObjCProtocolDecl **Protocols, - unsigned NumProtocols) { - llvm::FoldingSetNodeID ID; - ObjCProtocolListType::Profile(ID, T, Protocols, NumProtocols); - - void *InsertPos = 0; - if (ObjCProtocolListType *QT = - ObjCProtocolListTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(QT, 0); - - // No Match; - ObjCProtocolListType *QType = new (*this, TypeAlignment) - ObjCProtocolListType(T, Protocols, NumProtocols); - Types.push_back(QType); - ObjCProtocolListTypes.InsertNode(QType, InsertPos); - return QualType(QType, 0); -} - /// getTypeOfExprType - Unlike many "get" functions, we can't unique /// TypeOfExprType AST's (since expression's are never shared). For example, /// multiple declarations that refer to "typeof(x)" all contain different @@ -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(Ty)) { + Result = getArrayDecayedType(QualType(Ty,0)); + } else if (isa(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/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index daa2bc04f1c9..5fb0178834ff 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/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(getPointeeType())) + if (isa(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(getPointeeType())) + if (isa(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/clang/lib/CodeGen/Mangle.cpp b/clang/lib/CodeGen/Mangle.cpp index 155f87a41d39..2e6034bbcd97 100644 --- a/clang/lib/CodeGen/Mangle.cpp +++ b/clang/lib/CodeGen/Mangle.cpp @@ -248,7 +248,12 @@ void CXXNameMangler::mangleFunctionEncoding(const FunctionDecl *FD) { FD = PrimaryTemplate->getTemplatedDecl(); } - mangleBareFunctionType(FD->getType()->getAs(), MangleReturnType); + // Do the canonicalization out here because parameter types can + // undergo additional canonicalization (e.g. array decay). + FunctionType *FT = cast(Context.getASTContext() + .getCanonicalType(FD->getType())); + + mangleBareFunctionType(FT, MangleReturnType); } static bool isStdNamespace(const DeclContext *DC) { diff --git a/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp index c02959f2cc79..7dc60f8e9944 100644 --- a/clang/lib/Frontend/PCHReader.cpp +++ b/clang/lib/Frontend/PCHReader.cpp @@ -1964,16 +1964,6 @@ QualType PCHReader::ReadTypeRecord(uint64_t Offset) { return Context->getObjCObjectPointerType(OIT, Protos.data(), NumProtos); } - case pch::TYPE_OBJC_PROTOCOL_LIST: { - unsigned Idx = 0; - QualType OIT = GetType(Record[Idx++]); - unsigned NumProtos = Record[Idx++]; - llvm::SmallVector Protos; - for (unsigned I = 0; I != NumProtos; ++I) - Protos.push_back(cast(GetDecl(Record[Idx++]))); - return Context->getObjCProtocolListType(OIT, Protos.data(), NumProtos); - } - case pch::TYPE_SUBST_TEMPLATE_TYPE_PARM: { unsigned Idx = 0; QualType Parm = GetType(Record[Idx++]); @@ -2124,16 +2114,21 @@ void TypeLocReader::VisitTypenameTypeLoc(TypenameTypeLoc TL) { } void TypeLocReader::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - TL.setStarLoc(SourceLocation::getFromRawEncoding(Record[Idx++])); -} -void TypeLocReader::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) { 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) { diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index c98080a38b7d..fb48df332121 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -248,15 +248,6 @@ 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 { @@ -387,16 +378,21 @@ void TypeLocWriter::VisitTypenameTypeLoc(TypenameTypeLoc TL) { } void TypeLocWriter::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { Writer.AddSourceLocation(TL.getNameLoc(), Record); -} -void TypeLocWriter::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) { - Writer.AddSourceLocation(TL.getStarLoc(), Record); -} -void TypeLocWriter::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) { 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); +} //===----------------------------------------------------------------------===// // PCHWriter Implementation @@ -569,7 +565,6 @@ void PCHWriter::WriteBlockInfoBlock() { RECORD(TYPE_ENUM); RECORD(TYPE_OBJC_INTERFACE); RECORD(TYPE_OBJC_OBJECT_POINTER); - RECORD(TYPE_OBJC_PROTOCOL_LIST); RECORD(DECL_ATTR); RECORD(DECL_TRANSLATION_UNIT); RECORD(DECL_TYPEDEF); diff --git a/clang/lib/Index/ResolveLocation.cpp b/clang/lib/Index/ResolveLocation.cpp index d3ba8192b22e..8edd634f8af4 100644 --- a/clang/lib/Index/ResolveLocation.cpp +++ b/clang/lib/Index/ResolveLocation.cpp @@ -120,11 +120,12 @@ public: TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd) : LocResolverBase(ctx, loc), ParentDecl(pd) { } + ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL); ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL); ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL); ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL); ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL); - ASTLocation VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL); + ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL); ASTLocation VisitTypeLoc(TypeLoc TL); }; @@ -349,6 +350,24 @@ ASTLocation DeclLocResolver::VisitDecl(Decl *D) { return ASTLocation(D); } +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()->getDecl(); + return ASTLocation(ParentDecl, D, TL.getNameLoc()); + } + + // Same thing with 'Class'. + if (T->getKind() == BuiltinType::ObjCClass) { + TypedefDecl *D = Ctx.getObjCClassType()->getAs()->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"); @@ -389,12 +408,6 @@ ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc 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::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc 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::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLo 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"); diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 074a6fcb62ef..6dd081bdc25e 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/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); @@ -3755,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/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e083c074319e..6d1f4ea4a865 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -4281,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/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 219ac3e58276..49f7119c8b06 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -52,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: @@ -106,9 +104,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, case DeclSpec::TST_unspecified: // "" 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()); @@ -226,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()) { // It would be nice if protocol qualifiers were only stored with the @@ -385,8 +377,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS, Result = Context.getQualifiedType(Result, Quals); } - if (SourceTy.isNull()) - SourceTy = Result; return Result; } @@ -450,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()) { - // 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(); + + // 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" @@ -511,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); } @@ -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 ArgTys; - - for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { - ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs(); - 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 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,8 +1220,12 @@ 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; } @@ -1314,17 +1245,49 @@ namespace { } void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) { TL.setNameLoc(DS.getTypeSpecTypeLoc()); - } - void VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) { - assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers()); - TL.setLAngleLoc(DS.getProtocolLAngleLoc()); - TL.setRAngleLoc(DS.getSourceRange().getEnd()); - for (unsigned i = 0; i != DS.getNumProtocolQualifiers(); ++i) - TL.setProtocolLoc(i, DS.getProtocolLocs()[i]); - TypeLoc BaseLoc = TL.getBaseTypeLoc(); - if (BaseLoc) + 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()); + + TL.setStarLoc(SourceLocation()); + + 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]); + + } else { + assert(TL.getNumProtocols() == 0); + TL.setHasProtocolsAsWritten(false); + TL.setLAngleLoc(SourceLocation()); + TL.setRAngleLoc(SourceLocation()); + } + + // 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. @@ -1353,6 +1316,10 @@ namespace { 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()); } void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::MemberPointer); @@ -1361,7 +1328,8 @@ namespace { } void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) { assert(Chunk.Kind == DeclaratorChunk::Reference); - assert(Chunk.Ref.LValueRef); + // 'Amp' is misleading: this might have been originally + /// spelled with AmpAmp. TL.setAmpLoc(Chunk.Loc); } void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) { @@ -1381,12 +1349,9 @@ namespace { TL.setRParenLoc(Chunk.EndLoc); const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun; - for (unsigned i = 0, e = FTI.NumArgs, tpi = 0; i != e; ++i) { + for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) { ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs(); - if (Param) { - assert(tpi < TL.getNumArgs()); - TL.setArg(tpi++, Param); - } + TL.setArg(tpi++, Param); } // FIXME: exception specs } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 5f06ce5e35dc..38273dcbebad 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -514,14 +514,6 @@ public: SourceRange(getDerived().getBaseLocation())); } - /// \brief Rebuild an objective C protocol list type. - QualType RebuildObjCProtocolListType(QualType BaseType, - ObjCProtocolDecl **Protocols, - unsigned NumProtocols) { - return SemaRef.Context.getObjCProtocolListType(BaseType, Protocols, - NumProtocols); - } - /// \brief Build a new nested-name-specifier given the prefix and an /// identifier that names the next step in the nested-name-specifier. /// @@ -2808,50 +2800,16 @@ template QualType TreeTransform::TransformObjCInterfaceType(TypeLocBuilder &TLB, ObjCInterfaceTypeLoc TL) { - return TransformTypeSpecType(TLB, TL); + assert(false && "TransformObjCInterfaceType unimplemented"); + return QualType(); } template QualType TreeTransform::TransformObjCObjectPointerType(TypeLocBuilder &TLB, ObjCObjectPointerTypeLoc TL) { - TransformPointerLikeType(ObjCObjectPointerType); -} - -template -QualType TreeTransform::TransformObjCProtocolListType( - TypeLocBuilder &TLB, - ObjCProtocolListTypeLoc TL) { - ObjCProtocolListType *T = TL.getTypePtr(); - QualType BaseType = T->getBaseType(); - if (!BaseType.isNull()) { - BaseType = getDerived().TransformType(TLB, TL.getBaseTypeLoc()); - if (BaseType.isNull()) - return QualType(); - } - - QualType Result = TL.getType(); - if (getDerived().AlwaysRebuild() || - BaseType != T->getBaseType()) { - // TODO: transform these? - llvm::SmallVector Protocols(T->getNumProtocols()); - std::copy(T->qual_begin(), T->qual_end(), Protocols.begin()); - Result = getDerived().RebuildObjCProtocolListType(BaseType, - &Protocols[0], - T->getNumProtocols()); - if (Result.isNull()) - return QualType(); - } - - ObjCProtocolListTypeLoc NewTL = TLB.push(Result); - NewTL.setLAngleLoc(TL.getLAngleLoc()); - NewTL.setRAngleLoc(TL.getRAngleLoc()); - - assert(NewTL.getNumProtocols() == TL.getNumProtocols()); - for (unsigned i = 0, e = TL.getNumProtocols(); i != e; ++i) - NewTL.setProtocolLoc(i, TL.getProtocolLoc(i)); - - return Result; + assert(false && "TransformObjCObjectPointerType unimplemented"); + return QualType(); } //===----------------------------------------------------------------------===// diff --git a/clang/test/SemaCXX/overloaded-operator.cpp b/clang/test/SemaCXX/overloaded-operator.cpp index 8f71ad538138..10b0f5a76804 100644 --- a/clang/test/SemaCXX/overloaded-operator.cpp +++ b/clang/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()(); };