xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/ASTDiagnostic.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements a diagnostic formatting hook for AST elements.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/AST/ASTDiagnostic.h"
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTLambda.h"
160b57cec5SDimitry Andric #include "clang/AST/Attr.h"
170b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclTemplate.h"
190b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
200b57cec5SDimitry Andric #include "clang/AST/TemplateBase.h"
210b57cec5SDimitry Andric #include "clang/AST/Type.h"
22fe6060f1SDimitry Andric #include "llvm/ADT/StringExtras.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric using namespace clang;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric // Returns a desugared version of the QualType, and marks ShouldAKA as true
2806c3fb27SDimitry Andric // whenever we remove significant sugar from the type. Make sure ShouldAKA
2906c3fb27SDimitry Andric // is initialized before passing it in.
300eae32dcSDimitry Andric QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
310eae32dcSDimitry Andric                                      bool &ShouldAKA) {
320b57cec5SDimitry Andric   QualifierCollector QC;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   while (true) {
350b57cec5SDimitry Andric     const Type *Ty = QC.strip(QT);
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric     // Don't aka just because we saw an elaborated type...
380b57cec5SDimitry Andric     if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) {
390b57cec5SDimitry Andric       QT = ET->desugar();
400b57cec5SDimitry Andric       continue;
410b57cec5SDimitry Andric     }
420eae32dcSDimitry Andric     // ... or a using type ...
430eae32dcSDimitry Andric     if (const UsingType *UT = dyn_cast<UsingType>(Ty)) {
440eae32dcSDimitry Andric       QT = UT->desugar();
450eae32dcSDimitry Andric       continue;
460eae32dcSDimitry Andric     }
470b57cec5SDimitry Andric     // ... or a paren type ...
480b57cec5SDimitry Andric     if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
490b57cec5SDimitry Andric       QT = PT->desugar();
500b57cec5SDimitry Andric       continue;
510b57cec5SDimitry Andric     }
520b57cec5SDimitry Andric     // ... or a macro defined type ...
530b57cec5SDimitry Andric     if (const MacroQualifiedType *MDT = dyn_cast<MacroQualifiedType>(Ty)) {
540b57cec5SDimitry Andric       QT = MDT->desugar();
550b57cec5SDimitry Andric       continue;
560b57cec5SDimitry Andric     }
570b57cec5SDimitry Andric     // ...or a substituted template type parameter ...
580b57cec5SDimitry Andric     if (const SubstTemplateTypeParmType *ST =
590b57cec5SDimitry Andric           dyn_cast<SubstTemplateTypeParmType>(Ty)) {
600b57cec5SDimitry Andric       QT = ST->desugar();
610b57cec5SDimitry Andric       continue;
620b57cec5SDimitry Andric     }
630b57cec5SDimitry Andric     // ...or an attributed type...
640b57cec5SDimitry Andric     if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) {
650b57cec5SDimitry Andric       QT = AT->desugar();
660b57cec5SDimitry Andric       continue;
670b57cec5SDimitry Andric     }
680b57cec5SDimitry Andric     // ...or an adjusted type...
690b57cec5SDimitry Andric     if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) {
700b57cec5SDimitry Andric       QT = AT->desugar();
710b57cec5SDimitry Andric       continue;
720b57cec5SDimitry Andric     }
730b57cec5SDimitry Andric     // ... or an auto type.
740b57cec5SDimitry Andric     if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
750b57cec5SDimitry Andric       if (!AT->isSugared())
760b57cec5SDimitry Andric         break;
770b57cec5SDimitry Andric       QT = AT->desugar();
780b57cec5SDimitry Andric       continue;
790b57cec5SDimitry Andric     }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric     // Desugar FunctionType if return type or any parameter type should be
820b57cec5SDimitry Andric     // desugared. Preserve nullability attribute on desugared types.
830b57cec5SDimitry Andric     if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) {
840b57cec5SDimitry Andric       bool DesugarReturn = false;
850b57cec5SDimitry Andric       QualType SugarRT = FT->getReturnType();
860eae32dcSDimitry Andric       QualType RT = desugarForDiagnostic(Context, SugarRT, DesugarReturn);
870b57cec5SDimitry Andric       if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {
880b57cec5SDimitry Andric         RT = Context.getAttributedType(
890b57cec5SDimitry Andric             AttributedType::getNullabilityAttrKind(*nullability), RT, RT);
900b57cec5SDimitry Andric       }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric       bool DesugarArgument = false;
930b57cec5SDimitry Andric       SmallVector<QualType, 4> Args;
940b57cec5SDimitry Andric       const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);
950b57cec5SDimitry Andric       if (FPT) {
960b57cec5SDimitry Andric         for (QualType SugarPT : FPT->param_types()) {
970eae32dcSDimitry Andric           QualType PT = desugarForDiagnostic(Context, SugarPT, DesugarArgument);
980b57cec5SDimitry Andric           if (auto nullability =
990b57cec5SDimitry Andric                   AttributedType::stripOuterNullability(SugarPT)) {
1000b57cec5SDimitry Andric             PT = Context.getAttributedType(
1010b57cec5SDimitry Andric                 AttributedType::getNullabilityAttrKind(*nullability), PT, PT);
1020b57cec5SDimitry Andric           }
1030b57cec5SDimitry Andric           Args.push_back(PT);
1040b57cec5SDimitry Andric         }
1050b57cec5SDimitry Andric       }
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric       if (DesugarReturn || DesugarArgument) {
1080b57cec5SDimitry Andric         ShouldAKA = true;
1090b57cec5SDimitry Andric         QT = FPT ? Context.getFunctionType(RT, Args, FPT->getExtProtoInfo())
1100b57cec5SDimitry Andric                  : Context.getFunctionNoProtoType(RT, FT->getExtInfo());
1110b57cec5SDimitry Andric         break;
1120b57cec5SDimitry Andric       }
1130b57cec5SDimitry Andric     }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric     // Desugar template specializations if any template argument should be
1160b57cec5SDimitry Andric     // desugared.
1170b57cec5SDimitry Andric     if (const TemplateSpecializationType *TST =
1180b57cec5SDimitry Andric             dyn_cast<TemplateSpecializationType>(Ty)) {
1190b57cec5SDimitry Andric       if (!TST->isTypeAlias()) {
1200b57cec5SDimitry Andric         bool DesugarArgument = false;
1210b57cec5SDimitry Andric         SmallVector<TemplateArgument, 4> Args;
122bdd1243dSDimitry Andric         for (const TemplateArgument &Arg : TST->template_arguments()) {
1230b57cec5SDimitry Andric           if (Arg.getKind() == TemplateArgument::Type)
1240eae32dcSDimitry Andric             Args.push_back(desugarForDiagnostic(Context, Arg.getAsType(),
1250eae32dcSDimitry Andric                                                 DesugarArgument));
1260b57cec5SDimitry Andric           else
1270b57cec5SDimitry Andric             Args.push_back(Arg);
1280b57cec5SDimitry Andric         }
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric         if (DesugarArgument) {
1310b57cec5SDimitry Andric           ShouldAKA = true;
1320b57cec5SDimitry Andric           QT = Context.getTemplateSpecializationType(
1330b57cec5SDimitry Andric               TST->getTemplateName(), Args, QT);
1340b57cec5SDimitry Andric         }
1350b57cec5SDimitry Andric         break;
1360b57cec5SDimitry Andric       }
1370b57cec5SDimitry Andric     }
1380b57cec5SDimitry Andric 
1390eae32dcSDimitry Andric     if (const auto *AT = dyn_cast<ArrayType>(Ty)) {
1400eae32dcSDimitry Andric       QualType ElementTy =
1410eae32dcSDimitry Andric           desugarForDiagnostic(Context, AT->getElementType(), ShouldAKA);
1420eae32dcSDimitry Andric       if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
1430eae32dcSDimitry Andric         QT = Context.getConstantArrayType(
1440eae32dcSDimitry Andric             ElementTy, CAT->getSize(), CAT->getSizeExpr(),
1450eae32dcSDimitry Andric             CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());
1460eae32dcSDimitry Andric       else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
1470eae32dcSDimitry Andric         QT = Context.getVariableArrayType(
1480eae32dcSDimitry Andric             ElementTy, VAT->getSizeExpr(), VAT->getSizeModifier(),
1490eae32dcSDimitry Andric             VAT->getIndexTypeCVRQualifiers(), VAT->getBracketsRange());
1500eae32dcSDimitry Andric       else if (const auto *DSAT = dyn_cast<DependentSizedArrayType>(AT))
1510eae32dcSDimitry Andric         QT = Context.getDependentSizedArrayType(
1520eae32dcSDimitry Andric             ElementTy, DSAT->getSizeExpr(), DSAT->getSizeModifier(),
1530eae32dcSDimitry Andric             DSAT->getIndexTypeCVRQualifiers(), DSAT->getBracketsRange());
1540eae32dcSDimitry Andric       else if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT))
1550eae32dcSDimitry Andric         QT = Context.getIncompleteArrayType(ElementTy, IAT->getSizeModifier(),
1560eae32dcSDimitry Andric                                             IAT->getIndexTypeCVRQualifiers());
1570eae32dcSDimitry Andric       else
1580eae32dcSDimitry Andric         llvm_unreachable("Unhandled array type");
1590eae32dcSDimitry Andric       break;
1600eae32dcSDimitry Andric     }
1610eae32dcSDimitry Andric 
1620b57cec5SDimitry Andric     // Don't desugar magic Objective-C types.
1630b57cec5SDimitry Andric     if (QualType(Ty,0) == Context.getObjCIdType() ||
1640b57cec5SDimitry Andric         QualType(Ty,0) == Context.getObjCClassType() ||
1650b57cec5SDimitry Andric         QualType(Ty,0) == Context.getObjCSelType() ||
1660b57cec5SDimitry Andric         QualType(Ty,0) == Context.getObjCProtoType())
1670b57cec5SDimitry Andric       break;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric     // Don't desugar va_list.
1700b57cec5SDimitry Andric     if (QualType(Ty, 0) == Context.getBuiltinVaListType() ||
1710b57cec5SDimitry Andric         QualType(Ty, 0) == Context.getBuiltinMSVaListType())
1720b57cec5SDimitry Andric       break;
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric     // Otherwise, do a single-step desugar.
1750b57cec5SDimitry Andric     QualType Underlying;
1760b57cec5SDimitry Andric     bool IsSugar = false;
1770b57cec5SDimitry Andric     switch (Ty->getTypeClass()) {
1780b57cec5SDimitry Andric #define ABSTRACT_TYPE(Class, Base)
1790b57cec5SDimitry Andric #define TYPE(Class, Base) \
1800b57cec5SDimitry Andric case Type::Class: { \
1810b57cec5SDimitry Andric const Class##Type *CTy = cast<Class##Type>(Ty); \
1820b57cec5SDimitry Andric if (CTy->isSugared()) { \
1830b57cec5SDimitry Andric IsSugar = true; \
1840b57cec5SDimitry Andric Underlying = CTy->desugar(); \
1850b57cec5SDimitry Andric } \
1860b57cec5SDimitry Andric break; \
1870b57cec5SDimitry Andric }
188a7dea167SDimitry Andric #include "clang/AST/TypeNodes.inc"
1890b57cec5SDimitry Andric     }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric     // If it wasn't sugared, we're done.
1920b57cec5SDimitry Andric     if (!IsSugar)
1930b57cec5SDimitry Andric       break;
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric     // If the desugared type is a vector type, we don't want to expand
1960b57cec5SDimitry Andric     // it, it will turn into an attribute mess. People want their "vec4".
1970b57cec5SDimitry Andric     if (isa<VectorType>(Underlying))
1980b57cec5SDimitry Andric       break;
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric     // Don't desugar through the primary typedef of an anonymous type.
2010b57cec5SDimitry Andric     if (const TagType *UTT = Underlying->getAs<TagType>())
2020b57cec5SDimitry Andric       if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))
2030b57cec5SDimitry Andric         if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
2040b57cec5SDimitry Andric           break;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric     // Record that we actually looked through an opaque type here.
2070b57cec5SDimitry Andric     ShouldAKA = true;
2080b57cec5SDimitry Andric     QT = Underlying;
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   // If we have a pointer-like type, desugar the pointee as well.
2120b57cec5SDimitry Andric   // FIXME: Handle other pointer-like types.
2130b57cec5SDimitry Andric   if (const PointerType *Ty = QT->getAs<PointerType>()) {
2140eae32dcSDimitry Andric     QT = Context.getPointerType(
2150eae32dcSDimitry Andric         desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));
2160b57cec5SDimitry Andric   } else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) {
2170eae32dcSDimitry Andric     QT = Context.getObjCObjectPointerType(
2180eae32dcSDimitry Andric         desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));
2190b57cec5SDimitry Andric   } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
2200eae32dcSDimitry Andric     QT = Context.getLValueReferenceType(
2210eae32dcSDimitry Andric         desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));
2220b57cec5SDimitry Andric   } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
2230eae32dcSDimitry Andric     QT = Context.getRValueReferenceType(
2240eae32dcSDimitry Andric         desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));
2250b57cec5SDimitry Andric   } else if (const auto *Ty = QT->getAs<ObjCObjectType>()) {
2260b57cec5SDimitry Andric     if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {
2270eae32dcSDimitry Andric       QualType BaseType =
2280eae32dcSDimitry Andric           desugarForDiagnostic(Context, Ty->getBaseType(), ShouldAKA);
2290eae32dcSDimitry Andric       QT = Context.getObjCObjectType(
2300eae32dcSDimitry Andric           BaseType, Ty->getTypeArgsAsWritten(),
231bdd1243dSDimitry Andric           llvm::ArrayRef(Ty->qual_begin(), Ty->getNumProtocols()),
2320b57cec5SDimitry Andric           Ty->isKindOfTypeAsWritten());
2330b57cec5SDimitry Andric     }
2340b57cec5SDimitry Andric   }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   return QC.apply(Context, QT);
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric /// Convert the given type to a string suitable for printing as part of
2400b57cec5SDimitry Andric /// a diagnostic.
2410b57cec5SDimitry Andric ///
2420b57cec5SDimitry Andric /// There are four main criteria when determining whether we should have an
2430b57cec5SDimitry Andric /// a.k.a. clause when pretty-printing a type:
2440b57cec5SDimitry Andric ///
2450b57cec5SDimitry Andric /// 1) Some types provide very minimal sugar that doesn't impede the
2460b57cec5SDimitry Andric ///    user's understanding --- for example, elaborated type
2470b57cec5SDimitry Andric ///    specifiers.  If this is all the sugar we see, we don't want an
2480b57cec5SDimitry Andric ///    a.k.a. clause.
2490b57cec5SDimitry Andric /// 2) Some types are technically sugared but are much more familiar
2500b57cec5SDimitry Andric ///    when seen in their sugared form --- for example, va_list,
2510b57cec5SDimitry Andric ///    vector types, and the magic Objective C types.  We don't
2520b57cec5SDimitry Andric ///    want to desugar these, even if we do produce an a.k.a. clause.
2530b57cec5SDimitry Andric /// 3) Some types may have already been desugared previously in this diagnostic.
2540b57cec5SDimitry Andric ///    if this is the case, doing another "aka" would just be clutter.
2550b57cec5SDimitry Andric /// 4) Two different types within the same diagnostic have the same output
2560b57cec5SDimitry Andric ///    string.  In this case, force an a.k.a with the desugared type when
2570b57cec5SDimitry Andric ///    doing so will provide additional information.
2580b57cec5SDimitry Andric ///
2590b57cec5SDimitry Andric /// \param Context the context in which the type was allocated
2600b57cec5SDimitry Andric /// \param Ty the type to print
2610b57cec5SDimitry Andric /// \param QualTypeVals pointer values to QualTypes which are used in the
2620b57cec5SDimitry Andric /// diagnostic message
2630b57cec5SDimitry Andric static std::string
2640b57cec5SDimitry Andric ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
2650b57cec5SDimitry Andric                             ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
2660b57cec5SDimitry Andric                             ArrayRef<intptr_t> QualTypeVals) {
2670b57cec5SDimitry Andric   // FIXME: Playing with std::string is really slow.
2680b57cec5SDimitry Andric   bool ForceAKA = false;
2690b57cec5SDimitry Andric   QualType CanTy = Ty.getCanonicalType();
2700b57cec5SDimitry Andric   std::string S = Ty.getAsString(Context.getPrintingPolicy());
2710b57cec5SDimitry Andric   std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());
2720b57cec5SDimitry Andric 
27381ad6265SDimitry Andric   for (const intptr_t &QualTypeVal : QualTypeVals) {
2740b57cec5SDimitry Andric     QualType CompareTy =
27581ad6265SDimitry Andric         QualType::getFromOpaquePtr(reinterpret_cast<void *>(QualTypeVal));
2760b57cec5SDimitry Andric     if (CompareTy.isNull())
2770b57cec5SDimitry Andric       continue;
2780b57cec5SDimitry Andric     if (CompareTy == Ty)
2790b57cec5SDimitry Andric       continue;  // Same types
2800b57cec5SDimitry Andric     QualType CompareCanTy = CompareTy.getCanonicalType();
2810b57cec5SDimitry Andric     if (CompareCanTy == CanTy)
2820b57cec5SDimitry Andric       continue;  // Same canonical types
2830b57cec5SDimitry Andric     std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
2840b57cec5SDimitry Andric     bool ShouldAKA = false;
2850eae32dcSDimitry Andric     QualType CompareDesugar =
2860eae32dcSDimitry Andric         desugarForDiagnostic(Context, CompareTy, ShouldAKA);
2870b57cec5SDimitry Andric     std::string CompareDesugarStr =
2880b57cec5SDimitry Andric         CompareDesugar.getAsString(Context.getPrintingPolicy());
2890b57cec5SDimitry Andric     if (CompareS != S && CompareDesugarStr != S)
2900b57cec5SDimitry Andric       continue;  // The type string is different than the comparison string
2910b57cec5SDimitry Andric                  // and the desugared comparison string.
2920b57cec5SDimitry Andric     std::string CompareCanS =
2930b57cec5SDimitry Andric         CompareCanTy.getAsString(Context.getPrintingPolicy());
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric     if (CompareCanS == CanS)
2960b57cec5SDimitry Andric       continue;  // No new info from canonical type
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric     ForceAKA = true;
2990b57cec5SDimitry Andric     break;
3000b57cec5SDimitry Andric   }
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   // Check to see if we already desugared this type in this
3030b57cec5SDimitry Andric   // diagnostic.  If so, don't do it again.
3040b57cec5SDimitry Andric   bool Repeated = false;
30581ad6265SDimitry Andric   for (const auto &PrevArg : PrevArgs) {
3060b57cec5SDimitry Andric     // TODO: Handle ak_declcontext case.
30781ad6265SDimitry Andric     if (PrevArg.first == DiagnosticsEngine::ak_qualtype) {
30881ad6265SDimitry Andric       QualType PrevTy(
30981ad6265SDimitry Andric           QualType::getFromOpaquePtr(reinterpret_cast<void *>(PrevArg.second)));
3100b57cec5SDimitry Andric       if (PrevTy == Ty) {
3110b57cec5SDimitry Andric         Repeated = true;
3120b57cec5SDimitry Andric         break;
3130b57cec5SDimitry Andric       }
3140b57cec5SDimitry Andric     }
3150b57cec5SDimitry Andric   }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   // Consider producing an a.k.a. clause if removing all the direct
3180b57cec5SDimitry Andric   // sugar gives us something "significantly different".
3190b57cec5SDimitry Andric   if (!Repeated) {
3200b57cec5SDimitry Andric     bool ShouldAKA = false;
3210eae32dcSDimitry Andric     QualType DesugaredTy = desugarForDiagnostic(Context, Ty, ShouldAKA);
3220b57cec5SDimitry Andric     if (ShouldAKA || ForceAKA) {
3230b57cec5SDimitry Andric       if (DesugaredTy == Ty) {
3240b57cec5SDimitry Andric         DesugaredTy = Ty.getCanonicalType();
3250b57cec5SDimitry Andric       }
3260b57cec5SDimitry Andric       std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy());
3270b57cec5SDimitry Andric       if (akaStr != S) {
3280b57cec5SDimitry Andric         S = "'" + S + "' (aka '" + akaStr + "')";
3290b57cec5SDimitry Andric         return S;
3300b57cec5SDimitry Andric       }
3310b57cec5SDimitry Andric     }
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric     // Give some additional info on vector types. These are either not desugared
3340b57cec5SDimitry Andric     // or displaying complex __attribute__ expressions so add details of the
3350b57cec5SDimitry Andric     // type and element count.
336480093f4SDimitry Andric     if (const auto *VTy = Ty->getAs<VectorType>()) {
3370b57cec5SDimitry Andric       std::string DecoratedString;
3380b57cec5SDimitry Andric       llvm::raw_string_ostream OS(DecoratedString);
3390b57cec5SDimitry Andric       const char *Values = VTy->getNumElements() > 1 ? "values" : "value";
3400b57cec5SDimitry Andric       OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '"
3410b57cec5SDimitry Andric          << VTy->getElementType().getAsString(Context.getPrintingPolicy())
3420b57cec5SDimitry Andric          << "' " << Values << ")";
3430eae32dcSDimitry Andric       return DecoratedString;
3440b57cec5SDimitry Andric     }
3450b57cec5SDimitry Andric   }
3460b57cec5SDimitry Andric 
3470b57cec5SDimitry Andric   S = "'" + S + "'";
3480b57cec5SDimitry Andric   return S;
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
3520b57cec5SDimitry Andric                                    QualType ToType, bool PrintTree,
3530b57cec5SDimitry Andric                                    bool PrintFromType, bool ElideType,
3540b57cec5SDimitry Andric                                    bool ShowColors, raw_ostream &OS);
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric void clang::FormatASTNodeDiagnosticArgument(
3570b57cec5SDimitry Andric     DiagnosticsEngine::ArgumentKind Kind,
3580b57cec5SDimitry Andric     intptr_t Val,
3590b57cec5SDimitry Andric     StringRef Modifier,
3600b57cec5SDimitry Andric     StringRef Argument,
3610b57cec5SDimitry Andric     ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
3620b57cec5SDimitry Andric     SmallVectorImpl<char> &Output,
3630b57cec5SDimitry Andric     void *Cookie,
3640b57cec5SDimitry Andric     ArrayRef<intptr_t> QualTypeVals) {
3650b57cec5SDimitry Andric   ASTContext &Context = *static_cast<ASTContext*>(Cookie);
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   size_t OldEnd = Output.size();
3680b57cec5SDimitry Andric   llvm::raw_svector_ostream OS(Output);
3690b57cec5SDimitry Andric   bool NeedQuotes = true;
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric   switch (Kind) {
3720b57cec5SDimitry Andric     default: llvm_unreachable("unknown ArgumentKind");
373480093f4SDimitry Andric     case DiagnosticsEngine::ak_addrspace: {
374480093f4SDimitry Andric       assert(Modifier.empty() && Argument.empty() &&
37581ad6265SDimitry Andric              "Invalid modifier for Qualifiers argument");
376480093f4SDimitry Andric 
377480093f4SDimitry Andric       auto S = Qualifiers::getAddrSpaceAsString(static_cast<LangAS>(Val));
378480093f4SDimitry Andric       if (S.empty()) {
379480093f4SDimitry Andric         OS << (Context.getLangOpts().OpenCL ? "default" : "generic");
380480093f4SDimitry Andric         OS << " address space";
381480093f4SDimitry Andric       } else {
382480093f4SDimitry Andric         OS << "address space";
383480093f4SDimitry Andric         OS << " '" << S << "'";
384480093f4SDimitry Andric       }
385480093f4SDimitry Andric       NeedQuotes = false;
386480093f4SDimitry Andric       break;
387480093f4SDimitry Andric     }
3880b57cec5SDimitry Andric     case DiagnosticsEngine::ak_qual: {
3890b57cec5SDimitry Andric       assert(Modifier.empty() && Argument.empty() &&
39081ad6265SDimitry Andric              "Invalid modifier for Qualifiers argument");
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric       Qualifiers Q(Qualifiers::fromOpaqueValue(Val));
3930b57cec5SDimitry Andric       auto S = Q.getAsString();
3940b57cec5SDimitry Andric       if (S.empty()) {
3950b57cec5SDimitry Andric         OS << "unqualified";
3960b57cec5SDimitry Andric         NeedQuotes = false;
3970b57cec5SDimitry Andric       } else {
398480093f4SDimitry Andric         OS << S;
3990b57cec5SDimitry Andric       }
4000b57cec5SDimitry Andric       break;
4010b57cec5SDimitry Andric     }
4020b57cec5SDimitry Andric     case DiagnosticsEngine::ak_qualtype_pair: {
4030b57cec5SDimitry Andric       TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val);
4040b57cec5SDimitry Andric       QualType FromType =
4050b57cec5SDimitry Andric           QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType));
4060b57cec5SDimitry Andric       QualType ToType =
4070b57cec5SDimitry Andric           QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType));
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric       if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree,
4100b57cec5SDimitry Andric                                  TDT.PrintFromType, TDT.ElideType,
4110b57cec5SDimitry Andric                                  TDT.ShowColors, OS)) {
4120b57cec5SDimitry Andric         NeedQuotes = !TDT.PrintTree;
4130b57cec5SDimitry Andric         TDT.TemplateDiffUsed = true;
4140b57cec5SDimitry Andric         break;
4150b57cec5SDimitry Andric       }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric       // Don't fall-back during tree printing.  The caller will handle
4180b57cec5SDimitry Andric       // this case.
4190b57cec5SDimitry Andric       if (TDT.PrintTree)
4200b57cec5SDimitry Andric         return;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric       // Attempting to do a template diff on non-templates.  Set the variables
4230b57cec5SDimitry Andric       // and continue with regular type printing of the appropriate type.
4240b57cec5SDimitry Andric       Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType;
4250b57cec5SDimitry Andric       Modifier = StringRef();
4260b57cec5SDimitry Andric       Argument = StringRef();
4270b57cec5SDimitry Andric       // Fall through
428bdd1243dSDimitry Andric       [[fallthrough]];
4290b57cec5SDimitry Andric     }
4300b57cec5SDimitry Andric     case DiagnosticsEngine::ak_qualtype: {
4310b57cec5SDimitry Andric       assert(Modifier.empty() && Argument.empty() &&
4320b57cec5SDimitry Andric              "Invalid modifier for QualType argument");
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric       QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));
4350b57cec5SDimitry Andric       OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals);
4360b57cec5SDimitry Andric       NeedQuotes = false;
4370b57cec5SDimitry Andric       break;
4380b57cec5SDimitry Andric     }
4390b57cec5SDimitry Andric     case DiagnosticsEngine::ak_declarationname: {
4400b57cec5SDimitry Andric       if (Modifier == "objcclass" && Argument.empty())
4410b57cec5SDimitry Andric         OS << '+';
4420b57cec5SDimitry Andric       else if (Modifier == "objcinstance" && Argument.empty())
4430b57cec5SDimitry Andric         OS << '-';
4440b57cec5SDimitry Andric       else
4450b57cec5SDimitry Andric         assert(Modifier.empty() && Argument.empty() &&
4460b57cec5SDimitry Andric                "Invalid modifier for DeclarationName argument");
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric       OS << DeclarationName::getFromOpaqueInteger(Val);
4490b57cec5SDimitry Andric       break;
4500b57cec5SDimitry Andric     }
4510b57cec5SDimitry Andric     case DiagnosticsEngine::ak_nameddecl: {
4520b57cec5SDimitry Andric       bool Qualified;
4530b57cec5SDimitry Andric       if (Modifier == "q" && Argument.empty())
4540b57cec5SDimitry Andric         Qualified = true;
4550b57cec5SDimitry Andric       else {
4560b57cec5SDimitry Andric         assert(Modifier.empty() && Argument.empty() &&
4570b57cec5SDimitry Andric                "Invalid modifier for NamedDecl* argument");
4580b57cec5SDimitry Andric         Qualified = false;
4590b57cec5SDimitry Andric       }
4600b57cec5SDimitry Andric       const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val);
4610b57cec5SDimitry Andric       ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified);
4620b57cec5SDimitry Andric       break;
4630b57cec5SDimitry Andric     }
4640b57cec5SDimitry Andric     case DiagnosticsEngine::ak_nestednamespec: {
4650b57cec5SDimitry Andric       NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val);
4660b57cec5SDimitry Andric       NNS->print(OS, Context.getPrintingPolicy());
4670b57cec5SDimitry Andric       NeedQuotes = false;
4680b57cec5SDimitry Andric       break;
4690b57cec5SDimitry Andric     }
4700b57cec5SDimitry Andric     case DiagnosticsEngine::ak_declcontext: {
4710b57cec5SDimitry Andric       DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
4720b57cec5SDimitry Andric       assert(DC && "Should never have a null declaration context");
4730b57cec5SDimitry Andric       NeedQuotes = false;
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric       // FIXME: Get the strings for DeclContext from some localized place
4760b57cec5SDimitry Andric       if (DC->isTranslationUnit()) {
4770b57cec5SDimitry Andric         if (Context.getLangOpts().CPlusPlus)
4780b57cec5SDimitry Andric           OS << "the global namespace";
4790b57cec5SDimitry Andric         else
4800b57cec5SDimitry Andric           OS << "the global scope";
4810b57cec5SDimitry Andric       } else if (DC->isClosure()) {
4820b57cec5SDimitry Andric         OS << "block literal";
4830b57cec5SDimitry Andric       } else if (isLambdaCallOperator(DC)) {
4840b57cec5SDimitry Andric         OS << "lambda expression";
4850b57cec5SDimitry Andric       } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {
4860b57cec5SDimitry Andric         OS << ConvertTypeToDiagnosticString(Context,
4870b57cec5SDimitry Andric                                             Context.getTypeDeclType(Type),
4880b57cec5SDimitry Andric                                             PrevArgs, QualTypeVals);
4890b57cec5SDimitry Andric       } else {
4900b57cec5SDimitry Andric         assert(isa<NamedDecl>(DC) && "Expected a NamedDecl");
4910b57cec5SDimitry Andric         NamedDecl *ND = cast<NamedDecl>(DC);
4920b57cec5SDimitry Andric         if (isa<NamespaceDecl>(ND))
4930b57cec5SDimitry Andric           OS << "namespace ";
4940b57cec5SDimitry Andric         else if (isa<ObjCMethodDecl>(ND))
4950b57cec5SDimitry Andric           OS << "method ";
4960b57cec5SDimitry Andric         else if (isa<FunctionDecl>(ND))
4970b57cec5SDimitry Andric           OS << "function ";
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric         OS << '\'';
5000b57cec5SDimitry Andric         ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);
5010b57cec5SDimitry Andric         OS << '\'';
5020b57cec5SDimitry Andric       }
5030b57cec5SDimitry Andric       break;
5040b57cec5SDimitry Andric     }
5050b57cec5SDimitry Andric     case DiagnosticsEngine::ak_attr: {
5060b57cec5SDimitry Andric       const Attr *At = reinterpret_cast<Attr *>(Val);
5070b57cec5SDimitry Andric       assert(At && "Received null Attr object!");
5080b57cec5SDimitry Andric       OS << '\'' << At->getSpelling() << '\'';
5090b57cec5SDimitry Andric       NeedQuotes = false;
5100b57cec5SDimitry Andric       break;
5110b57cec5SDimitry Andric     }
5120b57cec5SDimitry Andric   }
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric   if (NeedQuotes) {
5150b57cec5SDimitry Andric     Output.insert(Output.begin()+OldEnd, '\'');
5160b57cec5SDimitry Andric     Output.push_back('\'');
5170b57cec5SDimitry Andric   }
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric /// TemplateDiff - A class that constructs a pretty string for a pair of
5210b57cec5SDimitry Andric /// QualTypes.  For the pair of types, a diff tree will be created containing
5220b57cec5SDimitry Andric /// all the information about the templates and template arguments.  Afterwards,
5230b57cec5SDimitry Andric /// the tree is transformed to a string according to the options passed in.
5240b57cec5SDimitry Andric namespace {
5250b57cec5SDimitry Andric class TemplateDiff {
5260b57cec5SDimitry Andric   /// Context - The ASTContext which is used for comparing template arguments.
5270b57cec5SDimitry Andric   ASTContext &Context;
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric   /// Policy - Used during expression printing.
5300b57cec5SDimitry Andric   PrintingPolicy Policy;
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   /// ElideType - Option to elide identical types.
5330b57cec5SDimitry Andric   bool ElideType;
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   /// PrintTree - Format output string as a tree.
5360b57cec5SDimitry Andric   bool PrintTree;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   /// ShowColor - Diagnostics support color, so bolding will be used.
5390b57cec5SDimitry Andric   bool ShowColor;
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   /// FromTemplateType - When single type printing is selected, this is the
542bdd1243dSDimitry Andric   /// type to be printed.  When tree printing is selected, this type will
5430b57cec5SDimitry Andric   /// show up first in the tree.
5440b57cec5SDimitry Andric   QualType FromTemplateType;
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   /// ToTemplateType - The type that FromType is compared to.  Only in tree
5470b57cec5SDimitry Andric   /// printing will this type be outputed.
5480b57cec5SDimitry Andric   QualType ToTemplateType;
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   /// OS - The stream used to construct the output strings.
5510b57cec5SDimitry Andric   raw_ostream &OS;
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric   /// IsBold - Keeps track of the bold formatting for the output string.
5540b57cec5SDimitry Andric   bool IsBold;
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   /// DiffTree - A tree representation the differences between two types.
5570b57cec5SDimitry Andric   class DiffTree {
5580b57cec5SDimitry Andric   public:
5590b57cec5SDimitry Andric     /// DiffKind - The difference in a DiffNode.  Fields of
5600b57cec5SDimitry Andric     /// TemplateArgumentInfo needed by each difference can be found in the
5610b57cec5SDimitry Andric     /// Set* and Get* functions.
5620b57cec5SDimitry Andric     enum DiffKind {
5630b57cec5SDimitry Andric       /// Incomplete or invalid node.
5640b57cec5SDimitry Andric       Invalid,
5650b57cec5SDimitry Andric       /// Another level of templates
5660b57cec5SDimitry Andric       Template,
5670b57cec5SDimitry Andric       /// Type difference, all type differences except those falling under
5680b57cec5SDimitry Andric       /// the Template difference.
5690b57cec5SDimitry Andric       Type,
5700b57cec5SDimitry Andric       /// Expression difference, this is only when both arguments are
5710b57cec5SDimitry Andric       /// expressions.  If one argument is an expression and the other is
5720b57cec5SDimitry Andric       /// Integer or Declaration, then use that diff type instead.
5730b57cec5SDimitry Andric       Expression,
5740b57cec5SDimitry Andric       /// Template argument difference
5750b57cec5SDimitry Andric       TemplateTemplate,
5760b57cec5SDimitry Andric       /// Integer difference
5770b57cec5SDimitry Andric       Integer,
5780b57cec5SDimitry Andric       /// Declaration difference, nullptr arguments are included here
5790b57cec5SDimitry Andric       Declaration,
5800b57cec5SDimitry Andric       /// One argument being integer and the other being declaration
5810b57cec5SDimitry Andric       FromIntegerAndToDeclaration,
5820b57cec5SDimitry Andric       FromDeclarationAndToInteger
5830b57cec5SDimitry Andric     };
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric   private:
5860b57cec5SDimitry Andric     /// TemplateArgumentInfo - All the information needed to pretty print
5870b57cec5SDimitry Andric     /// a template argument.  See the Set* and Get* functions to see which
5880b57cec5SDimitry Andric     /// fields are used for each DiffKind.
5890b57cec5SDimitry Andric     struct TemplateArgumentInfo {
5900b57cec5SDimitry Andric       QualType ArgType;
5910b57cec5SDimitry Andric       Qualifiers Qual;
5920b57cec5SDimitry Andric       llvm::APSInt Val;
5930b57cec5SDimitry Andric       bool IsValidInt = false;
5940b57cec5SDimitry Andric       Expr *ArgExpr = nullptr;
5950b57cec5SDimitry Andric       TemplateDecl *TD = nullptr;
5960b57cec5SDimitry Andric       ValueDecl *VD = nullptr;
5970b57cec5SDimitry Andric       bool NeedAddressOf = false;
5980b57cec5SDimitry Andric       bool IsNullPtr = false;
5990b57cec5SDimitry Andric       bool IsDefault = false;
6000b57cec5SDimitry Andric     };
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric     /// DiffNode - The root node stores the original type.  Each child node
6030b57cec5SDimitry Andric     /// stores template arguments of their parents.  For templated types, the
6040b57cec5SDimitry Andric     /// template decl is also stored.
6050b57cec5SDimitry Andric     struct DiffNode {
6060b57cec5SDimitry Andric       DiffKind Kind = Invalid;
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric       /// NextNode - The index of the next sibling node or 0.
6090b57cec5SDimitry Andric       unsigned NextNode = 0;
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric       /// ChildNode - The index of the first child node or 0.
6120b57cec5SDimitry Andric       unsigned ChildNode = 0;
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric       /// ParentNode - The index of the parent node.
6150b57cec5SDimitry Andric       unsigned ParentNode = 0;
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric       TemplateArgumentInfo FromArgInfo, ToArgInfo;
6180b57cec5SDimitry Andric 
6190b57cec5SDimitry Andric       /// Same - Whether the two arguments evaluate to the same value.
6200b57cec5SDimitry Andric       bool Same = false;
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric       DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {}
6230b57cec5SDimitry Andric     };
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric     /// FlatTree - A flattened tree used to store the DiffNodes.
6260b57cec5SDimitry Andric     SmallVector<DiffNode, 16> FlatTree;
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric     /// CurrentNode - The index of the current node being used.
6290b57cec5SDimitry Andric     unsigned CurrentNode;
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric     /// NextFreeNode - The index of the next unused node.  Used when creating
6320b57cec5SDimitry Andric     /// child nodes.
6330b57cec5SDimitry Andric     unsigned NextFreeNode;
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric     /// ReadNode - The index of the current node being read.
6360b57cec5SDimitry Andric     unsigned ReadNode;
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   public:
639480093f4SDimitry Andric     DiffTree() : CurrentNode(0), NextFreeNode(1), ReadNode(0) {
6400b57cec5SDimitry Andric       FlatTree.push_back(DiffNode());
6410b57cec5SDimitry Andric     }
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric     // Node writing functions, one for each valid DiffKind element.
6440b57cec5SDimitry Andric     void SetTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,
6450b57cec5SDimitry Andric                          Qualifiers FromQual, Qualifiers ToQual,
6460b57cec5SDimitry Andric                          bool FromDefault, bool ToDefault) {
6470b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
6480b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = Template;
6490b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
6500b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
6510b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.Qual = FromQual;
6520b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.Qual = ToQual;
6530b57cec5SDimitry Andric       SetDefault(FromDefault, ToDefault);
6540b57cec5SDimitry Andric     }
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric     void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault,
6570b57cec5SDimitry Andric                      bool ToDefault) {
6580b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
6590b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = Type;
6600b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.ArgType = FromType;
6610b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.ArgType = ToType;
6620b57cec5SDimitry Andric       SetDefault(FromDefault, ToDefault);
6630b57cec5SDimitry Andric     }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric     void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault,
6660b57cec5SDimitry Andric                            bool ToDefault) {
6670b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
6680b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = Expression;
6690b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
6700b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
6710b57cec5SDimitry Andric       SetDefault(FromDefault, ToDefault);
6720b57cec5SDimitry Andric     }
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric     void SetTemplateTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,
6750b57cec5SDimitry Andric                                  bool FromDefault, bool ToDefault) {
6760b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
6770b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = TemplateTemplate;
6780b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
6790b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
6800b57cec5SDimitry Andric       SetDefault(FromDefault, ToDefault);
6810b57cec5SDimitry Andric     }
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric     void SetIntegerDiff(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
6840b57cec5SDimitry Andric                         bool IsValidFromInt, bool IsValidToInt,
6850b57cec5SDimitry Andric                         QualType FromIntType, QualType ToIntType,
6860b57cec5SDimitry Andric                         Expr *FromExpr, Expr *ToExpr, bool FromDefault,
6870b57cec5SDimitry Andric                         bool ToDefault) {
6880b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
6890b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = Integer;
6900b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
6910b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
6920b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
6930b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
6940b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
6950b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
6960b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
6970b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
6980b57cec5SDimitry Andric       SetDefault(FromDefault, ToDefault);
6990b57cec5SDimitry Andric     }
7000b57cec5SDimitry Andric 
7010b57cec5SDimitry Andric     void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
7020b57cec5SDimitry Andric                             bool FromAddressOf, bool ToAddressOf,
7030b57cec5SDimitry Andric                             bool FromNullPtr, bool ToNullPtr, Expr *FromExpr,
7040b57cec5SDimitry Andric                             Expr *ToExpr, bool FromDefault, bool ToDefault) {
7050b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
7060b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = Declaration;
7070b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
7080b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
7090b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
7100b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
7110b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
7120b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
7130b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
7140b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
7150b57cec5SDimitry Andric       SetDefault(FromDefault, ToDefault);
7160b57cec5SDimitry Andric     }
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric     void SetFromDeclarationAndToIntegerDiff(
7190b57cec5SDimitry Andric         ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr,
7200b57cec5SDimitry Andric         Expr *FromExpr, const llvm::APSInt &ToInt, bool IsValidToInt,
7210b57cec5SDimitry Andric         QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) {
7220b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
7230b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger;
7240b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
7250b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
7260b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
7270b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
7280b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
7290b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
7300b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
7310b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
7320b57cec5SDimitry Andric       SetDefault(FromDefault, ToDefault);
7330b57cec5SDimitry Andric     }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric     void SetFromIntegerAndToDeclarationDiff(
7360b57cec5SDimitry Andric         const llvm::APSInt &FromInt, bool IsValidFromInt, QualType FromIntType,
7370b57cec5SDimitry Andric         Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf,
7380b57cec5SDimitry Andric         bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) {
7390b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
7400b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration;
7410b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
7420b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
7430b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
7440b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
7450b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
7460b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
7470b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
7480b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
7490b57cec5SDimitry Andric       SetDefault(FromDefault, ToDefault);
7500b57cec5SDimitry Andric     }
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric     /// SetDefault - Sets FromDefault and ToDefault flags of the current node.
7530b57cec5SDimitry Andric     void SetDefault(bool FromDefault, bool ToDefault) {
7540b57cec5SDimitry Andric       assert((!FromDefault || !ToDefault) && "Both arguments cannot be default.");
7550b57cec5SDimitry Andric       FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault;
7560b57cec5SDimitry Andric       FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault;
7570b57cec5SDimitry Andric     }
7580b57cec5SDimitry Andric 
7590b57cec5SDimitry Andric     /// SetSame - Sets the same flag of the current node.
7600b57cec5SDimitry Andric     void SetSame(bool Same) {
7610b57cec5SDimitry Andric       FlatTree[CurrentNode].Same = Same;
7620b57cec5SDimitry Andric     }
7630b57cec5SDimitry Andric 
7640b57cec5SDimitry Andric     /// SetKind - Sets the current node's type.
7650b57cec5SDimitry Andric     void SetKind(DiffKind Kind) {
7660b57cec5SDimitry Andric       FlatTree[CurrentNode].Kind = Kind;
7670b57cec5SDimitry Andric     }
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric     /// Up - Changes the node to the parent of the current node.
7700b57cec5SDimitry Andric     void Up() {
7710b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind != Invalid &&
7720b57cec5SDimitry Andric              "Cannot exit node before setting node information.");
7730b57cec5SDimitry Andric       CurrentNode = FlatTree[CurrentNode].ParentNode;
7740b57cec5SDimitry Andric     }
7750b57cec5SDimitry Andric 
7760b57cec5SDimitry Andric     /// AddNode - Adds a child node to the current node, then sets that node
7770b57cec5SDimitry Andric     /// node as the current node.
7780b57cec5SDimitry Andric     void AddNode() {
7790b57cec5SDimitry Andric       assert(FlatTree[CurrentNode].Kind == Template &&
7800b57cec5SDimitry Andric              "Only Template nodes can have children nodes.");
7810b57cec5SDimitry Andric       FlatTree.push_back(DiffNode(CurrentNode));
7820b57cec5SDimitry Andric       DiffNode &Node = FlatTree[CurrentNode];
7830b57cec5SDimitry Andric       if (Node.ChildNode == 0) {
7840b57cec5SDimitry Andric         // If a child node doesn't exist, add one.
7850b57cec5SDimitry Andric         Node.ChildNode = NextFreeNode;
7860b57cec5SDimitry Andric       } else {
7870b57cec5SDimitry Andric         // If a child node exists, find the last child node and add a
7880b57cec5SDimitry Andric         // next node to it.
7890b57cec5SDimitry Andric         unsigned i;
7900b57cec5SDimitry Andric         for (i = Node.ChildNode; FlatTree[i].NextNode != 0;
7910b57cec5SDimitry Andric              i = FlatTree[i].NextNode) {
7920b57cec5SDimitry Andric         }
7930b57cec5SDimitry Andric         FlatTree[i].NextNode = NextFreeNode;
7940b57cec5SDimitry Andric       }
7950b57cec5SDimitry Andric       CurrentNode = NextFreeNode;
7960b57cec5SDimitry Andric       ++NextFreeNode;
7970b57cec5SDimitry Andric     }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric     // Node reading functions.
8000b57cec5SDimitry Andric     /// StartTraverse - Prepares the tree for recursive traversal.
8010b57cec5SDimitry Andric     void StartTraverse() {
8020b57cec5SDimitry Andric       ReadNode = 0;
8030b57cec5SDimitry Andric       CurrentNode = NextFreeNode;
8040b57cec5SDimitry Andric       NextFreeNode = 0;
8050b57cec5SDimitry Andric     }
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric     /// Parent - Move the current read node to its parent.
8080b57cec5SDimitry Andric     void Parent() {
8090b57cec5SDimitry Andric       ReadNode = FlatTree[ReadNode].ParentNode;
8100b57cec5SDimitry Andric     }
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric     void GetTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD,
8130b57cec5SDimitry Andric                          Qualifiers &FromQual, Qualifiers &ToQual) {
8140b57cec5SDimitry Andric       assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind.");
8150b57cec5SDimitry Andric       FromTD = FlatTree[ReadNode].FromArgInfo.TD;
8160b57cec5SDimitry Andric       ToTD = FlatTree[ReadNode].ToArgInfo.TD;
8170b57cec5SDimitry Andric       FromQual = FlatTree[ReadNode].FromArgInfo.Qual;
8180b57cec5SDimitry Andric       ToQual = FlatTree[ReadNode].ToArgInfo.Qual;
8190b57cec5SDimitry Andric     }
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric     void GetTypeDiff(QualType &FromType, QualType &ToType) {
8220b57cec5SDimitry Andric       assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind");
8230b57cec5SDimitry Andric       FromType = FlatTree[ReadNode].FromArgInfo.ArgType;
8240b57cec5SDimitry Andric       ToType = FlatTree[ReadNode].ToArgInfo.ArgType;
8250b57cec5SDimitry Andric     }
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric     void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) {
8280b57cec5SDimitry Andric       assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind");
8290b57cec5SDimitry Andric       FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
8300b57cec5SDimitry Andric       ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
8310b57cec5SDimitry Andric     }
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric     void GetTemplateTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {
8340b57cec5SDimitry Andric       assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind.");
8350b57cec5SDimitry Andric       FromTD = FlatTree[ReadNode].FromArgInfo.TD;
8360b57cec5SDimitry Andric       ToTD = FlatTree[ReadNode].ToArgInfo.TD;
8370b57cec5SDimitry Andric     }
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric     void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
8400b57cec5SDimitry Andric                         bool &IsValidFromInt, bool &IsValidToInt,
8410b57cec5SDimitry Andric                         QualType &FromIntType, QualType &ToIntType,
8420b57cec5SDimitry Andric                         Expr *&FromExpr, Expr *&ToExpr) {
8430b57cec5SDimitry Andric       assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind.");
8440b57cec5SDimitry Andric       FromInt = FlatTree[ReadNode].FromArgInfo.Val;
8450b57cec5SDimitry Andric       ToInt = FlatTree[ReadNode].ToArgInfo.Val;
8460b57cec5SDimitry Andric       IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
8470b57cec5SDimitry Andric       IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
8480b57cec5SDimitry Andric       FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
8490b57cec5SDimitry Andric       ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
8500b57cec5SDimitry Andric       FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
8510b57cec5SDimitry Andric       ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
8520b57cec5SDimitry Andric     }
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric     void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
8550b57cec5SDimitry Andric                             bool &FromAddressOf, bool &ToAddressOf,
8560b57cec5SDimitry Andric                             bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr,
8570b57cec5SDimitry Andric                             Expr *&ToExpr) {
8580b57cec5SDimitry Andric       assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind.");
8590b57cec5SDimitry Andric       FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
8600b57cec5SDimitry Andric       ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
8610b57cec5SDimitry Andric       FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
8620b57cec5SDimitry Andric       ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
8630b57cec5SDimitry Andric       FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
8640b57cec5SDimitry Andric       ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
8650b57cec5SDimitry Andric       FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
8660b57cec5SDimitry Andric       ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
8670b57cec5SDimitry Andric     }
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric     void GetFromDeclarationAndToIntegerDiff(
8700b57cec5SDimitry Andric         ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr,
8710b57cec5SDimitry Andric         Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt,
8720b57cec5SDimitry Andric         QualType &ToIntType, Expr *&ToExpr) {
8730b57cec5SDimitry Andric       assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger &&
8740b57cec5SDimitry Andric              "Unexpected kind.");
8750b57cec5SDimitry Andric       FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
8760b57cec5SDimitry Andric       FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
8770b57cec5SDimitry Andric       FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
8780b57cec5SDimitry Andric       FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
8790b57cec5SDimitry Andric       ToInt = FlatTree[ReadNode].ToArgInfo.Val;
8800b57cec5SDimitry Andric       IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
8810b57cec5SDimitry Andric       ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
8820b57cec5SDimitry Andric       ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
8830b57cec5SDimitry Andric     }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric     void GetFromIntegerAndToDeclarationDiff(
8860b57cec5SDimitry Andric         llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType,
8870b57cec5SDimitry Andric         Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf,
8880b57cec5SDimitry Andric         bool &ToNullPtr, Expr *&ToExpr) {
8890b57cec5SDimitry Andric       assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration &&
8900b57cec5SDimitry Andric              "Unexpected kind.");
8910b57cec5SDimitry Andric       FromInt = FlatTree[ReadNode].FromArgInfo.Val;
8920b57cec5SDimitry Andric       IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
8930b57cec5SDimitry Andric       FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
8940b57cec5SDimitry Andric       FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
8950b57cec5SDimitry Andric       ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
8960b57cec5SDimitry Andric       ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
8970b57cec5SDimitry Andric       ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
8980b57cec5SDimitry Andric       ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
8990b57cec5SDimitry Andric     }
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric     /// FromDefault - Return true if the from argument is the default.
9020b57cec5SDimitry Andric     bool FromDefault() {
9030b57cec5SDimitry Andric       return FlatTree[ReadNode].FromArgInfo.IsDefault;
9040b57cec5SDimitry Andric     }
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric     /// ToDefault - Return true if the to argument is the default.
9070b57cec5SDimitry Andric     bool ToDefault() {
9080b57cec5SDimitry Andric       return FlatTree[ReadNode].ToArgInfo.IsDefault;
9090b57cec5SDimitry Andric     }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric     /// NodeIsSame - Returns true the arguments are the same.
9120b57cec5SDimitry Andric     bool NodeIsSame() {
9130b57cec5SDimitry Andric       return FlatTree[ReadNode].Same;
9140b57cec5SDimitry Andric     }
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric     /// HasChildrend - Returns true if the node has children.
9170b57cec5SDimitry Andric     bool HasChildren() {
9180b57cec5SDimitry Andric       return FlatTree[ReadNode].ChildNode != 0;
9190b57cec5SDimitry Andric     }
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric     /// MoveToChild - Moves from the current node to its child.
9220b57cec5SDimitry Andric     void MoveToChild() {
9230b57cec5SDimitry Andric       ReadNode = FlatTree[ReadNode].ChildNode;
9240b57cec5SDimitry Andric     }
9250b57cec5SDimitry Andric 
9260b57cec5SDimitry Andric     /// AdvanceSibling - If there is a next sibling, advance to it and return
9270b57cec5SDimitry Andric     /// true.  Otherwise, return false.
9280b57cec5SDimitry Andric     bool AdvanceSibling() {
9290b57cec5SDimitry Andric       if (FlatTree[ReadNode].NextNode == 0)
9300b57cec5SDimitry Andric         return false;
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric       ReadNode = FlatTree[ReadNode].NextNode;
9330b57cec5SDimitry Andric       return true;
9340b57cec5SDimitry Andric     }
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric     /// HasNextSibling - Return true if the node has a next sibling.
9370b57cec5SDimitry Andric     bool HasNextSibling() {
9380b57cec5SDimitry Andric       return FlatTree[ReadNode].NextNode != 0;
9390b57cec5SDimitry Andric     }
9400b57cec5SDimitry Andric 
9410b57cec5SDimitry Andric     /// Empty - Returns true if the tree has no information.
9420b57cec5SDimitry Andric     bool Empty() {
9430b57cec5SDimitry Andric       return GetKind() == Invalid;
9440b57cec5SDimitry Andric     }
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric     /// GetKind - Returns the current node's type.
9470b57cec5SDimitry Andric     DiffKind GetKind() {
9480b57cec5SDimitry Andric       return FlatTree[ReadNode].Kind;
9490b57cec5SDimitry Andric     }
9500b57cec5SDimitry Andric   };
9510b57cec5SDimitry Andric 
9520b57cec5SDimitry Andric   DiffTree Tree;
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric   /// TSTiterator - a pair of iterators that walks the
9550b57cec5SDimitry Andric   /// TemplateSpecializationType and the desugared TemplateSpecializationType.
9560b57cec5SDimitry Andric   /// The deseguared TemplateArgument should provide the canonical argument
9570b57cec5SDimitry Andric   /// for comparisons.
9580b57cec5SDimitry Andric   class TSTiterator {
9590b57cec5SDimitry Andric     typedef const TemplateArgument& reference;
9600b57cec5SDimitry Andric     typedef const TemplateArgument* pointer;
9610b57cec5SDimitry Andric 
9620b57cec5SDimitry Andric     /// InternalIterator - an iterator that is used to enter a
9630b57cec5SDimitry Andric     /// TemplateSpecializationType and read TemplateArguments inside template
9640b57cec5SDimitry Andric     /// parameter packs in order with the rest of the TemplateArguments.
9650b57cec5SDimitry Andric     struct InternalIterator {
9660b57cec5SDimitry Andric       /// TST - the template specialization whose arguments this iterator
9670b57cec5SDimitry Andric       /// traverse over.
9680b57cec5SDimitry Andric       const TemplateSpecializationType *TST;
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric       /// Index - the index of the template argument in TST.
9710b57cec5SDimitry Andric       unsigned Index;
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric       /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA
9740b57cec5SDimitry Andric       /// points to a TemplateArgument within a parameter pack.
9750b57cec5SDimitry Andric       TemplateArgument::pack_iterator CurrentTA;
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric       /// EndTA - the end iterator of a parameter pack
9780b57cec5SDimitry Andric       TemplateArgument::pack_iterator EndTA;
9790b57cec5SDimitry Andric 
9800b57cec5SDimitry Andric       /// InternalIterator - Constructs an iterator and sets it to the first
9810b57cec5SDimitry Andric       /// template argument.
9820b57cec5SDimitry Andric       InternalIterator(const TemplateSpecializationType *TST)
9830b57cec5SDimitry Andric           : TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) {
9840b57cec5SDimitry Andric         if (!TST) return;
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric         if (isEnd()) return;
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric         // Set to first template argument.  If not a parameter pack, done.
989bdd1243dSDimitry Andric         TemplateArgument TA = TST->template_arguments()[0];
9900b57cec5SDimitry Andric         if (TA.getKind() != TemplateArgument::Pack) return;
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric         // Start looking into the parameter pack.
9930b57cec5SDimitry Andric         CurrentTA = TA.pack_begin();
9940b57cec5SDimitry Andric         EndTA = TA.pack_end();
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric         // Found a valid template argument.
9970b57cec5SDimitry Andric         if (CurrentTA != EndTA) return;
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric         // Parameter pack is empty, use the increment to get to a valid
10000b57cec5SDimitry Andric         // template argument.
10010b57cec5SDimitry Andric         ++(*this);
10020b57cec5SDimitry Andric       }
10030b57cec5SDimitry Andric 
10040b57cec5SDimitry Andric       /// Return true if the iterator is non-singular.
10050b57cec5SDimitry Andric       bool isValid() const { return TST; }
10060b57cec5SDimitry Andric 
10070b57cec5SDimitry Andric       /// isEnd - Returns true if the iterator is one past the end.
10080b57cec5SDimitry Andric       bool isEnd() const {
10090b57cec5SDimitry Andric         assert(TST && "InternalIterator is invalid with a null TST.");
1010bdd1243dSDimitry Andric         return Index >= TST->template_arguments().size();
10110b57cec5SDimitry Andric       }
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric       /// &operator++ - Increment the iterator to the next template argument.
10140b57cec5SDimitry Andric       InternalIterator &operator++() {
10150b57cec5SDimitry Andric         assert(TST && "InternalIterator is invalid with a null TST.");
10160b57cec5SDimitry Andric         if (isEnd()) {
10170b57cec5SDimitry Andric           return *this;
10180b57cec5SDimitry Andric         }
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric         // If in a parameter pack, advance in the parameter pack.
10210b57cec5SDimitry Andric         if (CurrentTA != EndTA) {
10220b57cec5SDimitry Andric           ++CurrentTA;
10230b57cec5SDimitry Andric           if (CurrentTA != EndTA)
10240b57cec5SDimitry Andric             return *this;
10250b57cec5SDimitry Andric         }
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric         // Loop until a template argument is found, or the end is reached.
10280b57cec5SDimitry Andric         while (true) {
10290b57cec5SDimitry Andric           // Advance to the next template argument.  Break if reached the end.
1030bdd1243dSDimitry Andric           if (++Index == TST->template_arguments().size())
10310b57cec5SDimitry Andric             break;
10320b57cec5SDimitry Andric 
10330b57cec5SDimitry Andric           // If the TemplateArgument is not a parameter pack, done.
1034bdd1243dSDimitry Andric           TemplateArgument TA = TST->template_arguments()[Index];
10350b57cec5SDimitry Andric           if (TA.getKind() != TemplateArgument::Pack)
10360b57cec5SDimitry Andric             break;
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric           // Handle parameter packs.
10390b57cec5SDimitry Andric           CurrentTA = TA.pack_begin();
10400b57cec5SDimitry Andric           EndTA = TA.pack_end();
10410b57cec5SDimitry Andric 
10420b57cec5SDimitry Andric           // If the parameter pack is empty, try to advance again.
10430b57cec5SDimitry Andric           if (CurrentTA != EndTA)
10440b57cec5SDimitry Andric             break;
10450b57cec5SDimitry Andric         }
10460b57cec5SDimitry Andric         return *this;
10470b57cec5SDimitry Andric       }
10480b57cec5SDimitry Andric 
10490b57cec5SDimitry Andric       /// operator* - Returns the appropriate TemplateArgument.
10500b57cec5SDimitry Andric       reference operator*() const {
10510b57cec5SDimitry Andric         assert(TST && "InternalIterator is invalid with a null TST.");
10520b57cec5SDimitry Andric         assert(!isEnd() && "Index exceeds number of arguments.");
10530b57cec5SDimitry Andric         if (CurrentTA == EndTA)
1054bdd1243dSDimitry Andric           return TST->template_arguments()[Index];
10550b57cec5SDimitry Andric         else
10560b57cec5SDimitry Andric           return *CurrentTA;
10570b57cec5SDimitry Andric       }
10580b57cec5SDimitry Andric 
10590b57cec5SDimitry Andric       /// operator-> - Allow access to the underlying TemplateArgument.
10600b57cec5SDimitry Andric       pointer operator->() const {
10610b57cec5SDimitry Andric         assert(TST && "InternalIterator is invalid with a null TST.");
10620b57cec5SDimitry Andric         return &operator*();
10630b57cec5SDimitry Andric       }
10640b57cec5SDimitry Andric     };
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric     InternalIterator SugaredIterator;
10670b57cec5SDimitry Andric     InternalIterator DesugaredIterator;
10680b57cec5SDimitry Andric 
10690b57cec5SDimitry Andric   public:
10700b57cec5SDimitry Andric     TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
10710b57cec5SDimitry Andric         : SugaredIterator(TST),
10720b57cec5SDimitry Andric           DesugaredIterator(
10730b57cec5SDimitry Andric               (TST->isSugared() && !TST->isTypeAlias())
10740b57cec5SDimitry Andric                   ? GetTemplateSpecializationType(Context, TST->desugar())
10750b57cec5SDimitry Andric                   : nullptr) {}
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric     /// &operator++ - Increment the iterator to the next template argument.
10780b57cec5SDimitry Andric     TSTiterator &operator++() {
10790b57cec5SDimitry Andric       ++SugaredIterator;
10800b57cec5SDimitry Andric       if (DesugaredIterator.isValid())
10810b57cec5SDimitry Andric         ++DesugaredIterator;
10820b57cec5SDimitry Andric       return *this;
10830b57cec5SDimitry Andric     }
10840b57cec5SDimitry Andric 
10850b57cec5SDimitry Andric     /// operator* - Returns the appropriate TemplateArgument.
10860b57cec5SDimitry Andric     reference operator*() const {
10870b57cec5SDimitry Andric       return *SugaredIterator;
10880b57cec5SDimitry Andric     }
10890b57cec5SDimitry Andric 
10900b57cec5SDimitry Andric     /// operator-> - Allow access to the underlying TemplateArgument.
10910b57cec5SDimitry Andric     pointer operator->() const {
10920b57cec5SDimitry Andric       return &operator*();
10930b57cec5SDimitry Andric     }
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric     /// isEnd - Returns true if no more TemplateArguments are available.
10960b57cec5SDimitry Andric     bool isEnd() const {
10970b57cec5SDimitry Andric       return SugaredIterator.isEnd();
10980b57cec5SDimitry Andric     }
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric     /// hasDesugaredTA - Returns true if there is another TemplateArgument
11010b57cec5SDimitry Andric     /// available.
11020b57cec5SDimitry Andric     bool hasDesugaredTA() const {
11030b57cec5SDimitry Andric       return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();
11040b57cec5SDimitry Andric     }
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric     /// getDesugaredTA - Returns the desugared TemplateArgument.
11070b57cec5SDimitry Andric     reference getDesugaredTA() const {
11080b57cec5SDimitry Andric       assert(DesugaredIterator.isValid() &&
11090b57cec5SDimitry Andric              "Desugared TemplateArgument should not be used.");
11100b57cec5SDimitry Andric       return *DesugaredIterator;
11110b57cec5SDimitry Andric     }
11120b57cec5SDimitry Andric   };
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric   // These functions build up the template diff tree, including functions to
11150b57cec5SDimitry Andric   // retrieve and compare template arguments.
11160b57cec5SDimitry Andric 
11170b57cec5SDimitry Andric   static const TemplateSpecializationType *GetTemplateSpecializationType(
11180b57cec5SDimitry Andric       ASTContext &Context, QualType Ty) {
11190b57cec5SDimitry Andric     if (const TemplateSpecializationType *TST =
11200b57cec5SDimitry Andric             Ty->getAs<TemplateSpecializationType>())
11210b57cec5SDimitry Andric       return TST;
11220b57cec5SDimitry Andric 
1123349cc55cSDimitry Andric     if (const auto* SubstType = Ty->getAs<SubstTemplateTypeParmType>())
1124349cc55cSDimitry Andric       Ty = SubstType->getReplacementType();
1125349cc55cSDimitry Andric 
11260b57cec5SDimitry Andric     const RecordType *RT = Ty->getAs<RecordType>();
11270b57cec5SDimitry Andric 
11280b57cec5SDimitry Andric     if (!RT)
11290b57cec5SDimitry Andric       return nullptr;
11300b57cec5SDimitry Andric 
11310b57cec5SDimitry Andric     const ClassTemplateSpecializationDecl *CTSD =
11320b57cec5SDimitry Andric         dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric     if (!CTSD)
11350b57cec5SDimitry Andric       return nullptr;
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric     Ty = Context.getTemplateSpecializationType(
11380b57cec5SDimitry Andric              TemplateName(CTSD->getSpecializedTemplate()),
11390b57cec5SDimitry Andric              CTSD->getTemplateArgs().asArray(),
11400b57cec5SDimitry Andric              Ty.getLocalUnqualifiedType().getCanonicalType());
11410b57cec5SDimitry Andric 
11420b57cec5SDimitry Andric     return Ty->getAs<TemplateSpecializationType>();
11430b57cec5SDimitry Andric   }
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric   /// Returns true if the DiffType is Type and false for Template.
11460b57cec5SDimitry Andric   static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType,
11470b57cec5SDimitry Andric                                   QualType ToType,
11480b57cec5SDimitry Andric                                   const TemplateSpecializationType *&FromArgTST,
11490b57cec5SDimitry Andric                                   const TemplateSpecializationType *&ToArgTST) {
11500b57cec5SDimitry Andric     if (FromType.isNull() || ToType.isNull())
11510b57cec5SDimitry Andric       return true;
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric     if (Context.hasSameType(FromType, ToType))
11540b57cec5SDimitry Andric       return true;
11550b57cec5SDimitry Andric 
11560b57cec5SDimitry Andric     FromArgTST = GetTemplateSpecializationType(Context, FromType);
11570b57cec5SDimitry Andric     ToArgTST = GetTemplateSpecializationType(Context, ToType);
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric     if (!FromArgTST || !ToArgTST)
11600b57cec5SDimitry Andric       return true;
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric     if (!hasSameTemplate(FromArgTST, ToArgTST))
11630b57cec5SDimitry Andric       return true;
11640b57cec5SDimitry Andric 
11650b57cec5SDimitry Andric     return false;
11660b57cec5SDimitry Andric   }
11670b57cec5SDimitry Andric 
11680b57cec5SDimitry Andric   /// DiffTypes - Fills a DiffNode with information about a type difference.
11690b57cec5SDimitry Andric   void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) {
11700b57cec5SDimitry Andric     QualType FromType = GetType(FromIter);
11710b57cec5SDimitry Andric     QualType ToType = GetType(ToIter);
11720b57cec5SDimitry Andric 
11730b57cec5SDimitry Andric     bool FromDefault = FromIter.isEnd() && !FromType.isNull();
11740b57cec5SDimitry Andric     bool ToDefault = ToIter.isEnd() && !ToType.isNull();
11750b57cec5SDimitry Andric 
11760b57cec5SDimitry Andric     const TemplateSpecializationType *FromArgTST = nullptr;
11770b57cec5SDimitry Andric     const TemplateSpecializationType *ToArgTST = nullptr;
11780b57cec5SDimitry Andric     if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) {
11790b57cec5SDimitry Andric       Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault);
11800b57cec5SDimitry Andric       Tree.SetSame(!FromType.isNull() && !ToType.isNull() &&
11810b57cec5SDimitry Andric                    Context.hasSameType(FromType, ToType));
11820b57cec5SDimitry Andric     } else {
11830b57cec5SDimitry Andric       assert(FromArgTST && ToArgTST &&
11840b57cec5SDimitry Andric              "Both template specializations need to be valid.");
11850b57cec5SDimitry Andric       Qualifiers FromQual = FromType.getQualifiers(),
11860b57cec5SDimitry Andric                  ToQual = ToType.getQualifiers();
11870b57cec5SDimitry Andric       FromQual -= QualType(FromArgTST, 0).getQualifiers();
11880b57cec5SDimitry Andric       ToQual -= QualType(ToArgTST, 0).getQualifiers();
11890b57cec5SDimitry Andric       Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(),
11900b57cec5SDimitry Andric                            ToArgTST->getTemplateName().getAsTemplateDecl(),
11910b57cec5SDimitry Andric                            FromQual, ToQual, FromDefault, ToDefault);
11920b57cec5SDimitry Andric       DiffTemplate(FromArgTST, ToArgTST);
11930b57cec5SDimitry Andric     }
11940b57cec5SDimitry Andric   }
11950b57cec5SDimitry Andric 
11960b57cec5SDimitry Andric   /// DiffTemplateTemplates - Fills a DiffNode with information about a
11970b57cec5SDimitry Andric   /// template template difference.
11980b57cec5SDimitry Andric   void DiffTemplateTemplates(const TSTiterator &FromIter,
11990b57cec5SDimitry Andric                              const TSTiterator &ToIter) {
12000b57cec5SDimitry Andric     TemplateDecl *FromDecl = GetTemplateDecl(FromIter);
12010b57cec5SDimitry Andric     TemplateDecl *ToDecl = GetTemplateDecl(ToIter);
12020b57cec5SDimitry Andric     Tree.SetTemplateTemplateDiff(FromDecl, ToDecl, FromIter.isEnd() && FromDecl,
12030b57cec5SDimitry Andric                                  ToIter.isEnd() && ToDecl);
12040b57cec5SDimitry Andric     Tree.SetSame(FromDecl && ToDecl &&
12050b57cec5SDimitry Andric                  FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());
12060b57cec5SDimitry Andric   }
12070b57cec5SDimitry Andric 
12080b57cec5SDimitry Andric   /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes
12090b57cec5SDimitry Andric   static void InitializeNonTypeDiffVariables(ASTContext &Context,
12100b57cec5SDimitry Andric                                              const TSTiterator &Iter,
12110b57cec5SDimitry Andric                                              NonTypeTemplateParmDecl *Default,
12120b57cec5SDimitry Andric                                              llvm::APSInt &Value, bool &HasInt,
12130b57cec5SDimitry Andric                                              QualType &IntType, bool &IsNullPtr,
12140b57cec5SDimitry Andric                                              Expr *&E, ValueDecl *&VD,
12150b57cec5SDimitry Andric                                              bool &NeedAddressOf) {
12160b57cec5SDimitry Andric     if (!Iter.isEnd()) {
12170b57cec5SDimitry Andric       switch (Iter->getKind()) {
1218*0fca6ea1SDimitry Andric       case TemplateArgument::StructuralValue:
1219*0fca6ea1SDimitry Andric         // FIXME: Diffing of structural values is not implemented.
1220*0fca6ea1SDimitry Andric         // There is no possible fallback in this case, this will show up
1221*0fca6ea1SDimitry Andric         // as '(no argument)'.
1222*0fca6ea1SDimitry Andric         return;
12230b57cec5SDimitry Andric       case TemplateArgument::Integral:
12240b57cec5SDimitry Andric         Value = Iter->getAsIntegral();
12250b57cec5SDimitry Andric         HasInt = true;
12260b57cec5SDimitry Andric         IntType = Iter->getIntegralType();
12270b57cec5SDimitry Andric         return;
12280b57cec5SDimitry Andric       case TemplateArgument::Declaration: {
12290b57cec5SDimitry Andric         VD = Iter->getAsDecl();
12300b57cec5SDimitry Andric         QualType ArgType = Iter->getParamTypeForDecl();
12310b57cec5SDimitry Andric         QualType VDType = VD->getType();
12320b57cec5SDimitry Andric         if (ArgType->isPointerType() &&
12330b57cec5SDimitry Andric             Context.hasSameType(ArgType->getPointeeType(), VDType))
12340b57cec5SDimitry Andric           NeedAddressOf = true;
12350b57cec5SDimitry Andric         return;
12360b57cec5SDimitry Andric       }
12370b57cec5SDimitry Andric       case TemplateArgument::NullPtr:
12380b57cec5SDimitry Andric         IsNullPtr = true;
12390b57cec5SDimitry Andric         return;
12400b57cec5SDimitry Andric       case TemplateArgument::Expression:
12410b57cec5SDimitry Andric         E = Iter->getAsExpr();
1242*0fca6ea1SDimitry Andric         break;
1243*0fca6ea1SDimitry Andric       case TemplateArgument::Null:
1244*0fca6ea1SDimitry Andric       case TemplateArgument::Type:
1245*0fca6ea1SDimitry Andric       case TemplateArgument::Template:
1246*0fca6ea1SDimitry Andric       case TemplateArgument::TemplateExpansion:
1247*0fca6ea1SDimitry Andric         llvm_unreachable("TemplateArgument kind is not expected for NTTP");
1248*0fca6ea1SDimitry Andric       case TemplateArgument::Pack:
1249*0fca6ea1SDimitry Andric         llvm_unreachable("TemplateArgument kind should be handled elsewhere");
12500b57cec5SDimitry Andric       }
12510b57cec5SDimitry Andric     } else if (!Default->isParameterPack()) {
1252*0fca6ea1SDimitry Andric       E = Default->getDefaultArgument().getArgument().getAsExpr();
12530b57cec5SDimitry Andric     }
12540b57cec5SDimitry Andric 
1255*0fca6ea1SDimitry Andric     if (!Iter.hasDesugaredTA())
1256*0fca6ea1SDimitry Andric       return;
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric     const TemplateArgument &TA = Iter.getDesugaredTA();
12590b57cec5SDimitry Andric     switch (TA.getKind()) {
1260*0fca6ea1SDimitry Andric     case TemplateArgument::StructuralValue:
1261*0fca6ea1SDimitry Andric       // FIXME: Diffing of structural values is not implemented.
1262*0fca6ea1SDimitry Andric       //        Just fall back to the expression.
1263*0fca6ea1SDimitry Andric       return;
12640b57cec5SDimitry Andric     case TemplateArgument::Integral:
12650b57cec5SDimitry Andric       Value = TA.getAsIntegral();
12660b57cec5SDimitry Andric       HasInt = true;
12670b57cec5SDimitry Andric       IntType = TA.getIntegralType();
12680b57cec5SDimitry Andric       return;
12690b57cec5SDimitry Andric     case TemplateArgument::Declaration: {
12700b57cec5SDimitry Andric       VD = TA.getAsDecl();
12710b57cec5SDimitry Andric       QualType ArgType = TA.getParamTypeForDecl();
12720b57cec5SDimitry Andric       QualType VDType = VD->getType();
12730b57cec5SDimitry Andric       if (ArgType->isPointerType() &&
12740b57cec5SDimitry Andric           Context.hasSameType(ArgType->getPointeeType(), VDType))
12750b57cec5SDimitry Andric         NeedAddressOf = true;
12760b57cec5SDimitry Andric       return;
12770b57cec5SDimitry Andric     }
12780b57cec5SDimitry Andric     case TemplateArgument::NullPtr:
12790b57cec5SDimitry Andric       IsNullPtr = true;
12800b57cec5SDimitry Andric       return;
12810b57cec5SDimitry Andric     case TemplateArgument::Expression:
12820b57cec5SDimitry Andric       // TODO: Sometimes, the desugared template argument Expr differs from
12830b57cec5SDimitry Andric       // the sugared template argument Expr.  It may be useful in the future
12840b57cec5SDimitry Andric       // but for now, it is just discarded.
12850b57cec5SDimitry Andric       if (!E)
12860b57cec5SDimitry Andric         E = TA.getAsExpr();
12870b57cec5SDimitry Andric       return;
1288*0fca6ea1SDimitry Andric     case TemplateArgument::Null:
1289*0fca6ea1SDimitry Andric     case TemplateArgument::Type:
1290*0fca6ea1SDimitry Andric     case TemplateArgument::Template:
1291*0fca6ea1SDimitry Andric     case TemplateArgument::TemplateExpansion:
1292*0fca6ea1SDimitry Andric       llvm_unreachable("TemplateArgument kind is not expected for NTTP");
1293*0fca6ea1SDimitry Andric     case TemplateArgument::Pack:
1294*0fca6ea1SDimitry Andric       llvm_unreachable("TemplateArgument kind should be handled elsewhere");
12950b57cec5SDimitry Andric     }
1296*0fca6ea1SDimitry Andric     llvm_unreachable("Unexpected TemplateArgument kind");
12970b57cec5SDimitry Andric   }
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric   /// DiffNonTypes - Handles any template parameters not handled by DiffTypes
13000b57cec5SDimitry Andric   /// of DiffTemplatesTemplates, such as integer and declaration parameters.
13010b57cec5SDimitry Andric   void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
13020b57cec5SDimitry Andric                     NonTypeTemplateParmDecl *FromDefaultNonTypeDecl,
13030b57cec5SDimitry Andric                     NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) {
13040b57cec5SDimitry Andric     Expr *FromExpr = nullptr, *ToExpr = nullptr;
13050b57cec5SDimitry Andric     llvm::APSInt FromInt, ToInt;
13060b57cec5SDimitry Andric     QualType FromIntType, ToIntType;
13070b57cec5SDimitry Andric     ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
13080b57cec5SDimitry Andric     bool HasFromInt = false, HasToInt = false, FromNullPtr = false,
13090b57cec5SDimitry Andric          ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;
13100b57cec5SDimitry Andric     InitializeNonTypeDiffVariables(
13110b57cec5SDimitry Andric         Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt,
13120b57cec5SDimitry Andric         FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf);
13130b57cec5SDimitry Andric     InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt,
13140b57cec5SDimitry Andric                                    HasToInt, ToIntType, ToNullPtr, ToExpr,
13150b57cec5SDimitry Andric                                    ToValueDecl, NeedToAddressOf);
13160b57cec5SDimitry Andric 
13170b57cec5SDimitry Andric     bool FromDefault = FromIter.isEnd() &&
13180b57cec5SDimitry Andric                        (FromExpr || FromValueDecl || HasFromInt || FromNullPtr);
13190b57cec5SDimitry Andric     bool ToDefault = ToIter.isEnd() &&
13200b57cec5SDimitry Andric                      (ToExpr || ToValueDecl || HasToInt || ToNullPtr);
13210b57cec5SDimitry Andric 
13220b57cec5SDimitry Andric     bool FromDeclaration = FromValueDecl || FromNullPtr;
13230b57cec5SDimitry Andric     bool ToDeclaration = ToValueDecl || ToNullPtr;
13240b57cec5SDimitry Andric 
13250b57cec5SDimitry Andric     if (FromDeclaration && HasToInt) {
13260b57cec5SDimitry Andric       Tree.SetFromDeclarationAndToIntegerDiff(
13270b57cec5SDimitry Andric           FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt,
13280b57cec5SDimitry Andric           HasToInt, ToIntType, ToExpr, FromDefault, ToDefault);
13290b57cec5SDimitry Andric       Tree.SetSame(false);
13300b57cec5SDimitry Andric       return;
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric     }
13330b57cec5SDimitry Andric 
13340b57cec5SDimitry Andric     if (HasFromInt && ToDeclaration) {
13350b57cec5SDimitry Andric       Tree.SetFromIntegerAndToDeclarationDiff(
13360b57cec5SDimitry Andric           FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl,
13370b57cec5SDimitry Andric           NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault);
13380b57cec5SDimitry Andric       Tree.SetSame(false);
13390b57cec5SDimitry Andric       return;
13400b57cec5SDimitry Andric     }
13410b57cec5SDimitry Andric 
13420b57cec5SDimitry Andric     if (HasFromInt || HasToInt) {
13430b57cec5SDimitry Andric       Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,
13440b57cec5SDimitry Andric                           ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);
13450b57cec5SDimitry Andric       if (HasFromInt && HasToInt) {
13460b57cec5SDimitry Andric         Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) &&
13470b57cec5SDimitry Andric                      FromInt == ToInt);
13480b57cec5SDimitry Andric       }
13490b57cec5SDimitry Andric       return;
13500b57cec5SDimitry Andric     }
13510b57cec5SDimitry Andric 
13520b57cec5SDimitry Andric     if (FromDeclaration || ToDeclaration) {
13530b57cec5SDimitry Andric       Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf,
13540b57cec5SDimitry Andric                               NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
13550b57cec5SDimitry Andric                               ToExpr, FromDefault, ToDefault);
13560b57cec5SDimitry Andric       bool BothNull = FromNullPtr && ToNullPtr;
13570b57cec5SDimitry Andric       bool SameValueDecl =
13580b57cec5SDimitry Andric           FromValueDecl && ToValueDecl &&
13590b57cec5SDimitry Andric           NeedFromAddressOf == NeedToAddressOf &&
13600b57cec5SDimitry Andric           FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl();
13610b57cec5SDimitry Andric       Tree.SetSame(BothNull || SameValueDecl);
13620b57cec5SDimitry Andric       return;
13630b57cec5SDimitry Andric     }
13640b57cec5SDimitry Andric 
13650b57cec5SDimitry Andric     assert((FromExpr || ToExpr) && "Both template arguments cannot be empty.");
13660b57cec5SDimitry Andric     Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault);
13670b57cec5SDimitry Andric     Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
13680b57cec5SDimitry Andric   }
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric   /// DiffTemplate - recursively visits template arguments and stores the
13710b57cec5SDimitry Andric   /// argument info into a tree.
13720b57cec5SDimitry Andric   void DiffTemplate(const TemplateSpecializationType *FromTST,
13730b57cec5SDimitry Andric                     const TemplateSpecializationType *ToTST) {
13740b57cec5SDimitry Andric     // Begin descent into diffing template tree.
13750b57cec5SDimitry Andric     TemplateParameterList *ParamsFrom =
13760b57cec5SDimitry Andric         FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
13770b57cec5SDimitry Andric     TemplateParameterList *ParamsTo =
13780b57cec5SDimitry Andric         ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
13790b57cec5SDimitry Andric     unsigned TotalArgs = 0;
13800b57cec5SDimitry Andric     for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST);
13810b57cec5SDimitry Andric          !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {
13820b57cec5SDimitry Andric       Tree.AddNode();
13830b57cec5SDimitry Andric 
13840b57cec5SDimitry Andric       // Get the parameter at index TotalArgs.  If index is larger
13850b57cec5SDimitry Andric       // than the total number of parameters, then there is an
13860b57cec5SDimitry Andric       // argument pack, so re-use the last parameter.
13870b57cec5SDimitry Andric       unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);
13880b57cec5SDimitry Andric       unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1);
13890b57cec5SDimitry Andric       NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex);
13900b57cec5SDimitry Andric       NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex);
13910b57cec5SDimitry Andric 
13920b57cec5SDimitry Andric       assert(FromParamND->getKind() == ToParamND->getKind() &&
13930b57cec5SDimitry Andric              "Parameter Decl are not the same kind.");
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric       if (isa<TemplateTypeParmDecl>(FromParamND)) {
13960b57cec5SDimitry Andric         DiffTypes(FromIter, ToIter);
13970b57cec5SDimitry Andric       } else if (isa<TemplateTemplateParmDecl>(FromParamND)) {
13980b57cec5SDimitry Andric         DiffTemplateTemplates(FromIter, ToIter);
13990b57cec5SDimitry Andric       } else if (isa<NonTypeTemplateParmDecl>(FromParamND)) {
14000b57cec5SDimitry Andric         NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =
14010b57cec5SDimitry Andric             cast<NonTypeTemplateParmDecl>(FromParamND);
14020b57cec5SDimitry Andric         NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =
14030b57cec5SDimitry Andric             cast<NonTypeTemplateParmDecl>(ToParamND);
14040b57cec5SDimitry Andric         DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,
14050b57cec5SDimitry Andric                      ToDefaultNonTypeDecl);
14060b57cec5SDimitry Andric       } else {
14070b57cec5SDimitry Andric         llvm_unreachable("Unexpected Decl type.");
14080b57cec5SDimitry Andric       }
14090b57cec5SDimitry Andric 
14100b57cec5SDimitry Andric       ++FromIter;
14110b57cec5SDimitry Andric       ++ToIter;
14120b57cec5SDimitry Andric       Tree.Up();
14130b57cec5SDimitry Andric     }
14140b57cec5SDimitry Andric   }
14150b57cec5SDimitry Andric 
14160b57cec5SDimitry Andric   /// makeTemplateList - Dump every template alias into the vector.
14170b57cec5SDimitry Andric   static void makeTemplateList(
14180b57cec5SDimitry Andric       SmallVectorImpl<const TemplateSpecializationType *> &TemplateList,
14190b57cec5SDimitry Andric       const TemplateSpecializationType *TST) {
14200b57cec5SDimitry Andric     while (TST) {
14210b57cec5SDimitry Andric       TemplateList.push_back(TST);
14220b57cec5SDimitry Andric       if (!TST->isTypeAlias())
14230b57cec5SDimitry Andric         return;
14240b57cec5SDimitry Andric       TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
14250b57cec5SDimitry Andric     }
14260b57cec5SDimitry Andric   }
14270b57cec5SDimitry Andric 
14280b57cec5SDimitry Andric   /// hasSameBaseTemplate - Returns true when the base templates are the same,
14290b57cec5SDimitry Andric   /// even if the template arguments are not.
14300b57cec5SDimitry Andric   static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST,
14310b57cec5SDimitry Andric                                   const TemplateSpecializationType *ToTST) {
14320b57cec5SDimitry Andric     return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() ==
14330b57cec5SDimitry Andric            ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl();
14340b57cec5SDimitry Andric   }
14350b57cec5SDimitry Andric 
14360b57cec5SDimitry Andric   /// hasSameTemplate - Returns true if both types are specialized from the
14370b57cec5SDimitry Andric   /// same template declaration.  If they come from different template aliases,
14380b57cec5SDimitry Andric   /// do a parallel ascension search to determine the highest template alias in
14390b57cec5SDimitry Andric   /// common and set the arguments to them.
14400b57cec5SDimitry Andric   static bool hasSameTemplate(const TemplateSpecializationType *&FromTST,
14410b57cec5SDimitry Andric                               const TemplateSpecializationType *&ToTST) {
14420b57cec5SDimitry Andric     // Check the top templates if they are the same.
14430b57cec5SDimitry Andric     if (hasSameBaseTemplate(FromTST, ToTST))
14440b57cec5SDimitry Andric       return true;
14450b57cec5SDimitry Andric 
14460b57cec5SDimitry Andric     // Create vectors of template aliases.
14470b57cec5SDimitry Andric     SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,
14480b57cec5SDimitry Andric                                                       ToTemplateList;
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric     makeTemplateList(FromTemplateList, FromTST);
14510b57cec5SDimitry Andric     makeTemplateList(ToTemplateList, ToTST);
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric     SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator
14540b57cec5SDimitry Andric         FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),
14550b57cec5SDimitry Andric         ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();
14560b57cec5SDimitry Andric 
14570b57cec5SDimitry Andric     // Check if the lowest template types are the same.  If not, return.
14580b57cec5SDimitry Andric     if (!hasSameBaseTemplate(*FromIter, *ToIter))
14590b57cec5SDimitry Andric       return false;
14600b57cec5SDimitry Andric 
14610b57cec5SDimitry Andric     // Begin searching up the template aliases.  The bottom most template
14620b57cec5SDimitry Andric     // matches so move up until one pair does not match.  Use the template
14630b57cec5SDimitry Andric     // right before that one.
14640b57cec5SDimitry Andric     for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {
14650b57cec5SDimitry Andric       if (!hasSameBaseTemplate(*FromIter, *ToIter))
14660b57cec5SDimitry Andric         break;
14670b57cec5SDimitry Andric     }
14680b57cec5SDimitry Andric 
14690b57cec5SDimitry Andric     FromTST = FromIter[-1];
14700b57cec5SDimitry Andric     ToTST = ToIter[-1];
14710b57cec5SDimitry Andric 
14720b57cec5SDimitry Andric     return true;
14730b57cec5SDimitry Andric   }
14740b57cec5SDimitry Andric 
14750b57cec5SDimitry Andric   /// GetType - Retrieves the template type arguments, including default
14760b57cec5SDimitry Andric   /// arguments.
14770b57cec5SDimitry Andric   static QualType GetType(const TSTiterator &Iter) {
14780b57cec5SDimitry Andric     if (!Iter.isEnd())
14790b57cec5SDimitry Andric       return Iter->getAsType();
14800b57cec5SDimitry Andric     if (Iter.hasDesugaredTA())
14810b57cec5SDimitry Andric       return Iter.getDesugaredTA().getAsType();
14820b57cec5SDimitry Andric     return QualType();
14830b57cec5SDimitry Andric   }
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric   /// GetTemplateDecl - Retrieves the template template arguments, including
14860b57cec5SDimitry Andric   /// default arguments.
14870b57cec5SDimitry Andric   static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) {
14880b57cec5SDimitry Andric     if (!Iter.isEnd())
14890b57cec5SDimitry Andric       return Iter->getAsTemplate().getAsTemplateDecl();
14900b57cec5SDimitry Andric     if (Iter.hasDesugaredTA())
14910b57cec5SDimitry Andric       return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl();
14920b57cec5SDimitry Andric     return nullptr;
14930b57cec5SDimitry Andric   }
14940b57cec5SDimitry Andric 
14950b57cec5SDimitry Andric   /// IsEqualExpr - Returns true if the expressions are the same in regards to
14960b57cec5SDimitry Andric   /// template arguments.  These expressions are dependent, so profile them
14970b57cec5SDimitry Andric   /// instead of trying to evaluate them.
14980b57cec5SDimitry Andric   static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {
14990b57cec5SDimitry Andric     if (FromExpr == ToExpr)
15000b57cec5SDimitry Andric       return true;
15010b57cec5SDimitry Andric 
15020b57cec5SDimitry Andric     if (!FromExpr || !ToExpr)
15030b57cec5SDimitry Andric       return false;
15040b57cec5SDimitry Andric 
15050b57cec5SDimitry Andric     llvm::FoldingSetNodeID FromID, ToID;
15060b57cec5SDimitry Andric     FromExpr->Profile(FromID, Context, true);
15070b57cec5SDimitry Andric     ToExpr->Profile(ToID, Context, true);
15080b57cec5SDimitry Andric     return FromID == ToID;
15090b57cec5SDimitry Andric   }
15100b57cec5SDimitry Andric 
15110b57cec5SDimitry Andric   // These functions converts the tree representation of the template
15120b57cec5SDimitry Andric   // differences into the internal character vector.
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric   /// TreeToString - Converts the Tree object into a character stream which
15150b57cec5SDimitry Andric   /// will later be turned into the output string.
15160b57cec5SDimitry Andric   void TreeToString(int Indent = 1) {
15170b57cec5SDimitry Andric     if (PrintTree) {
15180b57cec5SDimitry Andric       OS << '\n';
15190b57cec5SDimitry Andric       OS.indent(2 * Indent);
15200b57cec5SDimitry Andric       ++Indent;
15210b57cec5SDimitry Andric     }
15220b57cec5SDimitry Andric 
15230b57cec5SDimitry Andric     // Handle cases where the difference is not templates with different
15240b57cec5SDimitry Andric     // arguments.
15250b57cec5SDimitry Andric     switch (Tree.GetKind()) {
15260b57cec5SDimitry Andric       case DiffTree::Invalid:
15270b57cec5SDimitry Andric         llvm_unreachable("Template diffing failed with bad DiffNode");
15280b57cec5SDimitry Andric       case DiffTree::Type: {
15290b57cec5SDimitry Andric         QualType FromType, ToType;
15300b57cec5SDimitry Andric         Tree.GetTypeDiff(FromType, ToType);
15310b57cec5SDimitry Andric         PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),
15320b57cec5SDimitry Andric                        Tree.NodeIsSame());
15330b57cec5SDimitry Andric         return;
15340b57cec5SDimitry Andric       }
15350b57cec5SDimitry Andric       case DiffTree::Expression: {
15360b57cec5SDimitry Andric         Expr *FromExpr, *ToExpr;
15370b57cec5SDimitry Andric         Tree.GetExpressionDiff(FromExpr, ToExpr);
15380b57cec5SDimitry Andric         PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
15390b57cec5SDimitry Andric                   Tree.NodeIsSame());
15400b57cec5SDimitry Andric         return;
15410b57cec5SDimitry Andric       }
15420b57cec5SDimitry Andric       case DiffTree::TemplateTemplate: {
15430b57cec5SDimitry Andric         TemplateDecl *FromTD, *ToTD;
15440b57cec5SDimitry Andric         Tree.GetTemplateTemplateDiff(FromTD, ToTD);
15450b57cec5SDimitry Andric         PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),
15460b57cec5SDimitry Andric                               Tree.ToDefault(), Tree.NodeIsSame());
15470b57cec5SDimitry Andric         return;
15480b57cec5SDimitry Andric       }
15490b57cec5SDimitry Andric       case DiffTree::Integer: {
15500b57cec5SDimitry Andric         llvm::APSInt FromInt, ToInt;
15510b57cec5SDimitry Andric         Expr *FromExpr, *ToExpr;
15520b57cec5SDimitry Andric         bool IsValidFromInt, IsValidToInt;
15530b57cec5SDimitry Andric         QualType FromIntType, ToIntType;
15540b57cec5SDimitry Andric         Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,
15550b57cec5SDimitry Andric                             FromIntType, ToIntType, FromExpr, ToExpr);
15560b57cec5SDimitry Andric         PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,
15570b57cec5SDimitry Andric                     ToIntType, FromExpr, ToExpr, Tree.FromDefault(),
15580b57cec5SDimitry Andric                     Tree.ToDefault(), Tree.NodeIsSame());
15590b57cec5SDimitry Andric         return;
15600b57cec5SDimitry Andric       }
15610b57cec5SDimitry Andric       case DiffTree::Declaration: {
15620b57cec5SDimitry Andric         ValueDecl *FromValueDecl, *ToValueDecl;
15630b57cec5SDimitry Andric         bool FromAddressOf, ToAddressOf;
15640b57cec5SDimitry Andric         bool FromNullPtr, ToNullPtr;
15650b57cec5SDimitry Andric         Expr *FromExpr, *ToExpr;
15660b57cec5SDimitry Andric         Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf,
15670b57cec5SDimitry Andric                                 ToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
15680b57cec5SDimitry Andric                                 ToExpr);
15690b57cec5SDimitry Andric         PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
15700b57cec5SDimitry Andric                        FromNullPtr, ToNullPtr, FromExpr, ToExpr,
15710b57cec5SDimitry Andric                        Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
15720b57cec5SDimitry Andric         return;
15730b57cec5SDimitry Andric       }
15740b57cec5SDimitry Andric       case DiffTree::FromDeclarationAndToInteger: {
15750b57cec5SDimitry Andric         ValueDecl *FromValueDecl;
15760b57cec5SDimitry Andric         bool FromAddressOf;
15770b57cec5SDimitry Andric         bool FromNullPtr;
15780b57cec5SDimitry Andric         Expr *FromExpr;
15790b57cec5SDimitry Andric         llvm::APSInt ToInt;
15800b57cec5SDimitry Andric         bool IsValidToInt;
15810b57cec5SDimitry Andric         QualType ToIntType;
15820b57cec5SDimitry Andric         Expr *ToExpr;
15830b57cec5SDimitry Andric         Tree.GetFromDeclarationAndToIntegerDiff(
15840b57cec5SDimitry Andric             FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt,
15850b57cec5SDimitry Andric             IsValidToInt, ToIntType, ToExpr);
15860b57cec5SDimitry Andric         assert((FromValueDecl || FromNullPtr) && IsValidToInt);
15870b57cec5SDimitry Andric         PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr,
15880b57cec5SDimitry Andric                                  FromExpr, Tree.FromDefault(), ToInt, ToIntType,
15890b57cec5SDimitry Andric                                  ToExpr, Tree.ToDefault());
15900b57cec5SDimitry Andric         return;
15910b57cec5SDimitry Andric       }
15920b57cec5SDimitry Andric       case DiffTree::FromIntegerAndToDeclaration: {
15930b57cec5SDimitry Andric         llvm::APSInt FromInt;
15940b57cec5SDimitry Andric         bool IsValidFromInt;
15950b57cec5SDimitry Andric         QualType FromIntType;
15960b57cec5SDimitry Andric         Expr *FromExpr;
15970b57cec5SDimitry Andric         ValueDecl *ToValueDecl;
15980b57cec5SDimitry Andric         bool ToAddressOf;
15990b57cec5SDimitry Andric         bool ToNullPtr;
16000b57cec5SDimitry Andric         Expr *ToExpr;
16010b57cec5SDimitry Andric         Tree.GetFromIntegerAndToDeclarationDiff(
16020b57cec5SDimitry Andric             FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl,
16030b57cec5SDimitry Andric             ToAddressOf, ToNullPtr, ToExpr);
16040b57cec5SDimitry Andric         assert(IsValidFromInt && (ToValueDecl || ToNullPtr));
16050b57cec5SDimitry Andric         PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr,
16060b57cec5SDimitry Andric                                  Tree.FromDefault(), ToValueDecl, ToAddressOf,
16070b57cec5SDimitry Andric                                  ToNullPtr, ToExpr, Tree.ToDefault());
16080b57cec5SDimitry Andric         return;
16090b57cec5SDimitry Andric       }
16100b57cec5SDimitry Andric       case DiffTree::Template: {
16110b57cec5SDimitry Andric         // Node is root of template.  Recurse on children.
16120b57cec5SDimitry Andric         TemplateDecl *FromTD, *ToTD;
16130b57cec5SDimitry Andric         Qualifiers FromQual, ToQual;
16140b57cec5SDimitry Andric         Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual);
16150b57cec5SDimitry Andric 
16160b57cec5SDimitry Andric         PrintQualifiers(FromQual, ToQual);
16170b57cec5SDimitry Andric 
16180b57cec5SDimitry Andric         if (!Tree.HasChildren()) {
16190b57cec5SDimitry Andric           // If we're dealing with a template specialization with zero
16200b57cec5SDimitry Andric           // arguments, there are no children; special-case this.
1621e8d8bef9SDimitry Andric           OS << FromTD->getDeclName() << "<>";
16220b57cec5SDimitry Andric           return;
16230b57cec5SDimitry Andric         }
16240b57cec5SDimitry Andric 
1625e8d8bef9SDimitry Andric         OS << FromTD->getDeclName() << '<';
16260b57cec5SDimitry Andric         Tree.MoveToChild();
16270b57cec5SDimitry Andric         unsigned NumElideArgs = 0;
16280b57cec5SDimitry Andric         bool AllArgsElided = true;
16290b57cec5SDimitry Andric         do {
16300b57cec5SDimitry Andric           if (ElideType) {
16310b57cec5SDimitry Andric             if (Tree.NodeIsSame()) {
16320b57cec5SDimitry Andric               ++NumElideArgs;
16330b57cec5SDimitry Andric               continue;
16340b57cec5SDimitry Andric             }
16350b57cec5SDimitry Andric             AllArgsElided = false;
16360b57cec5SDimitry Andric             if (NumElideArgs > 0) {
16370b57cec5SDimitry Andric               PrintElideArgs(NumElideArgs, Indent);
16380b57cec5SDimitry Andric               NumElideArgs = 0;
16390b57cec5SDimitry Andric               OS << ", ";
16400b57cec5SDimitry Andric             }
16410b57cec5SDimitry Andric           }
16420b57cec5SDimitry Andric           TreeToString(Indent);
16430b57cec5SDimitry Andric           if (Tree.HasNextSibling())
16440b57cec5SDimitry Andric             OS << ", ";
16450b57cec5SDimitry Andric         } while (Tree.AdvanceSibling());
16460b57cec5SDimitry Andric         if (NumElideArgs > 0) {
16470b57cec5SDimitry Andric           if (AllArgsElided)
16480b57cec5SDimitry Andric             OS << "...";
16490b57cec5SDimitry Andric           else
16500b57cec5SDimitry Andric             PrintElideArgs(NumElideArgs, Indent);
16510b57cec5SDimitry Andric         }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric         Tree.Parent();
16540b57cec5SDimitry Andric         OS << ">";
16550b57cec5SDimitry Andric         return;
16560b57cec5SDimitry Andric       }
16570b57cec5SDimitry Andric     }
16580b57cec5SDimitry Andric   }
16590b57cec5SDimitry Andric 
16600b57cec5SDimitry Andric   // To signal to the text printer that a certain text needs to be bolded,
16610b57cec5SDimitry Andric   // a special character is injected into the character stream which the
16620b57cec5SDimitry Andric   // text printer will later strip out.
16630b57cec5SDimitry Andric 
16640b57cec5SDimitry Andric   /// Bold - Start bolding text.
16650b57cec5SDimitry Andric   void Bold() {
16660b57cec5SDimitry Andric     assert(!IsBold && "Attempting to bold text that is already bold.");
16670b57cec5SDimitry Andric     IsBold = true;
16680b57cec5SDimitry Andric     if (ShowColor)
16690b57cec5SDimitry Andric       OS << ToggleHighlight;
16700b57cec5SDimitry Andric   }
16710b57cec5SDimitry Andric 
16720b57cec5SDimitry Andric   /// Unbold - Stop bolding text.
16730b57cec5SDimitry Andric   void Unbold() {
16740b57cec5SDimitry Andric     assert(IsBold && "Attempting to remove bold from unbold text.");
16750b57cec5SDimitry Andric     IsBold = false;
16760b57cec5SDimitry Andric     if (ShowColor)
16770b57cec5SDimitry Andric       OS << ToggleHighlight;
16780b57cec5SDimitry Andric   }
16790b57cec5SDimitry Andric 
16800b57cec5SDimitry Andric   // Functions to print out the arguments and highlighting the difference.
16810b57cec5SDimitry Andric 
16820b57cec5SDimitry Andric   /// PrintTypeNames - prints the typenames, bolding differences.  Will detect
16830b57cec5SDimitry Andric   /// typenames that are the same and attempt to disambiguate them by using
16840b57cec5SDimitry Andric   /// canonical typenames.
16850b57cec5SDimitry Andric   void PrintTypeNames(QualType FromType, QualType ToType,
16860b57cec5SDimitry Andric                       bool FromDefault, bool ToDefault, bool Same) {
16870b57cec5SDimitry Andric     assert((!FromType.isNull() || !ToType.isNull()) &&
16880b57cec5SDimitry Andric            "Only one template argument may be missing.");
16890b57cec5SDimitry Andric 
16900b57cec5SDimitry Andric     if (Same) {
16910b57cec5SDimitry Andric       OS << FromType.getAsString(Policy);
16920b57cec5SDimitry Andric       return;
16930b57cec5SDimitry Andric     }
16940b57cec5SDimitry Andric 
16950b57cec5SDimitry Andric     if (!FromType.isNull() && !ToType.isNull() &&
16960b57cec5SDimitry Andric         FromType.getLocalUnqualifiedType() ==
16970b57cec5SDimitry Andric         ToType.getLocalUnqualifiedType()) {
16980b57cec5SDimitry Andric       Qualifiers FromQual = FromType.getLocalQualifiers(),
16990b57cec5SDimitry Andric                  ToQual = ToType.getLocalQualifiers();
17000b57cec5SDimitry Andric       PrintQualifiers(FromQual, ToQual);
17010b57cec5SDimitry Andric       FromType.getLocalUnqualifiedType().print(OS, Policy);
17020b57cec5SDimitry Andric       return;
17030b57cec5SDimitry Andric     }
17040b57cec5SDimitry Andric 
17050b57cec5SDimitry Andric     std::string FromTypeStr = FromType.isNull() ? "(no argument)"
17060b57cec5SDimitry Andric                                                 : FromType.getAsString(Policy);
17070b57cec5SDimitry Andric     std::string ToTypeStr = ToType.isNull() ? "(no argument)"
17080b57cec5SDimitry Andric                                             : ToType.getAsString(Policy);
1709bdd1243dSDimitry Andric     // Print without ElaboratedType sugar if it is better.
17100b57cec5SDimitry Andric     // TODO: merge this with other aka printing above.
17110b57cec5SDimitry Andric     if (FromTypeStr == ToTypeStr) {
1712bdd1243dSDimitry Andric       const auto *FromElTy = dyn_cast<ElaboratedType>(FromType),
1713bdd1243dSDimitry Andric                  *ToElTy = dyn_cast<ElaboratedType>(ToType);
1714bdd1243dSDimitry Andric       if (FromElTy || ToElTy) {
1715bdd1243dSDimitry Andric         std::string FromNamedTypeStr =
1716bdd1243dSDimitry Andric             FromElTy ? FromElTy->getNamedType().getAsString(Policy)
1717bdd1243dSDimitry Andric                      : FromTypeStr;
1718bdd1243dSDimitry Andric         std::string ToNamedTypeStr =
1719bdd1243dSDimitry Andric             ToElTy ? ToElTy->getNamedType().getAsString(Policy) : ToTypeStr;
1720bdd1243dSDimitry Andric         if (FromNamedTypeStr != ToNamedTypeStr) {
1721bdd1243dSDimitry Andric           FromTypeStr = FromNamedTypeStr;
1722bdd1243dSDimitry Andric           ToTypeStr = ToNamedTypeStr;
1723bdd1243dSDimitry Andric           goto PrintTypes;
1724bdd1243dSDimitry Andric         }
1725bdd1243dSDimitry Andric       }
1726bdd1243dSDimitry Andric       // Switch to canonical typename if it is better.
17270b57cec5SDimitry Andric       std::string FromCanTypeStr =
17280b57cec5SDimitry Andric           FromType.getCanonicalType().getAsString(Policy);
17290b57cec5SDimitry Andric       std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy);
17300b57cec5SDimitry Andric       if (FromCanTypeStr != ToCanTypeStr) {
17310b57cec5SDimitry Andric         FromTypeStr = FromCanTypeStr;
17320b57cec5SDimitry Andric         ToTypeStr = ToCanTypeStr;
17330b57cec5SDimitry Andric       }
17340b57cec5SDimitry Andric     }
17350b57cec5SDimitry Andric 
1736bdd1243dSDimitry Andric   PrintTypes:
17370b57cec5SDimitry Andric     if (PrintTree) OS << '[';
17380b57cec5SDimitry Andric     OS << (FromDefault ? "(default) " : "");
17390b57cec5SDimitry Andric     Bold();
17400b57cec5SDimitry Andric     OS << FromTypeStr;
17410b57cec5SDimitry Andric     Unbold();
17420b57cec5SDimitry Andric     if (PrintTree) {
17430b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) " : "");
17440b57cec5SDimitry Andric       Bold();
17450b57cec5SDimitry Andric       OS << ToTypeStr;
17460b57cec5SDimitry Andric       Unbold();
17470b57cec5SDimitry Andric       OS << "]";
17480b57cec5SDimitry Andric     }
17490b57cec5SDimitry Andric   }
17500b57cec5SDimitry Andric 
17510b57cec5SDimitry Andric   /// PrintExpr - Prints out the expr template arguments, highlighting argument
17520b57cec5SDimitry Andric   /// differences.
17530b57cec5SDimitry Andric   void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault,
17540b57cec5SDimitry Andric                  bool ToDefault, bool Same) {
17550b57cec5SDimitry Andric     assert((FromExpr || ToExpr) &&
17560b57cec5SDimitry Andric             "Only one template argument may be missing.");
17570b57cec5SDimitry Andric     if (Same) {
17580b57cec5SDimitry Andric       PrintExpr(FromExpr);
17590b57cec5SDimitry Andric     } else if (!PrintTree) {
17600b57cec5SDimitry Andric       OS << (FromDefault ? "(default) " : "");
17610b57cec5SDimitry Andric       Bold();
17620b57cec5SDimitry Andric       PrintExpr(FromExpr);
17630b57cec5SDimitry Andric       Unbold();
17640b57cec5SDimitry Andric     } else {
17650b57cec5SDimitry Andric       OS << (FromDefault ? "[(default) " : "[");
17660b57cec5SDimitry Andric       Bold();
17670b57cec5SDimitry Andric       PrintExpr(FromExpr);
17680b57cec5SDimitry Andric       Unbold();
17690b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) " : "");
17700b57cec5SDimitry Andric       Bold();
17710b57cec5SDimitry Andric       PrintExpr(ToExpr);
17720b57cec5SDimitry Andric       Unbold();
17730b57cec5SDimitry Andric       OS << ']';
17740b57cec5SDimitry Andric     }
17750b57cec5SDimitry Andric   }
17760b57cec5SDimitry Andric 
17770b57cec5SDimitry Andric   /// PrintExpr - Actual formatting and printing of expressions.
17780b57cec5SDimitry Andric   void PrintExpr(const Expr *E) {
17790b57cec5SDimitry Andric     if (E) {
17800b57cec5SDimitry Andric       E->printPretty(OS, nullptr, Policy);
17810b57cec5SDimitry Andric       return;
17820b57cec5SDimitry Andric     }
17830b57cec5SDimitry Andric     OS << "(no argument)";
17840b57cec5SDimitry Andric   }
17850b57cec5SDimitry Andric 
17860b57cec5SDimitry Andric   /// PrintTemplateTemplate - Handles printing of template template arguments,
17870b57cec5SDimitry Andric   /// highlighting argument differences.
17880b57cec5SDimitry Andric   void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,
17890b57cec5SDimitry Andric                              bool FromDefault, bool ToDefault, bool Same) {
17900b57cec5SDimitry Andric     assert((FromTD || ToTD) && "Only one template argument may be missing.");
17910b57cec5SDimitry Andric 
17925ffd83dbSDimitry Andric     std::string FromName =
17935ffd83dbSDimitry Andric         std::string(FromTD ? FromTD->getName() : "(no argument)");
17945ffd83dbSDimitry Andric     std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");
17950b57cec5SDimitry Andric     if (FromTD && ToTD && FromName == ToName) {
17960b57cec5SDimitry Andric       FromName = FromTD->getQualifiedNameAsString();
17970b57cec5SDimitry Andric       ToName = ToTD->getQualifiedNameAsString();
17980b57cec5SDimitry Andric     }
17990b57cec5SDimitry Andric 
18000b57cec5SDimitry Andric     if (Same) {
1801e8d8bef9SDimitry Andric       OS << "template " << FromTD->getDeclName();
18020b57cec5SDimitry Andric     } else if (!PrintTree) {
18030b57cec5SDimitry Andric       OS << (FromDefault ? "(default) template " : "template ");
18040b57cec5SDimitry Andric       Bold();
18050b57cec5SDimitry Andric       OS << FromName;
18060b57cec5SDimitry Andric       Unbold();
18070b57cec5SDimitry Andric     } else {
18080b57cec5SDimitry Andric       OS << (FromDefault ? "[(default) template " : "[template ");
18090b57cec5SDimitry Andric       Bold();
18100b57cec5SDimitry Andric       OS << FromName;
18110b57cec5SDimitry Andric       Unbold();
18120b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) template " : "template ");
18130b57cec5SDimitry Andric       Bold();
18140b57cec5SDimitry Andric       OS << ToName;
18150b57cec5SDimitry Andric       Unbold();
18160b57cec5SDimitry Andric       OS << ']';
18170b57cec5SDimitry Andric     }
18180b57cec5SDimitry Andric   }
18190b57cec5SDimitry Andric 
18200b57cec5SDimitry Andric   /// PrintAPSInt - Handles printing of integral arguments, highlighting
18210b57cec5SDimitry Andric   /// argument differences.
18220b57cec5SDimitry Andric   void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
18230b57cec5SDimitry Andric                    bool IsValidFromInt, bool IsValidToInt, QualType FromIntType,
18240b57cec5SDimitry Andric                    QualType ToIntType, Expr *FromExpr, Expr *ToExpr,
18250b57cec5SDimitry Andric                    bool FromDefault, bool ToDefault, bool Same) {
18260b57cec5SDimitry Andric     assert((IsValidFromInt || IsValidToInt) &&
18270b57cec5SDimitry Andric            "Only one integral argument may be missing.");
18280b57cec5SDimitry Andric 
18290b57cec5SDimitry Andric     if (Same) {
18300b57cec5SDimitry Andric       if (FromIntType->isBooleanType()) {
18310b57cec5SDimitry Andric         OS << ((FromInt == 0) ? "false" : "true");
18320b57cec5SDimitry Andric       } else {
1833fe6060f1SDimitry Andric         OS << toString(FromInt, 10);
18340b57cec5SDimitry Andric       }
18350b57cec5SDimitry Andric       return;
18360b57cec5SDimitry Andric     }
18370b57cec5SDimitry Andric 
18380b57cec5SDimitry Andric     bool PrintType = IsValidFromInt && IsValidToInt &&
18390b57cec5SDimitry Andric                      !Context.hasSameType(FromIntType, ToIntType);
18400b57cec5SDimitry Andric 
18410b57cec5SDimitry Andric     if (!PrintTree) {
18420b57cec5SDimitry Andric       OS << (FromDefault ? "(default) " : "");
18430b57cec5SDimitry Andric       PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
18440b57cec5SDimitry Andric     } else {
18450b57cec5SDimitry Andric       OS << (FromDefault ? "[(default) " : "[");
18460b57cec5SDimitry Andric       PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
18470b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) " : "");
18480b57cec5SDimitry Andric       PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType);
18490b57cec5SDimitry Andric       OS << ']';
18500b57cec5SDimitry Andric     }
18510b57cec5SDimitry Andric   }
18520b57cec5SDimitry Andric 
18530b57cec5SDimitry Andric   /// PrintAPSInt - If valid, print the APSInt.  If the expression is
18540b57cec5SDimitry Andric   /// gives more information, print it too.
18550b57cec5SDimitry Andric   void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid,
18560b57cec5SDimitry Andric                    QualType IntType, bool PrintType) {
18570b57cec5SDimitry Andric     Bold();
18580b57cec5SDimitry Andric     if (Valid) {
18590b57cec5SDimitry Andric       if (HasExtraInfo(E)) {
18600b57cec5SDimitry Andric         PrintExpr(E);
18610b57cec5SDimitry Andric         Unbold();
18620b57cec5SDimitry Andric         OS << " aka ";
18630b57cec5SDimitry Andric         Bold();
18640b57cec5SDimitry Andric       }
18650b57cec5SDimitry Andric       if (PrintType) {
18660b57cec5SDimitry Andric         Unbold();
18670b57cec5SDimitry Andric         OS << "(";
18680b57cec5SDimitry Andric         Bold();
18690b57cec5SDimitry Andric         IntType.print(OS, Context.getPrintingPolicy());
18700b57cec5SDimitry Andric         Unbold();
18710b57cec5SDimitry Andric         OS << ") ";
18720b57cec5SDimitry Andric         Bold();
18730b57cec5SDimitry Andric       }
18740b57cec5SDimitry Andric       if (IntType->isBooleanType()) {
18750b57cec5SDimitry Andric         OS << ((Val == 0) ? "false" : "true");
18760b57cec5SDimitry Andric       } else {
1877fe6060f1SDimitry Andric         OS << toString(Val, 10);
18780b57cec5SDimitry Andric       }
18790b57cec5SDimitry Andric     } else if (E) {
18800b57cec5SDimitry Andric       PrintExpr(E);
18810b57cec5SDimitry Andric     } else {
18820b57cec5SDimitry Andric       OS << "(no argument)";
18830b57cec5SDimitry Andric     }
18840b57cec5SDimitry Andric     Unbold();
18850b57cec5SDimitry Andric   }
18860b57cec5SDimitry Andric 
18870b57cec5SDimitry Andric   /// HasExtraInfo - Returns true if E is not an integer literal, the
18880b57cec5SDimitry Andric   /// negation of an integer literal, or a boolean literal.
18890b57cec5SDimitry Andric   bool HasExtraInfo(Expr *E) {
18900b57cec5SDimitry Andric     if (!E) return false;
18910b57cec5SDimitry Andric 
18920b57cec5SDimitry Andric     E = E->IgnoreImpCasts();
18930b57cec5SDimitry Andric 
18940b57cec5SDimitry Andric     if (isa<IntegerLiteral>(E)) return false;
18950b57cec5SDimitry Andric 
18960b57cec5SDimitry Andric     if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))
18970b57cec5SDimitry Andric       if (UO->getOpcode() == UO_Minus)
18980b57cec5SDimitry Andric         if (isa<IntegerLiteral>(UO->getSubExpr()))
18990b57cec5SDimitry Andric           return false;
19000b57cec5SDimitry Andric 
19010b57cec5SDimitry Andric     if (isa<CXXBoolLiteralExpr>(E))
19020b57cec5SDimitry Andric       return false;
19030b57cec5SDimitry Andric 
19040b57cec5SDimitry Andric     return true;
19050b57cec5SDimitry Andric   }
19060b57cec5SDimitry Andric 
19070b57cec5SDimitry Andric   void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) {
19080b57cec5SDimitry Andric     if (VD) {
19090b57cec5SDimitry Andric       if (AddressOf)
19100b57cec5SDimitry Andric         OS << "&";
1911e8d8bef9SDimitry Andric       else if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD)) {
1912e8d8bef9SDimitry Andric         // FIXME: Diffing the APValue would be neat.
1913e8d8bef9SDimitry Andric         // FIXME: Suppress this and use the full name of the declaration if the
1914e8d8bef9SDimitry Andric         // parameter is a pointer or reference.
19155f757f3fSDimitry Andric         TPO->getType().getUnqualifiedType().print(OS, Policy);
191681ad6265SDimitry Andric         TPO->printAsInit(OS, Policy);
1917e8d8bef9SDimitry Andric         return;
1918e8d8bef9SDimitry Andric       }
1919bdd1243dSDimitry Andric       VD->printName(OS, Policy);
19200b57cec5SDimitry Andric       return;
19210b57cec5SDimitry Andric     }
19220b57cec5SDimitry Andric 
19230b57cec5SDimitry Andric     if (NullPtr) {
19240b57cec5SDimitry Andric       if (E && !isa<CXXNullPtrLiteralExpr>(E)) {
19250b57cec5SDimitry Andric         PrintExpr(E);
19260b57cec5SDimitry Andric         if (IsBold) {
19270b57cec5SDimitry Andric           Unbold();
19280b57cec5SDimitry Andric           OS << " aka ";
19290b57cec5SDimitry Andric           Bold();
19300b57cec5SDimitry Andric         } else {
19310b57cec5SDimitry Andric           OS << " aka ";
19320b57cec5SDimitry Andric         }
19330b57cec5SDimitry Andric       }
19340b57cec5SDimitry Andric 
19350b57cec5SDimitry Andric       OS << "nullptr";
19360b57cec5SDimitry Andric       return;
19370b57cec5SDimitry Andric     }
19380b57cec5SDimitry Andric 
1939*0fca6ea1SDimitry Andric     if (E) {
1940*0fca6ea1SDimitry Andric       PrintExpr(E);
1941*0fca6ea1SDimitry Andric       return;
1942*0fca6ea1SDimitry Andric     }
1943*0fca6ea1SDimitry Andric 
19440b57cec5SDimitry Andric     OS << "(no argument)";
19450b57cec5SDimitry Andric   }
19460b57cec5SDimitry Andric 
19470b57cec5SDimitry Andric   /// PrintDecl - Handles printing of Decl arguments, highlighting
19480b57cec5SDimitry Andric   /// argument differences.
19490b57cec5SDimitry Andric   void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
19500b57cec5SDimitry Andric                       bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,
19510b57cec5SDimitry Andric                       bool ToNullPtr, Expr *FromExpr, Expr *ToExpr,
19520b57cec5SDimitry Andric                       bool FromDefault, bool ToDefault, bool Same) {
19530b57cec5SDimitry Andric     assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&
19540b57cec5SDimitry Andric            "Only one Decl argument may be NULL");
19550b57cec5SDimitry Andric 
19560b57cec5SDimitry Andric     if (Same) {
19570b57cec5SDimitry Andric       PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
19580b57cec5SDimitry Andric     } else if (!PrintTree) {
19590b57cec5SDimitry Andric       OS << (FromDefault ? "(default) " : "");
19600b57cec5SDimitry Andric       Bold();
19610b57cec5SDimitry Andric       PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
19620b57cec5SDimitry Andric       Unbold();
19630b57cec5SDimitry Andric     } else {
19640b57cec5SDimitry Andric       OS << (FromDefault ? "[(default) " : "[");
19650b57cec5SDimitry Andric       Bold();
19660b57cec5SDimitry Andric       PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
19670b57cec5SDimitry Andric       Unbold();
19680b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) " : "");
19690b57cec5SDimitry Andric       Bold();
19700b57cec5SDimitry Andric       PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr);
19710b57cec5SDimitry Andric       Unbold();
19720b57cec5SDimitry Andric       OS << ']';
19730b57cec5SDimitry Andric     }
19740b57cec5SDimitry Andric   }
19750b57cec5SDimitry Andric 
19760b57cec5SDimitry Andric   /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and
19770b57cec5SDimitry Andric   /// APSInt to print a mixed difference.
19780b57cec5SDimitry Andric   void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf,
19790b57cec5SDimitry Andric                                 bool IsNullPtr, Expr *VDExpr, bool DefaultDecl,
19800b57cec5SDimitry Andric                                 const llvm::APSInt &Val, QualType IntType,
19810b57cec5SDimitry Andric                                 Expr *IntExpr, bool DefaultInt) {
19820b57cec5SDimitry Andric     if (!PrintTree) {
19830b57cec5SDimitry Andric       OS << (DefaultDecl ? "(default) " : "");
19840b57cec5SDimitry Andric       Bold();
19850b57cec5SDimitry Andric       PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
19860b57cec5SDimitry Andric       Unbold();
19870b57cec5SDimitry Andric     } else {
19880b57cec5SDimitry Andric       OS << (DefaultDecl ? "[(default) " : "[");
19890b57cec5SDimitry Andric       Bold();
19900b57cec5SDimitry Andric       PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
19910b57cec5SDimitry Andric       Unbold();
19920b57cec5SDimitry Andric       OS << " != " << (DefaultInt ? "(default) " : "");
19930b57cec5SDimitry Andric       PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
19940b57cec5SDimitry Andric       OS << ']';
19950b57cec5SDimitry Andric     }
19960b57cec5SDimitry Andric   }
19970b57cec5SDimitry Andric 
19980b57cec5SDimitry Andric   /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and
19990b57cec5SDimitry Andric   /// ValueDecl to print a mixed difference.
20000b57cec5SDimitry Andric   void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType,
20010b57cec5SDimitry Andric                                 Expr *IntExpr, bool DefaultInt, ValueDecl *VD,
20020b57cec5SDimitry Andric                                 bool NeedAddressOf, bool IsNullPtr,
20030b57cec5SDimitry Andric                                 Expr *VDExpr, bool DefaultDecl) {
20040b57cec5SDimitry Andric     if (!PrintTree) {
20050b57cec5SDimitry Andric       OS << (DefaultInt ? "(default) " : "");
20060b57cec5SDimitry Andric       PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
20070b57cec5SDimitry Andric     } else {
20080b57cec5SDimitry Andric       OS << (DefaultInt ? "[(default) " : "[");
20090b57cec5SDimitry Andric       PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
20100b57cec5SDimitry Andric       OS << " != " << (DefaultDecl ? "(default) " : "");
20110b57cec5SDimitry Andric       Bold();
20120b57cec5SDimitry Andric       PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
20130b57cec5SDimitry Andric       Unbold();
20140b57cec5SDimitry Andric       OS << ']';
20150b57cec5SDimitry Andric     }
20160b57cec5SDimitry Andric   }
20170b57cec5SDimitry Andric 
20180b57cec5SDimitry Andric   // Prints the appropriate placeholder for elided template arguments.
20190b57cec5SDimitry Andric   void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
20200b57cec5SDimitry Andric     if (PrintTree) {
20210b57cec5SDimitry Andric       OS << '\n';
20220b57cec5SDimitry Andric       for (unsigned i = 0; i < Indent; ++i)
20230b57cec5SDimitry Andric         OS << "  ";
20240b57cec5SDimitry Andric     }
20250b57cec5SDimitry Andric     if (NumElideArgs == 0) return;
20260b57cec5SDimitry Andric     if (NumElideArgs == 1)
20270b57cec5SDimitry Andric       OS << "[...]";
20280b57cec5SDimitry Andric     else
20290b57cec5SDimitry Andric       OS << "[" << NumElideArgs << " * ...]";
20300b57cec5SDimitry Andric   }
20310b57cec5SDimitry Andric 
20320b57cec5SDimitry Andric   // Prints and highlights differences in Qualifiers.
20330b57cec5SDimitry Andric   void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {
20340b57cec5SDimitry Andric     // Both types have no qualifiers
20350b57cec5SDimitry Andric     if (FromQual.empty() && ToQual.empty())
20360b57cec5SDimitry Andric       return;
20370b57cec5SDimitry Andric 
20380b57cec5SDimitry Andric     // Both types have same qualifiers
20390b57cec5SDimitry Andric     if (FromQual == ToQual) {
20400b57cec5SDimitry Andric       PrintQualifier(FromQual, /*ApplyBold*/false);
20410b57cec5SDimitry Andric       return;
20420b57cec5SDimitry Andric     }
20430b57cec5SDimitry Andric 
20440b57cec5SDimitry Andric     // Find common qualifiers and strip them from FromQual and ToQual.
20450b57cec5SDimitry Andric     Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual,
20460b57cec5SDimitry Andric                                                                ToQual);
20470b57cec5SDimitry Andric 
20480b57cec5SDimitry Andric     // The qualifiers are printed before the template name.
20490b57cec5SDimitry Andric     // Inline printing:
20500b57cec5SDimitry Andric     // The common qualifiers are printed.  Then, qualifiers only in this type
20510b57cec5SDimitry Andric     // are printed and highlighted.  Finally, qualifiers only in the other
20520b57cec5SDimitry Andric     // type are printed and highlighted inside parentheses after "missing".
20530b57cec5SDimitry Andric     // Tree printing:
20540b57cec5SDimitry Andric     // Qualifiers are printed next to each other, inside brackets, and
20550b57cec5SDimitry Andric     // separated by "!=".  The printing order is:
20560b57cec5SDimitry Andric     // common qualifiers, highlighted from qualifiers, "!=",
20570b57cec5SDimitry Andric     // common qualifiers, highlighted to qualifiers
20580b57cec5SDimitry Andric     if (PrintTree) {
20590b57cec5SDimitry Andric       OS << "[";
20600b57cec5SDimitry Andric       if (CommonQual.empty() && FromQual.empty()) {
20610b57cec5SDimitry Andric         Bold();
20620b57cec5SDimitry Andric         OS << "(no qualifiers) ";
20630b57cec5SDimitry Andric         Unbold();
20640b57cec5SDimitry Andric       } else {
20650b57cec5SDimitry Andric         PrintQualifier(CommonQual, /*ApplyBold*/false);
20660b57cec5SDimitry Andric         PrintQualifier(FromQual, /*ApplyBold*/true);
20670b57cec5SDimitry Andric       }
20680b57cec5SDimitry Andric       OS << "!= ";
20690b57cec5SDimitry Andric       if (CommonQual.empty() && ToQual.empty()) {
20700b57cec5SDimitry Andric         Bold();
20710b57cec5SDimitry Andric         OS << "(no qualifiers)";
20720b57cec5SDimitry Andric         Unbold();
20730b57cec5SDimitry Andric       } else {
20740b57cec5SDimitry Andric         PrintQualifier(CommonQual, /*ApplyBold*/false,
20750b57cec5SDimitry Andric                        /*appendSpaceIfNonEmpty*/!ToQual.empty());
20760b57cec5SDimitry Andric         PrintQualifier(ToQual, /*ApplyBold*/true,
20770b57cec5SDimitry Andric                        /*appendSpaceIfNonEmpty*/false);
20780b57cec5SDimitry Andric       }
20790b57cec5SDimitry Andric       OS << "] ";
20800b57cec5SDimitry Andric     } else {
20810b57cec5SDimitry Andric       PrintQualifier(CommonQual, /*ApplyBold*/false);
20820b57cec5SDimitry Andric       PrintQualifier(FromQual, /*ApplyBold*/true);
20830b57cec5SDimitry Andric     }
20840b57cec5SDimitry Andric   }
20850b57cec5SDimitry Andric 
20860b57cec5SDimitry Andric   void PrintQualifier(Qualifiers Q, bool ApplyBold,
20870b57cec5SDimitry Andric                       bool AppendSpaceIfNonEmpty = true) {
20880b57cec5SDimitry Andric     if (Q.empty()) return;
20890b57cec5SDimitry Andric     if (ApplyBold) Bold();
20900b57cec5SDimitry Andric     Q.print(OS, Policy, AppendSpaceIfNonEmpty);
20910b57cec5SDimitry Andric     if (ApplyBold) Unbold();
20920b57cec5SDimitry Andric   }
20930b57cec5SDimitry Andric 
20940b57cec5SDimitry Andric public:
20950b57cec5SDimitry Andric 
20960b57cec5SDimitry Andric   TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType,
20970b57cec5SDimitry Andric                QualType ToType, bool PrintTree, bool PrintFromType,
20980b57cec5SDimitry Andric                bool ElideType, bool ShowColor)
20990b57cec5SDimitry Andric     : Context(Context),
21000b57cec5SDimitry Andric       Policy(Context.getLangOpts()),
21010b57cec5SDimitry Andric       ElideType(ElideType),
21020b57cec5SDimitry Andric       PrintTree(PrintTree),
21030b57cec5SDimitry Andric       ShowColor(ShowColor),
21040b57cec5SDimitry Andric       // When printing a single type, the FromType is the one printed.
21050b57cec5SDimitry Andric       FromTemplateType(PrintFromType ? FromType : ToType),
21060b57cec5SDimitry Andric       ToTemplateType(PrintFromType ? ToType : FromType),
21070b57cec5SDimitry Andric       OS(OS),
21080b57cec5SDimitry Andric       IsBold(false) {
21090b57cec5SDimitry Andric   }
21100b57cec5SDimitry Andric 
21110b57cec5SDimitry Andric   /// DiffTemplate - Start the template type diffing.
21120b57cec5SDimitry Andric   void DiffTemplate() {
21130b57cec5SDimitry Andric     Qualifiers FromQual = FromTemplateType.getQualifiers(),
21140b57cec5SDimitry Andric                ToQual = ToTemplateType.getQualifiers();
21150b57cec5SDimitry Andric 
21160b57cec5SDimitry Andric     const TemplateSpecializationType *FromOrigTST =
21170b57cec5SDimitry Andric         GetTemplateSpecializationType(Context, FromTemplateType);
21180b57cec5SDimitry Andric     const TemplateSpecializationType *ToOrigTST =
21190b57cec5SDimitry Andric         GetTemplateSpecializationType(Context, ToTemplateType);
21200b57cec5SDimitry Andric 
21210b57cec5SDimitry Andric     // Only checking templates.
21220b57cec5SDimitry Andric     if (!FromOrigTST || !ToOrigTST)
21230b57cec5SDimitry Andric       return;
21240b57cec5SDimitry Andric 
21250b57cec5SDimitry Andric     // Different base templates.
21260b57cec5SDimitry Andric     if (!hasSameTemplate(FromOrigTST, ToOrigTST)) {
21270b57cec5SDimitry Andric       return;
21280b57cec5SDimitry Andric     }
21290b57cec5SDimitry Andric 
21300b57cec5SDimitry Andric     FromQual -= QualType(FromOrigTST, 0).getQualifiers();
21310b57cec5SDimitry Andric     ToQual -= QualType(ToOrigTST, 0).getQualifiers();
21320b57cec5SDimitry Andric 
21330b57cec5SDimitry Andric     // Same base template, but different arguments.
21340b57cec5SDimitry Andric     Tree.SetTemplateDiff(FromOrigTST->getTemplateName().getAsTemplateDecl(),
21350b57cec5SDimitry Andric                          ToOrigTST->getTemplateName().getAsTemplateDecl(),
21360b57cec5SDimitry Andric                          FromQual, ToQual, false /*FromDefault*/,
21370b57cec5SDimitry Andric                          false /*ToDefault*/);
21380b57cec5SDimitry Andric 
21390b57cec5SDimitry Andric     DiffTemplate(FromOrigTST, ToOrigTST);
21400b57cec5SDimitry Andric   }
21410b57cec5SDimitry Andric 
21420b57cec5SDimitry Andric   /// Emit - When the two types given are templated types with the same
21430b57cec5SDimitry Andric   /// base template, a string representation of the type difference will be
21440b57cec5SDimitry Andric   /// emitted to the stream and return true.  Otherwise, return false.
21450b57cec5SDimitry Andric   bool Emit() {
21460b57cec5SDimitry Andric     Tree.StartTraverse();
21470b57cec5SDimitry Andric     if (Tree.Empty())
21480b57cec5SDimitry Andric       return false;
21490b57cec5SDimitry Andric 
21500b57cec5SDimitry Andric     TreeToString();
21510b57cec5SDimitry Andric     assert(!IsBold && "Bold is applied to end of string.");
21520b57cec5SDimitry Andric     return true;
21530b57cec5SDimitry Andric   }
21540b57cec5SDimitry Andric }; // end class TemplateDiff
21550b57cec5SDimitry Andric }  // end anonymous namespace
21560b57cec5SDimitry Andric 
21570b57cec5SDimitry Andric /// FormatTemplateTypeDiff - A helper static function to start the template
21580b57cec5SDimitry Andric /// diff and return the properly formatted string.  Returns true if the diff
21590b57cec5SDimitry Andric /// is successful.
21600b57cec5SDimitry Andric static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
21610b57cec5SDimitry Andric                                    QualType ToType, bool PrintTree,
21620b57cec5SDimitry Andric                                    bool PrintFromType, bool ElideType,
21630b57cec5SDimitry Andric                                    bool ShowColors, raw_ostream &OS) {
21640b57cec5SDimitry Andric   if (PrintTree)
21650b57cec5SDimitry Andric     PrintFromType = true;
21660b57cec5SDimitry Andric   TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType,
21670b57cec5SDimitry Andric                   ElideType, ShowColors);
21680b57cec5SDimitry Andric   TD.DiffTemplate();
21690b57cec5SDimitry Andric   return TD.Emit();
21700b57cec5SDimitry Andric }
2171