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<const Type *, Qualifiers>.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121478 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp
index 9e46e87..dfdc505 100644
--- a/lib/AST/ASTContext.cpp
+++ b/lib/AST/ASTContext.cpp
@@ -1084,7 +1084,7 @@
     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 @@
   // 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<ArrayType>(Ty);
@@ -2854,7 +2854,7 @@
   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 321a139..8d5e408 100644
--- a/lib/AST/ASTDiagnostic.cpp
+++ b/lib/AST/ASTDiagnostic.cpp
@@ -101,7 +101,7 @@
                                                 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 60792bb..56bfa35 100644
--- a/lib/AST/StmtDumper.cpp
+++ b/lib/AST/StmtDumper.cpp
@@ -90,13 +90,14 @@
     }
 
     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 489f766..705b097 100644
--- a/lib/AST/Type.cpp
+++ b/lib/AST/Type.cpp
@@ -145,7 +145,12 @@
 /// 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 @@
     case Type::Class: { \
       const Class##Type *Ty = cast<Class##Type>(CurTy); \
       if (!Ty->isSugared()) \
-        return Qs.apply(Cur); \
+        return SplitQualType(Ty, Qs); \
       Cur = Ty->desugar(); \
       break; \
     }
@@ -1089,32 +1094,6 @@
           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<TypedefType>(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<TypedefType>(Qs.strip(CurType));
-  } while (TDT);
-
-  return Qs.apply(CurType);
-}
-
 QualType TypedefType::desugar() const {
   return getDecl()->getUnderlyingType();
 }
@@ -1280,20 +1259,18 @@
     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 5dfad6c..0e37acb 100644
--- a/lib/AST/TypePrinter.cpp
+++ b/lib/AST/TypePrinter.cpp
@@ -30,12 +30,13 @@
   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 @@
   }
 }
 
-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 @@
     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 @@
     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<CLASS##Type>(T.getTypePtr()), S);      \
+#define TYPE(CLASS, PARENT) case Type::CLASS: \
+    print##CLASS(cast<CLASS##Type>(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::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 @@
   if (isa<ArrayType>(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 @@
   if (isa<ArrayType>(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 @@
   if (isa<ArrayType>(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 @@
   if (isa<ArrayType>(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 @@
   }
   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 @@
   }
   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 @@
   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::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 @@
   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 @@
           S += ", ";
 
         std::string ExceptionType;
-        Print(T->getExceptionType(I), ExceptionType);
+        print(T->getExceptionType(I), ExceptionType);
         S += ExceptionType;
       }
     S += ")";
@@ -367,10 +372,10 @@
 
   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 @@
   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 @@
     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 @@
   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 @@
     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 @@
   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 @@
     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 @@
     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 @@
   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 @@
     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 @@
     S = MyString + ' ' + S;
 }
 
-void TypePrinter::PrintDependentTemplateSpecialization(
+void TypePrinter::printDependentTemplateSpecialization(
         const DependentTemplateSpecializationType *T, std::string &S) { 
   std::string MyString;
   {
@@ -657,7 +662,7 @@
     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 @@
   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 @@
   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 @@
   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 @@
     
     // 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 @@
     
     // 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 @@
   }
 }
 
-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);
 }