aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-09-29 23:03:30 +0000
committerJohn McCall <rjmccall@apple.com>2009-09-29 23:03:30 +0000
commitbf1cc05907ceb2081e8158b26f3d3f48b31caad3 (patch)
treebca78feafa7d2dfa963070e2c2db681971722dd7
parent1070c9f7acc889336be6f80c70dc1b32622cc83d (diff)
Desugaring optimizations. Add single-step desugaring methods to all
concrete types. Use unqualified desugaring for getAs<> and sundry. Fix a few users to either not desugar or use qualified desugar, as seemed appropriate. Removed Type's qualified desugar method, as it was easy to accidentally use instead of QualType's. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83116 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Type.h149
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h4
-rw-r--r--lib/AST/Type.cpp111
-rw-r--r--lib/Analysis/RegionStore.cpp2
-rw-r--r--lib/Sema/Sema.cpp13
-rw-r--r--lib/Sema/SemaDeclCXX.cpp6
6 files changed, 206 insertions, 79 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index cef52175d1..89776b91fe 100644
--- a/include/clang/AST/Type.h
+++ b/include/clang/AST/Type.h
@@ -483,7 +483,9 @@ public:
return CVR;
}
- bool isConstant(ASTContext& Ctx) const;
+ bool isConstant(ASTContext& Ctx) const {
+ return QualType::isConstant(*this, Ctx);
+ }
// Don't promise in the API that anything besides 'const' can be
// easily added.
@@ -548,7 +550,9 @@ public:
/// concrete.
///
/// Qualifiers are left in place.
- QualType getDesugaredType(bool ForDisplay = false) const;
+ QualType getDesugaredType() const {
+ return QualType::getDesugaredType(*this);
+ }
/// operator==/!= - Indicate whether the specified types and qualifiers are
/// identical.
@@ -594,6 +598,13 @@ public:
/// getNoReturnAttr - Returns true if the type has the noreturn attribute,
/// false otherwise.
bool getNoReturnAttr() const;
+
+private:
+ // These methods are implemented in a separate translation unit;
+ // "static"-ize them to avoid creating temporary QualTypes in the
+ // caller.
+ static bool isConstant(QualType T, ASTContext& Ctx);
+ static QualType getDesugaredType(QualType T);
};
} // end clang.
@@ -842,13 +853,10 @@ public:
/// pointer, this returns the respective pointee.
QualType getPointeeType() const;
- /// getDesugaredType - Return the specified type with any "sugar" removed from
- /// the type. This takes off typedefs, typeof's etc. If the outer level of
- /// the type is already concrete, it returns it unmodified. This is similar
- /// to getting the canonical type, but it doesn't remove *all* typedefs. For
- /// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
- /// concrete.
- QualType getDesugaredType(bool ForDisplay = false) const;
+ /// getUnqualifiedDesugaredType() - Return the specified type with
+ /// any "sugar" removed from the type, removing any typedefs,
+ /// typeofs, etc., as well as any qualifiers.
+ const Type *getUnqualifiedDesugaredType() const;
/// More type predicates useful for type checking/promotion
bool isPromotableIntegerType() const; // C99 6.3.1.1p2
@@ -946,6 +954,9 @@ public:
Kind getKind() const { return TypeKind; }
const char *getName(const LangOptions &LO) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
@@ -968,6 +979,9 @@ public:
bool isSigned() const { return Signed; }
const char *getName() const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
@@ -991,6 +1005,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType());
}
@@ -1018,6 +1035,9 @@ public:
QualType getPointeeType() const { return PointeeType; }
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType());
}
@@ -1048,6 +1068,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType());
}
@@ -1099,6 +1122,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == LValueReference;
}
@@ -1116,6 +1142,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == RValueReference;
}
@@ -1145,6 +1174,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getPointeeType(), getClass());
}
@@ -1237,6 +1269,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getSize(),
getSizeModifier(), getIndexTypeCVRQualifiers());
@@ -1286,6 +1321,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArrayWithExpr;
}
@@ -1314,6 +1352,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == ConstantArrayWithoutExpr;
}
@@ -1337,6 +1378,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == IncompleteArray;
}
@@ -1400,6 +1444,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == VariableArray;
}
@@ -1453,6 +1500,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == DependentSizedArray;
}
@@ -1502,6 +1552,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == DependentSizedExtVector;
}
@@ -1544,6 +1597,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getElementType(), getNumElements(), getTypeClass());
}
@@ -1619,6 +1675,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == ExtVector;
}
@@ -1661,7 +1720,6 @@ public:
QualType getResultType() const { return ResultType; }
bool getNoReturnAttr() const { return NoReturn; }
-
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionNoProto ||
T->getTypeClass() == FunctionProto;
@@ -1683,6 +1741,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getResultType(), getNoReturnAttr());
}
@@ -1793,6 +1854,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const Type *T) {
return T->getTypeClass() == FunctionProto;
}
@@ -1828,6 +1892,9 @@ public:
/// looking through the typedefs for B will give you "const volatile A".
QualType LookThroughTypedefs() const;
+ bool isSugared() const { return true; }
+ QualType desugar() const;
+
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
@@ -1845,6 +1912,12 @@ protected:
public:
Expr *getUnderlyingExpr() const { return TOExpr; }
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const;
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return true; }
+
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
@@ -1862,6 +1935,9 @@ public:
DependentTypeOfExprType(ASTContext &Context, Expr *E)
: TypeOfExprType(E), Context(Context) { }
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, getUnderlyingExpr());
}
@@ -1881,6 +1957,12 @@ class TypeOfType : public Type {
public:
QualType getUnderlyingType() const { return TOType; }
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const { return getUnderlyingType(); }
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return true; }
+
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
@@ -1904,6 +1986,12 @@ public:
Expr *getUnderlyingExpr() const { return E; }
QualType getUnderlyingType() const { return UnderlyingType; }
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const { return getUnderlyingType(); }
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return !isDependentType(); }
+
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
@@ -1919,6 +2007,9 @@ class DependentDecltypeType : public DecltypeType, public llvm::FoldingSetNode {
public:
DependentDecltypeType(ASTContext &Context, Expr *E);
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Context, getUnderlyingExpr());
}
@@ -1983,6 +2074,9 @@ public:
// the same address space, and return that.
unsigned getAddressSpace() const { return 0; }
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const TagType *T);
static bool classof(const Type *T) {
return isa<TagType>(T) && classof(cast<TagType>(T));
@@ -2002,6 +2096,9 @@ public:
return reinterpret_cast<EnumDecl*>(TagType::getDecl());
}
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
static bool classof(const TagType *T);
static bool classof(const Type *T) {
return isa<TagType>(T) && classof(cast<TagType>(T));
@@ -2043,6 +2140,12 @@ public:
TagKind getTagKind() const { return Tag; }
QualType getUnderlyingType() const { return UnderlyingType; }
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const { return getUnderlyingType(); }
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return true; }
+
static const char *getNameForTagKind(TagKind Kind) {
switch (Kind) {
default: assert(0 && "Unknown TagKind!");
@@ -2094,6 +2197,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Depth, Index, ParameterPack, Name);
}
@@ -2185,6 +2291,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return !isDependentType(); }
+ QualType desugar() const { return getCanonicalTypeInternal(); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, Template, getArgs(), NumArgs, Context);
}
@@ -2227,6 +2336,12 @@ public:
/// \brief Retrieve the type named by the qualified-id.
QualType getNamedType() const { return NamedType; }
+ /// \brief Remove a single level of sugar.
+ QualType desugar() const { return getNamedType(); }
+
+ /// \brief Returns whether this type directly provides sugar.
+ bool isSugared() const { return true; }
+
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
@@ -2307,6 +2422,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, NNS, Name);
}
@@ -2357,6 +2475,9 @@ public:
virtual void getAsStringInternal(std::string &InnerString,
const PrintingPolicy &Policy) const;
+ bool isSugared() const { return false; }
+ QualType desugar() const { return QualType(this, 0); }
+
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID,
const ObjCInterfaceDecl *Decl,
@@ -2432,6 +2553,9 @@ public:
/// interface type, or 0 if there are none.
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);
@@ -2472,6 +2596,9 @@ public:
/// \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);
@@ -2803,7 +2930,7 @@ template <typename T> const T *Type::getAs() const {
// If this is a typedef for the type, strip the typedef off without
// losing all typedef information.
- return cast<T>(getDesugaredType());
+ return cast<T>(getUnqualifiedDesugaredType());
}
} // end namespace clang
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index ae0580afa4..0e487691a8 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -218,11 +218,11 @@ public:
QualType getDesugaredValueType(ASTContext& C) const {
QualType T = getValueType(C);
- return T.getTypePtr() ? T->getDesugaredType() : T;
+ return T.getTypePtr() ? T.getDesugaredType() : T;
}
QualType getDesugaredLocationType(ASTContext& C) const {
- return getLocationType(C)->getDesugaredType();
+ return getLocationType(C).getDesugaredType();
}
bool isBoundable() const {
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp
index 70b9fa5946..0293862bae 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -22,12 +22,12 @@
#include "llvm/Support/raw_ostream.h"
using namespace clang;
-bool QualType::isConstant(ASTContext &Ctx) const {
- if (isConstQualified())
+bool QualType::isConstant(QualType T, ASTContext &Ctx) {
+ if (T.isConstQualified())
return true;
- if (getTypePtr()->isArrayType())
- return Ctx.getAsArrayType(*this)->getElementType().isConstant(Ctx);
+ if (const ArrayType *AT = Ctx.getAsArrayType(T))
+ return AT->getElementType().isConstant(Ctx);
return false;
}
@@ -106,7 +106,8 @@ const Type *Type::getArrayElementTypeNoTypeQual() const {
// If this is a typedef for an array type, strip the typedef off without
// losing all typedef information.
- return cast<ArrayType>(getDesugaredType())->getElementType().getTypePtr();
+ return cast<ArrayType>(getUnqualifiedDesugaredType())
+ ->getElementType().getTypePtr();
}
/// getDesugaredType - Return the specified type with any "sugar" removed from
@@ -115,62 +116,46 @@ const Type *Type::getArrayElementTypeNoTypeQual() const {
/// to getting the canonical type, but it doesn't remove *all* typedefs. For
/// example, it returns "T*" as "T*", (not as "int*"), because the pointer is
/// concrete.
-///
-/// \param ForDisplay When true, the desugaring is provided for
-/// display purposes only. In this case, we apply more heuristics to
-/// decide whether it is worth providing a desugared form of the type
-/// or not.
-QualType QualType::getDesugaredType(bool ForDisplay) const {
+QualType QualType::getDesugaredType(QualType T) {
QualifierCollector Qs;
- return Qs.apply(Qs.strip(*this)->getDesugaredType(ForDisplay));
-}
-/// getDesugaredType - Return the specified type with any "sugar" removed from
-/// type type. This takes off typedefs, typeof's etc. If the outer level of
-/// the type is already concrete, it returns it unmodified. This is similar
-/// to getting the canonical type, but it doesn't remove *all* typedefs. For
-/// example, it return "T*" as "T*", (not as "int*"), because the pointer is
-/// concrete.
-///
-/// \param ForDisplay When true, the desugaring is provided for
-/// display purposes only. In this case, we apply more heuristics to
-/// decide whether it is worth providing a desugared form of the type
-/// or not.
-QualType Type::getDesugaredType(bool ForDisplay) const {
- if (const TypedefType *TDT = dyn_cast<TypedefType>(this))
- return TDT->LookThroughTypedefs().getDesugaredType();
- if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(this))
- return ET->getUnderlyingType().getDesugaredType();
- if (const TypeOfExprType *TOE = dyn_cast<TypeOfExprType>(this))
- return TOE->getUnderlyingExpr()->getType().getDesugaredType();
- if (const TypeOfType *TOT = dyn_cast<TypeOfType>(this))
- return TOT->getUnderlyingType().getDesugaredType();
- if (const DecltypeType *DTT = dyn_cast<DecltypeType>(this)) {
- if (!DTT->getUnderlyingType()->isDependentType())
- return DTT->getUnderlyingType().getDesugaredType();
- }
- if (const TemplateSpecializationType *Spec
- = dyn_cast<TemplateSpecializationType>(this)) {
- if (ForDisplay)
- return QualType(this, 0);
-
- QualType Canon = Spec->getCanonicalTypeInternal();
- if (Canon->getAs<TemplateSpecializationType>())
- return QualType(this, 0);
- return Canon->getDesugaredType();
- }
- if (const QualifiedNameType *QualName = dyn_cast<QualifiedNameType>(this)) {
- if (ForDisplay) {
- // If desugaring the type that the qualified name is referring to
- // produces something interesting, that's our desugared type.
- QualType NamedType = QualName->getNamedType().getDesugaredType();
- if (NamedType != QualName->getNamedType())
- return NamedType;
- } else
- return QualName->getNamedType().getDesugaredType();
+ QualType Cur = T;
+ while (true) {
+ const Type *CurTy = Qs.strip(Cur);
+ switch (CurTy->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Type::Class: { \
+ const Class##Type *Ty = cast<Class##Type>(CurTy); \
+ if (!Ty->isSugared()) \
+ return Qs.apply(Cur); \
+ Cur = Ty->desugar(); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
}
+}
- return QualType(this, 0);
+/// getUnqualifiedDesugaredType - Pull any qualifiers and syntactic
+/// sugar off the given type. This should produce an object of the
+/// same dynamic type as the canonical type.
+const Type *Type::getUnqualifiedDesugaredType() const {
+ const Type *Cur = this;
+
+ while (true) {
+ switch (Cur->getTypeClass()) {
+#define ABSTRACT_TYPE(Class, Parent)
+#define TYPE(Class, Parent) \
+ case Class: { \
+ const Class##Type *Ty = cast<Class##Type>(Cur); \
+ if (!Ty->isSugared()) return Cur; \
+ Cur = Ty->desugar().getTypePtr(); \
+ break; \
+ }
+#include "clang/AST/TypeNodes.def"
+ }
+ }
}
/// isVoidType - Helper method to determine if this is the 'void' type.
@@ -303,7 +288,7 @@ const RecordType *Type::getAsStructureType() const {
// If this is a typedef for a structure type, strip the typedef off without
// losing all typedef information.
- return cast<RecordType>(getDesugaredType());
+ return cast<RecordType>(getUnqualifiedDesugaredType());
}
return 0;
}
@@ -322,7 +307,7 @@ const RecordType *Type::getAsUnionType() const {
// If this is a typedef for a union type, strip the typedef off without
// losing all typedef information.
- return cast<RecordType>(getDesugaredType());
+ return cast<RecordType>(getUnqualifiedDesugaredType());
}
return 0;
@@ -790,10 +775,18 @@ QualType TypedefType::LookThroughTypedefs() const {
return Qs.apply(CurType);
}
+QualType TypedefType::desugar() const {
+ return getDecl()->getUnderlyingType();
+}
+
TypeOfExprType::TypeOfExprType(Expr *E, QualType can)
: Type(TypeOfExpr, can, E->isTypeDependent()), TOExpr(E) {
}
+QualType TypeOfExprType::desugar() const {
+ return getUnderlyingExpr()->getType();
+}
+
void DependentTypeOfExprType::Profile(llvm::FoldingSetNodeID &ID,
ASTContext &Context, Expr *E) {
E->Profile(ID, Context, true);
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index f63e9d874e..7a433dd148 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -770,7 +770,7 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) {
return UnknownVal();
// Strip off typedefs from the ArrayRegion's ValueType.
- QualType T = ArrayR->getValueType(getContext())->getDesugaredType();
+ QualType T = ArrayR->getValueType(getContext()).getDesugaredType();
ArrayType *AT = cast<ArrayType>(T);
T = AT->getElementType();
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp
index 81f7283e23..3aae2563d1 100644
--- a/lib/Sema/Sema.cpp
+++ b/lib/Sema/Sema.cpp
@@ -44,16 +44,23 @@ static void ConvertArgToStringFn(Diagnostic::ArgumentKind Kind, intptr_t Val,
// If this is a sugared type (like a typedef, typeof, etc), then unwrap one
// level of the sugar so that the type is more obvious to the user.
- QualType DesugaredTy = Ty.getDesugaredType(true);
+ QualType DesugaredTy = Ty.getDesugaredType();
if (Ty != DesugaredTy &&
// If the desugared type is a vector type, we don't want to expand it,
// it will turn into an attribute mess. People want their "vec4".
!isa<VectorType>(DesugaredTy) &&
- // Don't aka just because we saw an elaborated type.
+ // Don't aka just because we saw an elaborated type...
(!isa<ElaboratedType>(Ty) ||
- cast<ElaboratedType>(Ty)->getUnderlyingType() != DesugaredTy) &&
+ cast<ElaboratedType>(Ty)->desugar() != DesugaredTy) &&
+
+ // ...or a qualified name type...
+ (!isa<QualifiedNameType>(Ty) ||
+ cast<QualifiedNameType>(Ty)->desugar() != DesugaredTy) &&
+
+ // ...or a non-dependent template specialization.
+ (!isa<TemplateSpecializationType>(Ty) || Ty->isDependentType()) &&
// Don't desugar magic Objective-C types.
Ty.getUnqualifiedType() != Context.getObjCIdType() &&
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 7aa0261ff6..223662afce 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -1267,7 +1267,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
assert(BaseClass && "ActOnMemInitializers - neither field or base");
Diag(Member->getSourceLocation(),
diag::error_multiple_base_initialization)
- << BaseClass->getDesugaredType(true);
+ << QualType(BaseClass, 0);
}
Diag(PrevMember->getSourceLocation(), diag::note_previous_initializer)
<< 0;
@@ -1336,7 +1336,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
Type *BaseClass = PrevMember->getBaseClass();
Diag(PrevMember->getSourceLocation(),
diag::warn_base_initialized)
- << BaseClass->getDesugaredType(true);
+ << QualType(BaseClass, 0);
} else {
FieldDecl *Field = PrevMember->getMember();
Diag(PrevMember->getSourceLocation(),
@@ -1352,7 +1352,7 @@ void Sema::ActOnMemInitializers(DeclPtrTy ConstructorDecl,
Type *BaseClass = Member->getBaseClass();
Diag(Member->getSourceLocation(),
diag::note_fieldorbase_initialized_here) << 1
- << BaseClass->getDesugaredType(true);
+ << QualType(BaseClass, 0);
}
for (curIndex = 0; curIndex < Last; curIndex++)
if (MemberInCtorList == AllBaseOrMembers[curIndex])