summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/ASTContext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ASTContext.cpp')
-rw-r--r--clang/lib/AST/ASTContext.cpp141
1 files changed, 87 insertions, 54 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 292f2ac95d0..7f5fa35842a 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<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
OpenPOWER on IntegriCloud