From 49f4e1cbd839da27ff4814b4ea6d85a79f786cbd Mon Sep 17 00:00:00 2001 From: John McCall Date: Fri, 10 Dec 2010 11:01:00 +0000 Subject: [PATCH] It's kindof silly that ExtQuals has an ASTContext&, and we can use that space better. Remove this reference. To make that work, change some APIs (most importantly, getDesugaredType()) to take an ASTContext& if they need to return a QualType. Simultaneously, diminish the need to return a QualType by introducing some useful APIs on SplitQualType, which is just a std::pair. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121478 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Type.h | 131 ++++++----- .../clang/Checker/PathSensitive/MemRegion.h | 8 +- lib/AST/ASTContext.cpp | 6 +- lib/AST/ASTDiagnostic.cpp | 2 +- lib/AST/StmtDumper.cpp | 9 +- lib/AST/Type.cpp | 45 +--- lib/AST/TypePrinter.cpp | 207 +++++++++--------- lib/Checker/GRExprEngine.cpp | 4 +- lib/Checker/MemRegion.cpp | 4 +- lib/Checker/RegionStore.cpp | 2 +- lib/CodeGen/CGDebugInfo.cpp | 2 +- lib/Sema/SemaDecl.cpp | 2 +- lib/Sema/SemaExpr.cpp | 20 +- lib/Sema/SemaOverload.cpp | 6 +- lib/Sema/SemaStmt.cpp | 2 +- lib/Sema/SemaTemplate.cpp | 4 +- lib/Sema/SemaTemplateDeduction.cpp | 4 +- lib/Serialization/ASTCommon.h | 2 +- 18 files changed, 219 insertions(+), 241 deletions(-) diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index ccc732f61e..d041a405e2 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -351,12 +351,6 @@ class ExtQuals : public llvm::FoldingSetNode { // 3. ASTContext: // a) Update get{Volatile,Restrict}Type. - /// Context - the context to which this set belongs. We save this - /// here so that QualifierCollector can use it to reapply extended - /// qualifiers to an arbitrary type without requiring a context to - /// be pushed through every single API dealing with qualifiers. - ASTContext& Context; - /// BaseType - the underlying type that this qualifies const Type *BaseType; @@ -365,8 +359,7 @@ class ExtQuals : public llvm::FoldingSetNode { Qualifiers Quals; public: - ExtQuals(ASTContext& Context, const Type *Base, Qualifiers Quals) - : Context(Context), BaseType(Base), Quals(Quals) + ExtQuals(const Type *Base, Qualifiers Quals) : BaseType(Base), Quals(Quals) { assert(Quals.hasNonFastQualifiers() && "ExtQuals created with no fast qualifiers"); @@ -384,8 +377,6 @@ public: const Type *getBaseType() const { return BaseType; } - ASTContext &getContext() const { return Context; } - public: void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, getBaseType(), Quals); @@ -409,6 +400,7 @@ enum CallingConv { CC_X86Pascal // __attribute__((pascal)) }; +typedef std::pair SplitQualType; /// QualType - For efficiency, we don't store CV-qualified types as nodes on /// their own: instead each reference to a type stores the qualifiers. This @@ -458,6 +450,19 @@ public: return const_cast(getTypePtrUnsafe()); } + /// Divides a QualType into its unqualified type and a set of local + /// qualifiers. + SplitQualType split() const { + if (!hasLocalNonFastQualifiers()) + return SplitQualType(getTypePtrUnsafe(), + Qualifiers::fromFastMask(getLocalFastQualifiers())); + + const ExtQuals *eq = getExtQualsUnsafe(); + Qualifiers qs = eq->getQualifiers(); + qs.addFastQualifiers(getLocalFastQualifiers()); + return SplitQualType(eq->getBaseType(), qs); + } + void *getAsOpaquePtr() const { return Value.getOpaqueValue(); } static QualType getFromOpaquePtr(void *Ptr) { QualType T; @@ -579,16 +584,13 @@ public: Value.setInt(Value.getInt() | TQs); } - // FIXME: The remove* functions are semantically broken, because they might - // not remove a qualifier stored on a typedef. Most of the with* functions - // have the same problem. - void removeConst(); - void removeVolatile(); - void removeRestrict(); - void removeCVRQualifiers(unsigned Mask); + void removeLocalConst(); + void removeLocalVolatile(); + void removeLocalRestrict(); + void removeLocalCVRQualifiers(unsigned Mask); - void removeFastQualifiers() { Value.setInt(0); } - void removeFastQualifiers(unsigned Mask) { + void removeLocalFastQualifiers() { Value.setInt(0); } + void removeLocalFastQualifiers(unsigned Mask) { assert(!(Mask & ~Qualifiers::FastMask) && "mask has non-fast qualifiers"); Value.setInt(Value.getInt() & ~Mask); } @@ -603,14 +605,14 @@ public: // Creates a type with exactly the given fast qualifiers, removing // any existing fast qualifiers. - QualType withExactFastQualifiers(unsigned TQs) const { - return withoutFastQualifiers().withFastQualifiers(TQs); + QualType withExactLocalFastQualifiers(unsigned TQs) const { + return withoutLocalFastQualifiers().withFastQualifiers(TQs); } // Removes fast qualifiers, but leaves any extended qualifiers in place. - QualType withoutFastQualifiers() const { + QualType withoutLocalFastQualifiers() const { QualType T = *this; - T.removeFastQualifiers(); + T.removeLocalFastQualifiers(); return T; } @@ -651,8 +653,12 @@ public: /// concrete. /// /// Qualifiers are left in place. - QualType getDesugaredType() const { - return QualType::getDesugaredType(*this); + QualType getDesugaredType(ASTContext &Context) const { + return getDesugaredType(*this, Context); + } + + SplitQualType getSplitDesugaredType() const { + return getSplitDesugaredType(*this); } /// operator==/!= - Indicate whether the specified types and qualifiers are @@ -663,7 +669,13 @@ public: friend bool operator!=(const QualType &LHS, const QualType &RHS) { return LHS.Value != RHS.Value; } - std::string getAsString() const; + std::string getAsString() const { + return getAsString(split()); + } + static std::string getAsString(SplitQualType split) { + return getAsString(split.first, split.second); + } + static std::string getAsString(const Type *ty, Qualifiers qs); std::string getAsString(const PrintingPolicy &Policy) const { std::string S; @@ -671,7 +683,16 @@ public: return S; } void getAsStringInternal(std::string &Str, - const PrintingPolicy &Policy) const; + const PrintingPolicy &Policy) const { + return getAsStringInternal(split(), Str, Policy); + } + static void getAsStringInternal(SplitQualType split, std::string &out, + const PrintingPolicy &policy) { + return getAsStringInternal(split.first, split.second, out, policy); + } + static void getAsStringInternal(const Type *ty, Qualifiers qs, + std::string &out, + const PrintingPolicy &policy); void dump(const char *s) const; void dump() const; @@ -701,7 +722,8 @@ private: // "static"-ize them to avoid creating temporary QualTypes in the // caller. static bool isConstant(QualType T, ASTContext& Ctx); - static QualType getDesugaredType(QualType T); + static QualType getDesugaredType(QualType T, ASTContext &Context); + static SplitQualType getSplitDesugaredType(QualType T); }; } // end clang. @@ -2278,14 +2300,6 @@ public: TypedefDecl *getDecl() const { return Decl; } - /// LookThroughTypedefs - Return the ultimate type this typedef corresponds to - /// potentially looking through *all* consecutive typedefs. This returns the - /// sum of the type qualifiers, so if you have: - /// typedef const int A; - /// typedef volatile A B; - /// looking through the typedefs for B will give you "const volatile A". - QualType LookThroughTypedefs() const; - bool isSugared() const { return true; } QualType desugar() const; @@ -3341,15 +3355,8 @@ public: /// A qualifier set is used to build a set of qualifiers. class QualifierCollector : public Qualifiers { - ASTContext *Context; - public: - QualifierCollector(Qualifiers Qs = Qualifiers()) - : Qualifiers(Qs), Context(0) {} - QualifierCollector(ASTContext &Context, Qualifiers Qs = Qualifiers()) - : Qualifiers(Qs), Context(&Context) {} - - void setContext(ASTContext &C) { Context = &C; } + QualifierCollector(Qualifiers Qs = Qualifiers()) : Qualifiers(Qs) {} /// Collect any qualifiers on the given type and return an /// unqualified type. @@ -3357,7 +3364,6 @@ public: addFastQualifiers(QT.getLocalFastQualifiers()); if (QT.hasLocalNonFastQualifiers()) { const ExtQuals *EQ = QT.getExtQualsUnsafe(); - Context = &EQ->getContext(); addQualifiers(EQ->getQualifiers()); return EQ->getBaseType(); } @@ -3365,11 +3371,10 @@ public: } /// Apply the collected qualifiers to the given type. - QualType apply(QualType QT) const; + QualType apply(ASTContext &Context, QualType QT) const; /// Apply the collected qualifiers to the given type. - QualType apply(const Type* T) const; - + QualType apply(ASTContext &Context, const Type* T) const; }; @@ -3445,36 +3450,24 @@ inline unsigned QualType::getCVRQualifiersThroughArrayTypes() const { return 0; } -inline void QualType::removeConst() { - removeFastQualifiers(Qualifiers::Const); +inline void QualType::removeLocalConst() { + removeLocalFastQualifiers(Qualifiers::Const); } -inline void QualType::removeRestrict() { - removeFastQualifiers(Qualifiers::Restrict); +inline void QualType::removeLocalRestrict() { + removeLocalFastQualifiers(Qualifiers::Restrict); } -inline void QualType::removeVolatile() { - QualifierCollector Qc; - const Type *Ty = Qc.strip(*this); - if (Qc.hasVolatile()) { - Qc.removeVolatile(); - *this = Qc.apply(Ty); - } +inline void QualType::removeLocalVolatile() { + removeLocalFastQualifiers(Qualifiers::Volatile); } -inline void QualType::removeCVRQualifiers(unsigned Mask) { +inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits"); + assert(Qualifiers::CVRMask == Qualifiers::FastMask); // Fast path: we don't need to touch the slow qualifiers. - if (!(Mask & ~Qualifiers::FastMask)) { - removeFastQualifiers(Mask); - return; - } - - QualifierCollector Qc; - const Type *Ty = Qc.strip(*this); - Qc.removeCVRQualifiers(Mask); - *this = Qc.apply(Ty); + removeLocalFastQualifiers(Mask); } /// getAddressSpace - Return the address space of this type. diff --git a/include/clang/Checker/PathSensitive/MemRegion.h b/include/clang/Checker/PathSensitive/MemRegion.h index fb0ed27c14..33793e66e3 100644 --- a/include/clang/Checker/PathSensitive/MemRegion.h +++ b/include/clang/Checker/PathSensitive/MemRegion.h @@ -357,13 +357,13 @@ public: return getContext().getPointerType(getValueType()); } - QualType getDesugaredValueType() const { + QualType getDesugaredValueType(ASTContext &Context) const { QualType T = getValueType(); - return T.getTypePtr() ? T.getDesugaredType() : T; + return T.getTypePtr() ? T.getDesugaredType(Context) : T; } - QualType getDesugaredLocationType() const { - return getLocationType().getDesugaredType(); + QualType getDesugaredLocationType(ASTContext &Context) const { + return getLocationType().getDesugaredType(Context); } bool isBoundable() const { return true; } diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 9e46e8765c..dfdc505b1a 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -1084,7 +1084,7 @@ QualType ASTContext::getExtQualType(const Type *TypeNode, Qualifiers Quals) { return T; } - ExtQuals *New = new (*this, TypeAlignment) ExtQuals(*this, TypeNode, Quals); + ExtQuals *New = new (*this, TypeAlignment) ExtQuals(TypeNode, Quals); ExtQualNodes.InsertNode(New, InsertPos); QualType T = QualType(New, Fast); return T; @@ -2791,7 +2791,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) { // we must propagate them down into the element type. QualifierCollector Qs; - const Type *Ty = Qs.strip(T.getDesugaredType()); + const Type *Ty = Qs.strip(T.getDesugaredType(*this)); // If we have a simple case, just return now. const ArrayType *ATy = dyn_cast(Ty); @@ -2854,7 +2854,7 @@ QualType ASTContext::getBaseElementType(QualType QT) { QualifierCollector Qs; while (const ArrayType *AT = getAsArrayType(QualType(Qs.strip(QT), 0))) QT = AT->getElementType(); - return Qs.apply(QT); + return Qs.apply(*this, QT); } QualType ASTContext::getBaseElementType(const ArrayType *AT) { diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index 321a139665..8d5e408465 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -101,7 +101,7 @@ break; \ ShouldAKA)); } - return QC.apply(QT); + return QC.apply(Context, QT); } /// \brief Convert the given type to a string suitable for printing as part of diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index 60792bbd00..56bfa35425 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -90,13 +90,14 @@ namespace { } void DumpType(QualType T) { - OS << "'" << T.getAsString() << "'"; + SplitQualType T_split = T.split(); + OS << "'" << QualType::getAsString(T_split) << "'"; if (!T.isNull()) { // If the type is sugared, also dump a (shallow) desugared type. - QualType Simplified = T.getDesugaredType(); - if (Simplified != T) - OS << ":'" << Simplified.getAsString() << "'"; + SplitQualType D_split = T.getSplitDesugaredType(); + if (T_split != D_split) + OS << ":'" << QualType::getAsString(D_split) << "'"; } } void DumpStmt(const Stmt *Node) { diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 489f766d04..705b097212 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -145,7 +145,12 @@ QualType QualType::getUnqualifiedTypeSlow() 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. -QualType QualType::getDesugaredType(QualType T) { +QualType QualType::getDesugaredType(QualType T, ASTContext &Context) { + SplitQualType split = getSplitDesugaredType(T); + return Context.getQualifiedType(split.first, split.second); +} + +SplitQualType QualType::getSplitDesugaredType(QualType T) { QualifierCollector Qs; QualType Cur = T; @@ -157,7 +162,7 @@ QualType QualType::getDesugaredType(QualType T) { case Type::Class: { \ const Class##Type *Ty = cast(CurTy); \ if (!Ty->isSugared()) \ - return Qs.apply(Cur); \ + return SplitQualType(Ty, Qs); \ Cur = Ty->desugar(); \ break; \ } @@ -1089,32 +1094,6 @@ void FunctionProtoType::Profile(llvm::FoldingSetNodeID &ID) { getExtInfo()); } -/// 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: -/// typedef const int A; -/// typedef volatile A B; -/// looking through the typedefs for B will give you "const volatile A". -/// -QualType TypedefType::LookThroughTypedefs() const { - // Usually, there is only a single level of typedefs, be fast in that case. - QualType FirstType = getDecl()->getUnderlyingType(); - if (!isa(FirstType)) - return FirstType; - - // Otherwise, do the fully general loop. - QualifierCollector Qs; - - QualType CurType; - const TypedefType *TDT = this; - do { - CurType = TDT->getDecl()->getUnderlyingType(); - TDT = dyn_cast(Qs.strip(CurType)); - } while (TDT); - - return Qs.apply(CurType); -} - QualType TypedefType::desugar() const { return getDecl()->getUnderlyingType(); } @@ -1280,20 +1259,18 @@ TemplateSpecializationType::Profile(llvm::FoldingSetNodeID &ID, Args[Idx].Profile(ID, Context); } -QualType QualifierCollector::apply(QualType QT) const { +QualType QualifierCollector::apply(ASTContext &Context, QualType QT) const { if (!hasNonFastQualifiers()) return QT.withFastQualifiers(getFastQualifiers()); - assert(Context && "extended qualifiers but no context!"); - return Context->getQualifiedType(QT, *this); + return Context.getQualifiedType(QT, *this); } -QualType QualifierCollector::apply(const Type *T) const { +QualType QualifierCollector::apply(ASTContext &Context, const Type *T) const { if (!hasNonFastQualifiers()) return QualType(T, getFastQualifiers()); - assert(Context && "extended qualifiers but no context!"); - return Context->getQualifiedType(T, *this); + return Context.getQualifiedType(T, *this); } void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID, diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 5dfad6c900..0e37acb40f 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -30,12 +30,13 @@ namespace { public: explicit TypePrinter(const PrintingPolicy &Policy) : Policy(Policy) { } - void Print(QualType T, std::string &S); + void print(const Type *ty, Qualifiers qs, std::string &buffer); + void print(QualType T, std::string &S); void AppendScope(DeclContext *DC, std::string &S); - void PrintTag(TagDecl *T, std::string &S); + void printTag(TagDecl *T, std::string &S); #define ABSTRACT_TYPE(CLASS, PARENT) #define TYPE(CLASS, PARENT) \ - void Print##CLASS(const CLASS##Type *T, std::string &S); + void print##CLASS(const CLASS##Type *T, std::string &S); #include "clang/AST/TypeNodes.def" }; } @@ -55,9 +56,14 @@ static void AppendTypeQualList(std::string &S, unsigned TypeQuals) { } } -void TypePrinter::Print(QualType T, std::string &S) { - if (T.isNull()) { - S += "NULL TYPE"; +void TypePrinter::print(QualType t, std::string &buffer) { + SplitQualType split = t.split(); + print(split.first, split.second, buffer); +} + +void TypePrinter::print(const Type *T, Qualifiers Quals, std::string &buffer) { + if (!T) { + buffer += "NULL TYPE"; return; } @@ -65,7 +71,6 @@ void TypePrinter::Print(QualType T, std::string &S) { return; // Print qualifiers as appropriate. - Qualifiers Quals = T.getLocalQualifiers(); // CanPrefixQualifiers - We prefer to print type qualifiers before the type, // so that we get "const int" instead of "int const", but we can't do this if @@ -79,38 +84,38 @@ void TypePrinter::Print(QualType T, std::string &S) { T->isObjCIdType() || T->isObjCQualifiedIdType(); if (!CanPrefixQualifiers && !Quals.empty()) { - std::string TQS; - Quals.getAsStringInternal(TQS, Policy); + std::string qualsBuffer; + Quals.getAsStringInternal(qualsBuffer, Policy); - if (!S.empty()) { - TQS += ' '; - TQS += S; + if (!buffer.empty()) { + qualsBuffer += ' '; + qualsBuffer += buffer; } - std::swap(S, TQS); + std::swap(buffer, qualsBuffer); } switch (T->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) -#define TYPE(CLASS, PARENT) case Type::CLASS: \ - Print##CLASS(cast(T.getTypePtr()), S); \ +#define TYPE(CLASS, PARENT) case Type::CLASS: \ + print##CLASS(cast(T), buffer); \ break; #include "clang/AST/TypeNodes.def" } // If we're adding the qualifiers as a prefix, do it now. if (CanPrefixQualifiers && !Quals.empty()) { - std::string TQS; - Quals.getAsStringInternal(TQS, Policy); + std::string qualsBuffer; + Quals.getAsStringInternal(qualsBuffer, Policy); - if (!S.empty()) { - TQS += ' '; - TQS += S; + if (!buffer.empty()) { + qualsBuffer += ' '; + qualsBuffer += buffer; } - std::swap(S, TQS); + std::swap(buffer, qualsBuffer); } } -void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) { +void TypePrinter::printBuiltin(const BuiltinType *T, std::string &S) { if (S.empty()) { S = T->getName(Policy.LangOpts); } else { @@ -120,12 +125,12 @@ void TypePrinter::PrintBuiltin(const BuiltinType *T, std::string &S) { } } -void TypePrinter::PrintComplex(const ComplexType *T, std::string &S) { - Print(T->getElementType(), S); +void TypePrinter::printComplex(const ComplexType *T, std::string &S) { + print(T->getElementType(), S); S = "_Complex " + S; } -void TypePrinter::PrintPointer(const PointerType *T, std::string &S) { +void TypePrinter::printPointer(const PointerType *T, std::string &S) { S = '*' + S; // Handle things like 'int (*A)[4];' correctly. @@ -133,15 +138,15 @@ void TypePrinter::PrintPointer(const PointerType *T, std::string &S) { if (isa(T->getPointeeType())) S = '(' + S + ')'; - Print(T->getPointeeType(), S); + print(T->getPointeeType(), S); } -void TypePrinter::PrintBlockPointer(const BlockPointerType *T, std::string &S) { +void TypePrinter::printBlockPointer(const BlockPointerType *T, std::string &S) { S = '^' + S; - Print(T->getPointeeType(), S); + print(T->getPointeeType(), S); } -void TypePrinter::PrintLValueReference(const LValueReferenceType *T, +void TypePrinter::printLValueReference(const LValueReferenceType *T, std::string &S) { S = '&' + S; @@ -150,10 +155,10 @@ void TypePrinter::PrintLValueReference(const LValueReferenceType *T, if (isa(T->getPointeeTypeAsWritten())) S = '(' + S + ')'; - Print(T->getPointeeTypeAsWritten(), S); + print(T->getPointeeTypeAsWritten(), S); } -void TypePrinter::PrintRValueReference(const RValueReferenceType *T, +void TypePrinter::printRValueReference(const RValueReferenceType *T, std::string &S) { S = "&&" + S; @@ -162,13 +167,13 @@ void TypePrinter::PrintRValueReference(const RValueReferenceType *T, if (isa(T->getPointeeTypeAsWritten())) S = '(' + S + ')'; - Print(T->getPointeeTypeAsWritten(), S); + print(T->getPointeeTypeAsWritten(), S); } -void TypePrinter::PrintMemberPointer(const MemberPointerType *T, +void TypePrinter::printMemberPointer(const MemberPointerType *T, std::string &S) { std::string C; - Print(QualType(T->getClass(), 0), C); + print(QualType(T->getClass(), 0), C); C += "::*"; S = C + S; @@ -177,25 +182,25 @@ void TypePrinter::PrintMemberPointer(const MemberPointerType *T, if (isa(T->getPointeeType())) S = '(' + S + ')'; - Print(T->getPointeeType(), S); + print(T->getPointeeType(), S); } -void TypePrinter::PrintConstantArray(const ConstantArrayType *T, +void TypePrinter::printConstantArray(const ConstantArrayType *T, std::string &S) { S += '['; S += llvm::utostr(T->getSize().getZExtValue()); S += ']'; - Print(T->getElementType(), S); + print(T->getElementType(), S); } -void TypePrinter::PrintIncompleteArray(const IncompleteArrayType *T, +void TypePrinter::printIncompleteArray(const IncompleteArrayType *T, std::string &S) { S += "[]"; - Print(T->getElementType(), S); + print(T->getElementType(), S); } -void TypePrinter::PrintVariableArray(const VariableArrayType *T, +void TypePrinter::printVariableArray(const VariableArrayType *T, std::string &S) { S += '['; @@ -217,10 +222,10 @@ void TypePrinter::PrintVariableArray(const VariableArrayType *T, } S += ']'; - Print(T->getElementType(), S); + print(T->getElementType(), S); } -void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T, +void TypePrinter::printDependentSizedArray(const DependentSizedArrayType *T, std::string &S) { S += '['; @@ -232,13 +237,13 @@ void TypePrinter::PrintDependentSizedArray(const DependentSizedArrayType *T, } S += ']'; - Print(T->getElementType(), S); + print(T->getElementType(), S); } -void TypePrinter::PrintDependentSizedExtVector( +void TypePrinter::printDependentSizedExtVector( const DependentSizedExtVectorType *T, std::string &S) { - Print(T->getElementType(), S); + print(T->getElementType(), S); S += " __attribute__((ext_vector_type("; if (T->getSizeExpr()) { @@ -250,37 +255,37 @@ void TypePrinter::PrintDependentSizedExtVector( S += ")))"; } -void TypePrinter::PrintVector(const VectorType *T, std::string &S) { +void TypePrinter::printVector(const VectorType *T, std::string &S) { switch (T->getVectorKind()) { case VectorType::AltiVecPixel: S = "__vector __pixel " + S; break; case VectorType::AltiVecBool: - Print(T->getElementType(), S); + print(T->getElementType(), S); S = "__vector __bool " + S; break; case VectorType::AltiVecVector: - Print(T->getElementType(), S); + print(T->getElementType(), S); S = "__vector " + S; break; case VectorType::NeonVector: - Print(T->getElementType(), S); + print(T->getElementType(), S); S = ("__attribute__((neon_vector_type(" + llvm::utostr_32(T->getNumElements()) + "))) " + S); break; case VectorType::NeonPolyVector: - Print(T->getElementType(), S); + print(T->getElementType(), S); S = ("__attribute__((neon_polyvector_type(" + llvm::utostr_32(T->getNumElements()) + "))) " + S); break; case VectorType::GenericVector: { // FIXME: We prefer to print the size directly here, but have no way // to get the size of the type. - Print(T->getElementType(), S); + print(T->getElementType(), S); std::string V = "__attribute__((__vector_size__("; V += llvm::utostr_32(T->getNumElements()); // convert back to bytes. std::string ET; - Print(T->getElementType(), ET); + print(T->getElementType(), ET); V += " * sizeof(" + ET + ")))) "; S = V + S; break; @@ -288,14 +293,14 @@ void TypePrinter::PrintVector(const VectorType *T, std::string &S) { } } -void TypePrinter::PrintExtVector(const ExtVectorType *T, std::string &S) { +void TypePrinter::printExtVector(const ExtVectorType *T, std::string &S) { S += " __attribute__((ext_vector_type("; S += llvm::utostr_32(T->getNumElements()); S += ")))"; - Print(T->getElementType(), S); + print(T->getElementType(), S); } -void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, +void TypePrinter::printFunctionProto(const FunctionProtoType *T, std::string &S) { // If needed for precedence reasons, wrap the inner part in grouping parens. if (!S.empty()) @@ -307,7 +312,7 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, ParamPolicy.SuppressSpecifiers = false; for (unsigned i = 0, e = T->getNumArgs(); i != e; ++i) { if (i) S += ", "; - Print(T->getArgType(i), Tmp); + print(T->getArgType(i), Tmp); S += Tmp; Tmp.clear(); } @@ -359,7 +364,7 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, S += ", "; std::string ExceptionType; - Print(T->getExceptionType(I), ExceptionType); + print(T->getExceptionType(I), ExceptionType); S += ExceptionType; } S += ")"; @@ -367,10 +372,10 @@ void TypePrinter::PrintFunctionProto(const FunctionProtoType *T, AppendTypeQualList(S, T->getTypeQuals()); - Print(T->getResultType(), S); + print(T->getResultType(), S); } -void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, +void TypePrinter::printFunctionNoProto(const FunctionNoProtoType *T, std::string &S) { // If needed for precedence reasons, wrap the inner part in grouping parens. if (!S.empty()) @@ -379,10 +384,10 @@ void TypePrinter::PrintFunctionNoProto(const FunctionNoProtoType *T, S += "()"; if (T->getNoReturnAttr()) S += " __attribute__((noreturn))"; - Print(T->getResultType(), S); + print(T->getResultType(), S); } -static void PrintTypeSpec(const NamedDecl *D, std::string &S) { +static void printTypeSpec(const NamedDecl *D, std::string &S) { IdentifierInfo *II = D->getIdentifier(); if (S.empty()) S = II->getName().str(); @@ -390,16 +395,16 @@ static void PrintTypeSpec(const NamedDecl *D, std::string &S) { S = II->getName().str() + ' ' + S; } -void TypePrinter::PrintUnresolvedUsing(const UnresolvedUsingType *T, +void TypePrinter::printUnresolvedUsing(const UnresolvedUsingType *T, std::string &S) { - PrintTypeSpec(T->getDecl(), S); + printTypeSpec(T->getDecl(), S); } -void TypePrinter::PrintTypedef(const TypedefType *T, std::string &S) { - PrintTypeSpec(T->getDecl(), S); +void TypePrinter::printTypedef(const TypedefType *T, std::string &S) { + printTypeSpec(T->getDecl(), S); } -void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) { +void TypePrinter::printTypeOfExpr(const TypeOfExprType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'typeof(e) X'. S = ' ' + S; std::string Str; @@ -408,15 +413,15 @@ void TypePrinter::PrintTypeOfExpr(const TypeOfExprType *T, std::string &S) { S = "typeof " + s.str() + S; } -void TypePrinter::PrintTypeOf(const TypeOfType *T, std::string &S) { +void TypePrinter::printTypeOf(const TypeOfType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'typeof(t) X'. S = ' ' + S; std::string Tmp; - Print(T->getUnderlyingType(), Tmp); + print(T->getUnderlyingType(), Tmp); S = "typeof(" + Tmp + ")" + S; } -void TypePrinter::PrintDecltype(const DecltypeType *T, std::string &S) { +void TypePrinter::printDecltype(const DecltypeType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'decltype(t) X'. S = ' ' + S; std::string Str; @@ -458,7 +463,7 @@ void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { Buffer += "::"; } -void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) { +void TypePrinter::printTag(TagDecl *D, std::string &InnerString) { if (Policy.SuppressTag) return; @@ -538,15 +543,15 @@ void TypePrinter::PrintTag(TagDecl *D, std::string &InnerString) { std::swap(Buffer, InnerString); } -void TypePrinter::PrintRecord(const RecordType *T, std::string &S) { - PrintTag(T->getDecl(), S); +void TypePrinter::printRecord(const RecordType *T, std::string &S) { + printTag(T->getDecl(), S); } -void TypePrinter::PrintEnum(const EnumType *T, std::string &S) { - PrintTag(T->getDecl(), S); +void TypePrinter::printEnum(const EnumType *T, std::string &S) { + printTag(T->getDecl(), S); } -void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T, +void TypePrinter::printTemplateTypeParm(const TemplateTypeParmType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'parmname X'. S = ' ' + S; @@ -558,12 +563,12 @@ void TypePrinter::PrintTemplateTypeParm(const TemplateTypeParmType *T, S = T->getName()->getName().str() + S; } -void TypePrinter::PrintSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, +void TypePrinter::printSubstTemplateTypeParm(const SubstTemplateTypeParmType *T, std::string &S) { - Print(T->getReplacementType(), S); + print(T->getReplacementType(), S); } -void TypePrinter::PrintTemplateSpecialization( +void TypePrinter::printTemplateSpecialization( const TemplateSpecializationType *T, std::string &S) { std::string SpecString; @@ -583,12 +588,12 @@ void TypePrinter::PrintTemplateSpecialization( S = SpecString + ' ' + S; } -void TypePrinter::PrintInjectedClassName(const InjectedClassNameType *T, +void TypePrinter::printInjectedClassName(const InjectedClassNameType *T, std::string &S) { - PrintTemplateSpecialization(T->getInjectedTST(), S); + printTemplateSpecialization(T->getInjectedTST(), S); } -void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { +void TypePrinter::printElaborated(const ElaboratedType *T, std::string &S) { std::string MyString; { @@ -604,7 +609,7 @@ void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { std::string TypeStr; PrintingPolicy InnerPolicy(Policy); InnerPolicy.SuppressScope = true; - TypePrinter(InnerPolicy).Print(T->getNamedType(), TypeStr); + TypePrinter(InnerPolicy).print(T->getNamedType(), TypeStr); MyString += TypeStr; if (S.empty()) @@ -613,7 +618,7 @@ void TypePrinter::PrintElaborated(const ElaboratedType *T, std::string &S) { S = MyString + ' ' + S; } -void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) { +void TypePrinter::printDependentName(const DependentNameType *T, std::string &S) { std::string MyString; { @@ -633,7 +638,7 @@ void TypePrinter::PrintDependentName(const DependentNameType *T, std::string &S) S = MyString + ' ' + S; } -void TypePrinter::PrintDependentTemplateSpecialization( +void TypePrinter::printDependentTemplateSpecialization( const DependentTemplateSpecializationType *T, std::string &S) { std::string MyString; { @@ -657,7 +662,7 @@ void TypePrinter::PrintDependentTemplateSpecialization( S = MyString + ' ' + S; } -void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T, +void TypePrinter::printObjCInterface(const ObjCInterfaceType *T, std::string &S) { if (!S.empty()) // Prefix the basic type, e.g. 'typedefname X'. S = ' ' + S; @@ -666,13 +671,13 @@ void TypePrinter::PrintObjCInterface(const ObjCInterfaceType *T, S = ObjCQIString + S; } -void TypePrinter::PrintObjCObject(const ObjCObjectType *T, +void TypePrinter::printObjCObject(const ObjCObjectType *T, std::string &S) { if (T->qual_empty()) - return Print(T->getBaseType(), S); + return print(T->getBaseType(), S); std::string tmp; - Print(T->getBaseType(), tmp); + print(T->getBaseType(), tmp); tmp += '<'; bool isFirst = true; for (ObjCObjectType::qual_iterator @@ -692,7 +697,7 @@ void TypePrinter::PrintObjCObject(const ObjCObjectType *T, std::swap(tmp, S); } -void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, +void TypePrinter::printObjCObjectPointer(const ObjCObjectPointerType *T, std::string &S) { std::string ObjCQIString; @@ -730,7 +735,7 @@ void TypePrinter::PrintObjCObjectPointer(const ObjCObjectPointerType *T, S = ObjCQIString + S; } -static void PrintTemplateArgument(std::string &Buffer, +static void printTemplateArgument(std::string &Buffer, const TemplateArgument &Arg, const PrintingPolicy &Policy) { switch (Arg.getKind()) { @@ -789,7 +794,7 @@ TemplateSpecializationType::PrintTemplateArgumentList( // Print the argument into a string. std::string ArgString; - PrintTemplateArgument(ArgString, Args[Arg], Policy); + printTemplateArgument(ArgString, Args[Arg], Policy); // If this is the first argument and its string representation // begins with the global scope specifier ('::foo'), add a space @@ -823,7 +828,7 @@ PrintTemplateArgumentList(const TemplateArgumentLoc *Args, unsigned NumArgs, // Print the argument into a string. std::string ArgString; - PrintTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); + printTemplateArgument(ArgString, Args[Arg].getArgument(), Policy); // If this is the first argument and its string representation // begins with the global scope specifier ('::foo'), add a space @@ -889,15 +894,15 @@ void Qualifiers::getAsStringInternal(std::string &S, } } -std::string QualType::getAsString() const { - std::string S; - LangOptions LO; - getAsStringInternal(S, PrintingPolicy(LO)); - return S; +std::string QualType::getAsString(const Type *ty, Qualifiers qs) { + std::string buffer; + LangOptions options; + getAsStringInternal(ty, qs, buffer, PrintingPolicy(options)); + return buffer; } -void QualType::getAsStringInternal(std::string &S, - const PrintingPolicy &Policy) const { - TypePrinter Printer(Policy); - Printer.Print(*this, S); +void QualType::getAsStringInternal(const Type *ty, Qualifiers qs, + std::string &buffer, + const PrintingPolicy &policy) { + TypePrinter(policy).print(ty, qs, buffer); } diff --git a/lib/Checker/GRExprEngine.cpp b/lib/Checker/GRExprEngine.cpp index e01f5d9f03..efe8fbf25c 100644 --- a/lib/Checker/GRExprEngine.cpp +++ b/lib/Checker/GRExprEngine.cpp @@ -1263,8 +1263,8 @@ void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred, // NOTE: Do not use 'isAggregateType()' here as CXXRecordDecls that // are non-pod are not aggregates. - assert ((isa(Ex->getType().getDesugaredType()) || - isa(Ex->getType().getDesugaredType())) && + assert ((Ex->getType()->isRecordType() || + Ex->getType()->isArrayType()) && "Other kinds of expressions with non-aggregate/union/class types" " do not have lvalues."); diff --git a/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp index 9babe3447f..b08a53ffe7 100644 --- a/lib/Checker/MemRegion.cpp +++ b/lib/Checker/MemRegion.cpp @@ -178,7 +178,7 @@ const StackFrameContext *VarRegion::getStackFrame() const { DefinedOrUnknownSVal DeclRegion::getExtent(SValBuilder &svalBuilder) const { ASTContext& Ctx = svalBuilder.getContext(); - QualType T = getDesugaredValueType(); + QualType T = getDesugaredValueType(Ctx); if (isa(T)) return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this)); @@ -196,7 +196,7 @@ DefinedOrUnknownSVal FieldRegion::getExtent(SValBuilder &svalBuilder) const { // A zero-length array at the end of a struct often stands for dynamically- // allocated extra memory. if (Extent.isZeroConstant()) { - QualType T = getDesugaredValueType(); + QualType T = getDesugaredValueType(svalBuilder.getContext()); if (isa(T)) return UnknownVal(); diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index cf0a444001..bc28f137c4 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -799,7 +799,7 @@ SVal RegionStoreManager::ArrayToPointer(Loc Array) { return UnknownVal(); // Strip off typedefs from the ArrayRegion's ValueType. - QualType T = ArrayR->getValueType().getDesugaredType(); + QualType T = ArrayR->getValueType().getDesugaredType(Ctx); ArrayType *AT = cast(T); T = AT->getElementType(); diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index f83754e52b..3e77769466 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -387,7 +387,7 @@ llvm::DIType CGDebugInfo::CreateQualifiedType(QualType Ty, llvm::DIFile Unit) { return getOrCreateType(QualType(T, 0), Unit); } - llvm::DIType FromTy = getOrCreateType(Qc.apply(T), Unit); + llvm::DIType FromTy = getOrCreateType(Qc.apply(CGM.getContext(), T), Unit); // No need to fill in the Name, Line, Size, Alignment, Offset in case of // CVR derived types. diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index faf3b7382d..1112d85b8b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2569,7 +2569,7 @@ static QualType TryToFixInvalidVariablyModifiedType(QualType T, Oversized); if (FixedType.isNull()) return FixedType; FixedType = Context.getPointerType(FixedType); - return Qs.apply(FixedType); + return Qs.apply(Context, FixedType); } const VariableArrayType* VLATy = dyn_cast(T); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index bffc32f301..27e9e62fb3 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -5114,34 +5114,34 @@ QualType Sema::FindCompositeObjCPointerType(Expr *&LHS, Expr *&RHS, // to the pseudo-builtin, because that will be implicitly cast back to the // redefinition type if an attempt is made to access its fields. if (LHSTy->isObjCClassType() && - (RHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { + (Context.hasSameType(RHSTy, Context.ObjCClassRedefinitionType))) { ImpCastExprToType(RHS, LHSTy, CK_BitCast); return LHSTy; } if (RHSTy->isObjCClassType() && - (LHSTy.getDesugaredType() == Context.ObjCClassRedefinitionType)) { + (Context.hasSameType(LHSTy, Context.ObjCClassRedefinitionType))) { ImpCastExprToType(LHS, RHSTy, CK_BitCast); return RHSTy; } // And the same for struct objc_object* / id if (LHSTy->isObjCIdType() && - (RHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { + (Context.hasSameType(RHSTy, Context.ObjCIdRedefinitionType))) { ImpCastExprToType(RHS, LHSTy, CK_BitCast); return LHSTy; } if (RHSTy->isObjCIdType() && - (LHSTy.getDesugaredType() == Context.ObjCIdRedefinitionType)) { + (Context.hasSameType(LHSTy, Context.ObjCIdRedefinitionType))) { ImpCastExprToType(LHS, RHSTy, CK_BitCast); return RHSTy; } // And the same for struct objc_selector* / SEL if (Context.isObjCSelType(LHSTy) && - (RHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { + (Context.hasSameType(RHSTy, Context.ObjCSelRedefinitionType))) { ImpCastExprToType(RHS, LHSTy, CK_BitCast); return LHSTy; } if (Context.isObjCSelType(RHSTy) && - (LHSTy.getDesugaredType() == Context.ObjCSelRedefinitionType)) { + (Context.hasSameType(LHSTy, Context.ObjCSelRedefinitionType))) { ImpCastExprToType(LHS, RHSTy, CK_BitCast); return RHSTy; } @@ -5265,9 +5265,9 @@ Sema::CheckPointerTypesForAssignment(QualType lhsType, QualType rhsType) { QualType lhptee, rhptee; if ((lhsType->isObjCClassType() && - (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) || + (Context.hasSameType(rhsType, Context.ObjCClassRedefinitionType))) || (rhsType->isObjCClassType() && - (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) { + (Context.hasSameType(lhsType, Context.ObjCClassRedefinitionType)))) { return Compatible; } @@ -5471,9 +5471,9 @@ Sema::CheckAssignmentConstraints(QualType lhsType, Expr *&rhs, } if ((lhsType->isObjCClassType() && - (rhsType.getDesugaredType() == Context.ObjCClassRedefinitionType)) || + (Context.hasSameType(rhsType, Context.ObjCClassRedefinitionType))) || (rhsType->isObjCClassType() && - (lhsType.getDesugaredType() == Context.ObjCClassRedefinitionType))) { + (Context.hasSameType(lhsType, Context.ObjCClassRedefinitionType)))) { Kind = CK_BitCast; return Compatible; } diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 0ff8dc4ace..890854b897 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -5503,7 +5503,7 @@ Sema::AddBuiltinOperatorCandidates(OverloadedOperatorKind Op, if (!VisibleTypeConversionsQuals.hasRestrict() && T.isRestrictQualified()) continue; - T = Q1.apply(T); + T = Q1.apply(Context, T); QualType ResultTy = Context.getLValueReferenceType(T); AddBuiltinCandidate(ResultTy, ParamTypes, Args, 2, CandidateSet); } @@ -6075,9 +6075,9 @@ void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, // Param will have been canonicalized, but it should just be a // qualified version of ParamD, so move the qualifiers to that. - QualifierCollector Qs(S.Context); + QualifierCollector Qs; Qs.strip(Param); - QualType NonCanonParam = Qs.apply(TParam->getTypeForDecl()); + QualType NonCanonParam = Qs.apply(S.Context, TParam->getTypeForDecl()); assert(S.Context.hasSameType(Param, NonCanonParam)); // Arg has also been canonicalized, but there's nothing we can do diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index cac70ca7a8..6c212a7eb8 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -1144,7 +1144,7 @@ Sema::ActOnBlockReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { // part of the implementation spec. and not the actual qualifier for // the variable. if (CDRE->isConstQualAdded()) - CurBlock->ReturnType.removeConst(); + CurBlock->ReturnType.removeLocalConst(); // FIXME: local??? } } else CurBlock->ReturnType = Context.VoidTy; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5d3b75ede4..ad0d42a11a 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1354,8 +1354,8 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc, // // Following the existing practice of GNU and EDG, we allow a typedef of a // template specialization type. - if (const TypedefType *TT = dyn_cast(T)) - T = TT->LookThroughTypedefs().getTypePtr(); + while (const TypedefType *TT = dyn_cast(T)) + T = TT->getDecl()->getUnderlyingType().getTypePtr(); if (const TemplateSpecializationType *SpecType = dyn_cast(T)) { diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index c14acd62fe..da04b62198 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -464,7 +464,9 @@ DeduceTemplateArguments(Sema &S, assert(TemplateTypeParm->getDepth() == 0 && "Can't deduce with depth > 0"); assert(Arg != S.Context.OverloadTy && "Unresolved overloaded function"); QualType DeducedType = Arg; - DeducedType.removeCVRQualifiers(Param.getCVRQualifiers()); + + // local manipulation is okay because it's canonical + DeducedType.removeLocalCVRQualifiers(Param.getCVRQualifiers()); if (RecanonicalizeArg) DeducedType = S.Context.getCanonicalType(DeducedType); diff --git a/lib/Serialization/ASTCommon.h b/lib/Serialization/ASTCommon.h index 5ded8057e9..d4166998d1 100644 --- a/lib/Serialization/ASTCommon.h +++ b/lib/Serialization/ASTCommon.h @@ -34,7 +34,7 @@ TypeID MakeTypeID(QualType T, IdxForTypeTy IdxForType) { return PREDEF_TYPE_NULL_ID; unsigned FastQuals = T.getLocalFastQualifiers(); - T.removeFastQualifiers(); + T.removeLocalFastQualifiers(); if (T.hasLocalNonFastQualifiers()) return IdxForType(T).asTypeID(FastQuals); -- 2.40.0