aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/ASTContext.h13
-rw-r--r--include/clang/AST/Type.h110
-rw-r--r--include/clang/AST/TypeLoc.h181
-rw-r--r--include/clang/AST/TypeNodes.def2
-rw-r--r--include/clang/Frontend/PCHBitCodes.h8
-rw-r--r--lib/AST/ASTContext.cpp141
-rw-r--r--lib/AST/Type.cpp39
-rw-r--r--lib/CodeGen/Mangle.cpp7
-rw-r--r--lib/Frontend/PCHReader.cpp23
-rw-r--r--lib/Frontend/PCHWriter.cpp23
-rw-r--r--lib/Index/ResolveLocation.cpp45
-rw-r--r--lib/Sema/Sema.h18
-rw-r--r--lib/Sema/SemaDeclCXX.cpp3
-rw-r--r--lib/Sema/SemaType.cpp205
-rw-r--r--lib/Sema/TreeTransform.h50
-rw-r--r--test/SemaCXX/overloaded-operator.cpp2
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);
}