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.
desugarForDiagnostic(ASTContext & Context,QualType QT,bool & ShouldAKA)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
ConvertTypeToDiagnosticString(ASTContext & Context,QualType Ty,ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,ArrayRef<intptr_t> QualTypeVals)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 
FormatASTNodeDiagnosticArgument(DiagnosticsEngine::ArgumentKind Kind,intptr_t Val,StringRef Modifier,StringRef Argument,ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,SmallVectorImpl<char> & Output,void * Cookie,ArrayRef<intptr_t> QualTypeVals)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 
DiffNode__anon7f70efc60111::TemplateDiff::DiffTree::DiffNode6220b57cec5SDimitry 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:
DiffTree()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.
SetTemplateDiff(TemplateDecl * FromTD,TemplateDecl * ToTD,Qualifiers FromQual,Qualifiers ToQual,bool FromDefault,bool ToDefault)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 
SetTypeDiff(QualType FromType,QualType ToType,bool FromDefault,bool ToDefault)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 
SetExpressionDiff(Expr * FromExpr,Expr * ToExpr,bool FromDefault,bool ToDefault)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 
SetTemplateTemplateDiff(TemplateDecl * FromTD,TemplateDecl * ToTD,bool FromDefault,bool ToDefault)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 
SetIntegerDiff(const llvm::APSInt & FromInt,const llvm::APSInt & ToInt,bool IsValidFromInt,bool IsValidToInt,QualType FromIntType,QualType ToIntType,Expr * FromExpr,Expr * ToExpr,bool FromDefault,bool ToDefault)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 
SetDeclarationDiff(ValueDecl * FromValueDecl,ValueDecl * ToValueDecl,bool FromAddressOf,bool ToAddressOf,bool FromNullPtr,bool ToNullPtr,Expr * FromExpr,Expr * ToExpr,bool FromDefault,bool ToDefault)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 
SetFromDeclarationAndToIntegerDiff(ValueDecl * FromValueDecl,bool FromAddressOf,bool FromNullPtr,Expr * FromExpr,const llvm::APSInt & ToInt,bool IsValidToInt,QualType ToIntType,Expr * ToExpr,bool FromDefault,bool ToDefault)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 
SetFromIntegerAndToDeclarationDiff(const llvm::APSInt & FromInt,bool IsValidFromInt,QualType FromIntType,Expr * FromExpr,ValueDecl * ToValueDecl,bool ToAddressOf,bool ToNullPtr,Expr * ToExpr,bool FromDefault,bool ToDefault)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.
SetDefault(bool FromDefault,bool ToDefault)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.
SetSame(bool Same)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.
SetKind(DiffKind Kind)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.
Up()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.
AddNode()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.
StartTraverse()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.
Parent()8080b57cec5SDimitry Andric     void Parent() {
8090b57cec5SDimitry Andric       ReadNode = FlatTree[ReadNode].ParentNode;
8100b57cec5SDimitry Andric     }
8110b57cec5SDimitry Andric 
GetTemplateDiff(TemplateDecl * & FromTD,TemplateDecl * & ToTD,Qualifiers & FromQual,Qualifiers & ToQual)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 
GetTypeDiff(QualType & FromType,QualType & ToType)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 
GetExpressionDiff(Expr * & FromExpr,Expr * & ToExpr)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 
GetTemplateTemplateDiff(TemplateDecl * & FromTD,TemplateDecl * & ToTD)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 
GetIntegerDiff(llvm::APSInt & FromInt,llvm::APSInt & ToInt,bool & IsValidFromInt,bool & IsValidToInt,QualType & FromIntType,QualType & ToIntType,Expr * & FromExpr,Expr * & ToExpr)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 
GetDeclarationDiff(ValueDecl * & FromValueDecl,ValueDecl * & ToValueDecl,bool & FromAddressOf,bool & ToAddressOf,bool & FromNullPtr,bool & ToNullPtr,Expr * & FromExpr,Expr * & ToExpr)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 
GetFromDeclarationAndToIntegerDiff(ValueDecl * & FromValueDecl,bool & FromAddressOf,bool & FromNullPtr,Expr * & FromExpr,llvm::APSInt & ToInt,bool & IsValidToInt,QualType & ToIntType,Expr * & ToExpr)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 
GetFromIntegerAndToDeclarationDiff(llvm::APSInt & FromInt,bool & IsValidFromInt,QualType & FromIntType,Expr * & FromExpr,ValueDecl * & ToValueDecl,bool & ToAddressOf,bool & ToNullPtr,Expr * & ToExpr)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.
FromDefault()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.
ToDefault()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.
NodeIsSame()9120b57cec5SDimitry Andric     bool NodeIsSame() {
9130b57cec5SDimitry Andric       return FlatTree[ReadNode].Same;
9140b57cec5SDimitry Andric     }
9150b57cec5SDimitry Andric 
9160b57cec5SDimitry Andric     /// HasChildrend - Returns true if the node has children.
HasChildren()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.
MoveToChild()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.
AdvanceSibling()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.
HasNextSibling()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.
Empty()9420b57cec5SDimitry Andric     bool Empty() {
9430b57cec5SDimitry Andric       return GetKind() == Invalid;
9440b57cec5SDimitry Andric     }
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric     /// GetKind - Returns the current node's type.
GetKind()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.
InternalIterator__anon7f70efc60111::TemplateDiff::TSTiterator::InternalIterator9820b57cec5SDimitry 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.
isValid__anon7f70efc60111::TemplateDiff::TSTiterator::InternalIterator10050b57cec5SDimitry Andric       bool isValid() const { return TST; }
10060b57cec5SDimitry Andric 
10070b57cec5SDimitry Andric       /// isEnd - Returns true if the iterator is one past the end.
isEnd__anon7f70efc60111::TemplateDiff::TSTiterator::InternalIterator10080b57cec5SDimitry 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.
operator ++__anon7f70efc60111::TemplateDiff::TSTiterator::InternalIterator10140b57cec5SDimitry 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.
operator *__anon7f70efc60111::TemplateDiff::TSTiterator::InternalIterator10500b57cec5SDimitry 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.
operator ->__anon7f70efc60111::TemplateDiff::TSTiterator::InternalIterator10600b57cec5SDimitry 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:
TSTiterator(ASTContext & Context,const TemplateSpecializationType * TST)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.
operator ++()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.
operator *() const10860b57cec5SDimitry Andric     reference operator*() const {
10870b57cec5SDimitry Andric       return *SugaredIterator;
10880b57cec5SDimitry Andric     }
10890b57cec5SDimitry Andric 
10900b57cec5SDimitry Andric     /// operator-> - Allow access to the underlying TemplateArgument.
operator ->() const10910b57cec5SDimitry Andric     pointer operator->() const {
10920b57cec5SDimitry Andric       return &operator*();
10930b57cec5SDimitry Andric     }
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric     /// isEnd - Returns true if no more TemplateArguments are available.
isEnd() const10960b57cec5SDimitry 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.
hasDesugaredTA() const11020b57cec5SDimitry Andric     bool hasDesugaredTA() const {
11030b57cec5SDimitry Andric       return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();
11040b57cec5SDimitry Andric     }
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric     /// getDesugaredTA - Returns the desugared TemplateArgument.
getDesugaredTA() const11070b57cec5SDimitry 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 
GetTemplateSpecializationType(ASTContext & Context,QualType Ty)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.
OnlyPerformTypeDiff(ASTContext & Context,QualType FromType,QualType ToType,const TemplateSpecializationType * & FromArgTST,const TemplateSpecializationType * & ToArgTST)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.
DiffTypes(const TSTiterator & FromIter,const TSTiterator & ToIter)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.
DiffTemplateTemplates(const TSTiterator & FromIter,const TSTiterator & ToIter)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
InitializeNonTypeDiffVariables(ASTContext & Context,const TSTiterator & Iter,NonTypeTemplateParmDecl * Default,llvm::APSInt & Value,bool & HasInt,QualType & IntType,bool & IsNullPtr,Expr * & E,ValueDecl * & VD,bool & NeedAddressOf)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()) {
12180b57cec5SDimitry Andric         default:
12190b57cec5SDimitry Andric           llvm_unreachable("unknown ArgumentKind");
12200b57cec5SDimitry Andric         case TemplateArgument::Integral:
12210b57cec5SDimitry Andric           Value = Iter->getAsIntegral();
12220b57cec5SDimitry Andric           HasInt = true;
12230b57cec5SDimitry Andric           IntType = Iter->getIntegralType();
12240b57cec5SDimitry Andric           return;
12250b57cec5SDimitry Andric         case TemplateArgument::Declaration: {
12260b57cec5SDimitry Andric           VD = Iter->getAsDecl();
12270b57cec5SDimitry Andric           QualType ArgType = Iter->getParamTypeForDecl();
12280b57cec5SDimitry Andric           QualType VDType = VD->getType();
12290b57cec5SDimitry Andric           if (ArgType->isPointerType() &&
12300b57cec5SDimitry Andric               Context.hasSameType(ArgType->getPointeeType(), VDType))
12310b57cec5SDimitry Andric             NeedAddressOf = true;
12320b57cec5SDimitry Andric           return;
12330b57cec5SDimitry Andric         }
12340b57cec5SDimitry Andric         case TemplateArgument::NullPtr:
12350b57cec5SDimitry Andric           IsNullPtr = true;
12360b57cec5SDimitry Andric           return;
12370b57cec5SDimitry Andric         case TemplateArgument::Expression:
12380b57cec5SDimitry Andric           E = Iter->getAsExpr();
12390b57cec5SDimitry Andric       }
12400b57cec5SDimitry Andric     } else if (!Default->isParameterPack()) {
12410b57cec5SDimitry Andric       E = Default->getDefaultArgument();
12420b57cec5SDimitry Andric     }
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric     if (!Iter.hasDesugaredTA()) return;
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric     const TemplateArgument& TA = Iter.getDesugaredTA();
12470b57cec5SDimitry Andric     switch (TA.getKind()) {
12480b57cec5SDimitry Andric       default:
12490b57cec5SDimitry Andric         llvm_unreachable("unknown ArgumentKind");
12500b57cec5SDimitry Andric       case TemplateArgument::Integral:
12510b57cec5SDimitry Andric         Value = TA.getAsIntegral();
12520b57cec5SDimitry Andric         HasInt = true;
12530b57cec5SDimitry Andric         IntType = TA.getIntegralType();
12540b57cec5SDimitry Andric         return;
12550b57cec5SDimitry Andric       case TemplateArgument::Declaration: {
12560b57cec5SDimitry Andric         VD = TA.getAsDecl();
12570b57cec5SDimitry Andric         QualType ArgType = TA.getParamTypeForDecl();
12580b57cec5SDimitry Andric         QualType VDType = VD->getType();
12590b57cec5SDimitry Andric         if (ArgType->isPointerType() &&
12600b57cec5SDimitry Andric             Context.hasSameType(ArgType->getPointeeType(), VDType))
12610b57cec5SDimitry Andric           NeedAddressOf = true;
12620b57cec5SDimitry Andric         return;
12630b57cec5SDimitry Andric       }
12640b57cec5SDimitry Andric       case TemplateArgument::NullPtr:
12650b57cec5SDimitry Andric         IsNullPtr = true;
12660b57cec5SDimitry Andric         return;
12670b57cec5SDimitry Andric       case TemplateArgument::Expression:
12680b57cec5SDimitry Andric         // TODO: Sometimes, the desugared template argument Expr differs from
12690b57cec5SDimitry Andric         // the sugared template argument Expr.  It may be useful in the future
12700b57cec5SDimitry Andric         // but for now, it is just discarded.
12710b57cec5SDimitry Andric         if (!E)
12720b57cec5SDimitry Andric           E = TA.getAsExpr();
12730b57cec5SDimitry Andric         return;
12740b57cec5SDimitry Andric     }
12750b57cec5SDimitry Andric   }
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric   /// DiffNonTypes - Handles any template parameters not handled by DiffTypes
12780b57cec5SDimitry Andric   /// of DiffTemplatesTemplates, such as integer and declaration parameters.
DiffNonTypes(const TSTiterator & FromIter,const TSTiterator & ToIter,NonTypeTemplateParmDecl * FromDefaultNonTypeDecl,NonTypeTemplateParmDecl * ToDefaultNonTypeDecl)12790b57cec5SDimitry Andric   void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
12800b57cec5SDimitry Andric                     NonTypeTemplateParmDecl *FromDefaultNonTypeDecl,
12810b57cec5SDimitry Andric                     NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) {
12820b57cec5SDimitry Andric     Expr *FromExpr = nullptr, *ToExpr = nullptr;
12830b57cec5SDimitry Andric     llvm::APSInt FromInt, ToInt;
12840b57cec5SDimitry Andric     QualType FromIntType, ToIntType;
12850b57cec5SDimitry Andric     ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
12860b57cec5SDimitry Andric     bool HasFromInt = false, HasToInt = false, FromNullPtr = false,
12870b57cec5SDimitry Andric          ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;
12880b57cec5SDimitry Andric     InitializeNonTypeDiffVariables(
12890b57cec5SDimitry Andric         Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt,
12900b57cec5SDimitry Andric         FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf);
12910b57cec5SDimitry Andric     InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt,
12920b57cec5SDimitry Andric                                    HasToInt, ToIntType, ToNullPtr, ToExpr,
12930b57cec5SDimitry Andric                                    ToValueDecl, NeedToAddressOf);
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric     bool FromDefault = FromIter.isEnd() &&
12960b57cec5SDimitry Andric                        (FromExpr || FromValueDecl || HasFromInt || FromNullPtr);
12970b57cec5SDimitry Andric     bool ToDefault = ToIter.isEnd() &&
12980b57cec5SDimitry Andric                      (ToExpr || ToValueDecl || HasToInt || ToNullPtr);
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric     bool FromDeclaration = FromValueDecl || FromNullPtr;
13010b57cec5SDimitry Andric     bool ToDeclaration = ToValueDecl || ToNullPtr;
13020b57cec5SDimitry Andric 
13030b57cec5SDimitry Andric     if (FromDeclaration && HasToInt) {
13040b57cec5SDimitry Andric       Tree.SetFromDeclarationAndToIntegerDiff(
13050b57cec5SDimitry Andric           FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt,
13060b57cec5SDimitry Andric           HasToInt, ToIntType, ToExpr, FromDefault, ToDefault);
13070b57cec5SDimitry Andric       Tree.SetSame(false);
13080b57cec5SDimitry Andric       return;
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric     }
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric     if (HasFromInt && ToDeclaration) {
13130b57cec5SDimitry Andric       Tree.SetFromIntegerAndToDeclarationDiff(
13140b57cec5SDimitry Andric           FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl,
13150b57cec5SDimitry Andric           NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault);
13160b57cec5SDimitry Andric       Tree.SetSame(false);
13170b57cec5SDimitry Andric       return;
13180b57cec5SDimitry Andric     }
13190b57cec5SDimitry Andric 
13200b57cec5SDimitry Andric     if (HasFromInt || HasToInt) {
13210b57cec5SDimitry Andric       Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,
13220b57cec5SDimitry Andric                           ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);
13230b57cec5SDimitry Andric       if (HasFromInt && HasToInt) {
13240b57cec5SDimitry Andric         Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) &&
13250b57cec5SDimitry Andric                      FromInt == ToInt);
13260b57cec5SDimitry Andric       }
13270b57cec5SDimitry Andric       return;
13280b57cec5SDimitry Andric     }
13290b57cec5SDimitry Andric 
13300b57cec5SDimitry Andric     if (FromDeclaration || ToDeclaration) {
13310b57cec5SDimitry Andric       Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf,
13320b57cec5SDimitry Andric                               NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
13330b57cec5SDimitry Andric                               ToExpr, FromDefault, ToDefault);
13340b57cec5SDimitry Andric       bool BothNull = FromNullPtr && ToNullPtr;
13350b57cec5SDimitry Andric       bool SameValueDecl =
13360b57cec5SDimitry Andric           FromValueDecl && ToValueDecl &&
13370b57cec5SDimitry Andric           NeedFromAddressOf == NeedToAddressOf &&
13380b57cec5SDimitry Andric           FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl();
13390b57cec5SDimitry Andric       Tree.SetSame(BothNull || SameValueDecl);
13400b57cec5SDimitry Andric       return;
13410b57cec5SDimitry Andric     }
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric     assert((FromExpr || ToExpr) && "Both template arguments cannot be empty.");
13440b57cec5SDimitry Andric     Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault);
13450b57cec5SDimitry Andric     Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
13460b57cec5SDimitry Andric   }
13470b57cec5SDimitry Andric 
13480b57cec5SDimitry Andric   /// DiffTemplate - recursively visits template arguments and stores the
13490b57cec5SDimitry Andric   /// argument info into a tree.
DiffTemplate(const TemplateSpecializationType * FromTST,const TemplateSpecializationType * ToTST)13500b57cec5SDimitry Andric   void DiffTemplate(const TemplateSpecializationType *FromTST,
13510b57cec5SDimitry Andric                     const TemplateSpecializationType *ToTST) {
13520b57cec5SDimitry Andric     // Begin descent into diffing template tree.
13530b57cec5SDimitry Andric     TemplateParameterList *ParamsFrom =
13540b57cec5SDimitry Andric         FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
13550b57cec5SDimitry Andric     TemplateParameterList *ParamsTo =
13560b57cec5SDimitry Andric         ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
13570b57cec5SDimitry Andric     unsigned TotalArgs = 0;
13580b57cec5SDimitry Andric     for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST);
13590b57cec5SDimitry Andric          !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {
13600b57cec5SDimitry Andric       Tree.AddNode();
13610b57cec5SDimitry Andric 
13620b57cec5SDimitry Andric       // Get the parameter at index TotalArgs.  If index is larger
13630b57cec5SDimitry Andric       // than the total number of parameters, then there is an
13640b57cec5SDimitry Andric       // argument pack, so re-use the last parameter.
13650b57cec5SDimitry Andric       unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);
13660b57cec5SDimitry Andric       unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1);
13670b57cec5SDimitry Andric       NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex);
13680b57cec5SDimitry Andric       NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex);
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric       assert(FromParamND->getKind() == ToParamND->getKind() &&
13710b57cec5SDimitry Andric              "Parameter Decl are not the same kind.");
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric       if (isa<TemplateTypeParmDecl>(FromParamND)) {
13740b57cec5SDimitry Andric         DiffTypes(FromIter, ToIter);
13750b57cec5SDimitry Andric       } else if (isa<TemplateTemplateParmDecl>(FromParamND)) {
13760b57cec5SDimitry Andric         DiffTemplateTemplates(FromIter, ToIter);
13770b57cec5SDimitry Andric       } else if (isa<NonTypeTemplateParmDecl>(FromParamND)) {
13780b57cec5SDimitry Andric         NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =
13790b57cec5SDimitry Andric             cast<NonTypeTemplateParmDecl>(FromParamND);
13800b57cec5SDimitry Andric         NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =
13810b57cec5SDimitry Andric             cast<NonTypeTemplateParmDecl>(ToParamND);
13820b57cec5SDimitry Andric         DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,
13830b57cec5SDimitry Andric                      ToDefaultNonTypeDecl);
13840b57cec5SDimitry Andric       } else {
13850b57cec5SDimitry Andric         llvm_unreachable("Unexpected Decl type.");
13860b57cec5SDimitry Andric       }
13870b57cec5SDimitry Andric 
13880b57cec5SDimitry Andric       ++FromIter;
13890b57cec5SDimitry Andric       ++ToIter;
13900b57cec5SDimitry Andric       Tree.Up();
13910b57cec5SDimitry Andric     }
13920b57cec5SDimitry Andric   }
13930b57cec5SDimitry Andric 
13940b57cec5SDimitry Andric   /// makeTemplateList - Dump every template alias into the vector.
makeTemplateList(SmallVectorImpl<const TemplateSpecializationType * > & TemplateList,const TemplateSpecializationType * TST)13950b57cec5SDimitry Andric   static void makeTemplateList(
13960b57cec5SDimitry Andric       SmallVectorImpl<const TemplateSpecializationType *> &TemplateList,
13970b57cec5SDimitry Andric       const TemplateSpecializationType *TST) {
13980b57cec5SDimitry Andric     while (TST) {
13990b57cec5SDimitry Andric       TemplateList.push_back(TST);
14000b57cec5SDimitry Andric       if (!TST->isTypeAlias())
14010b57cec5SDimitry Andric         return;
14020b57cec5SDimitry Andric       TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
14030b57cec5SDimitry Andric     }
14040b57cec5SDimitry Andric   }
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric   /// hasSameBaseTemplate - Returns true when the base templates are the same,
14070b57cec5SDimitry Andric   /// even if the template arguments are not.
hasSameBaseTemplate(const TemplateSpecializationType * FromTST,const TemplateSpecializationType * ToTST)14080b57cec5SDimitry Andric   static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST,
14090b57cec5SDimitry Andric                                   const TemplateSpecializationType *ToTST) {
14100b57cec5SDimitry Andric     return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() ==
14110b57cec5SDimitry Andric            ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl();
14120b57cec5SDimitry Andric   }
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric   /// hasSameTemplate - Returns true if both types are specialized from the
14150b57cec5SDimitry Andric   /// same template declaration.  If they come from different template aliases,
14160b57cec5SDimitry Andric   /// do a parallel ascension search to determine the highest template alias in
14170b57cec5SDimitry Andric   /// common and set the arguments to them.
hasSameTemplate(const TemplateSpecializationType * & FromTST,const TemplateSpecializationType * & ToTST)14180b57cec5SDimitry Andric   static bool hasSameTemplate(const TemplateSpecializationType *&FromTST,
14190b57cec5SDimitry Andric                               const TemplateSpecializationType *&ToTST) {
14200b57cec5SDimitry Andric     // Check the top templates if they are the same.
14210b57cec5SDimitry Andric     if (hasSameBaseTemplate(FromTST, ToTST))
14220b57cec5SDimitry Andric       return true;
14230b57cec5SDimitry Andric 
14240b57cec5SDimitry Andric     // Create vectors of template aliases.
14250b57cec5SDimitry Andric     SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,
14260b57cec5SDimitry Andric                                                       ToTemplateList;
14270b57cec5SDimitry Andric 
14280b57cec5SDimitry Andric     makeTemplateList(FromTemplateList, FromTST);
14290b57cec5SDimitry Andric     makeTemplateList(ToTemplateList, ToTST);
14300b57cec5SDimitry Andric 
14310b57cec5SDimitry Andric     SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator
14320b57cec5SDimitry Andric         FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),
14330b57cec5SDimitry Andric         ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();
14340b57cec5SDimitry Andric 
14350b57cec5SDimitry Andric     // Check if the lowest template types are the same.  If not, return.
14360b57cec5SDimitry Andric     if (!hasSameBaseTemplate(*FromIter, *ToIter))
14370b57cec5SDimitry Andric       return false;
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric     // Begin searching up the template aliases.  The bottom most template
14400b57cec5SDimitry Andric     // matches so move up until one pair does not match.  Use the template
14410b57cec5SDimitry Andric     // right before that one.
14420b57cec5SDimitry Andric     for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {
14430b57cec5SDimitry Andric       if (!hasSameBaseTemplate(*FromIter, *ToIter))
14440b57cec5SDimitry Andric         break;
14450b57cec5SDimitry Andric     }
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric     FromTST = FromIter[-1];
14480b57cec5SDimitry Andric     ToTST = ToIter[-1];
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric     return true;
14510b57cec5SDimitry Andric   }
14520b57cec5SDimitry Andric 
14530b57cec5SDimitry Andric   /// GetType - Retrieves the template type arguments, including default
14540b57cec5SDimitry Andric   /// arguments.
GetType(const TSTiterator & Iter)14550b57cec5SDimitry Andric   static QualType GetType(const TSTiterator &Iter) {
14560b57cec5SDimitry Andric     if (!Iter.isEnd())
14570b57cec5SDimitry Andric       return Iter->getAsType();
14580b57cec5SDimitry Andric     if (Iter.hasDesugaredTA())
14590b57cec5SDimitry Andric       return Iter.getDesugaredTA().getAsType();
14600b57cec5SDimitry Andric     return QualType();
14610b57cec5SDimitry Andric   }
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric   /// GetTemplateDecl - Retrieves the template template arguments, including
14640b57cec5SDimitry Andric   /// default arguments.
GetTemplateDecl(const TSTiterator & Iter)14650b57cec5SDimitry Andric   static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) {
14660b57cec5SDimitry Andric     if (!Iter.isEnd())
14670b57cec5SDimitry Andric       return Iter->getAsTemplate().getAsTemplateDecl();
14680b57cec5SDimitry Andric     if (Iter.hasDesugaredTA())
14690b57cec5SDimitry Andric       return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl();
14700b57cec5SDimitry Andric     return nullptr;
14710b57cec5SDimitry Andric   }
14720b57cec5SDimitry Andric 
14730b57cec5SDimitry Andric   /// IsEqualExpr - Returns true if the expressions are the same in regards to
14740b57cec5SDimitry Andric   /// template arguments.  These expressions are dependent, so profile them
14750b57cec5SDimitry Andric   /// instead of trying to evaluate them.
IsEqualExpr(ASTContext & Context,Expr * FromExpr,Expr * ToExpr)14760b57cec5SDimitry Andric   static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {
14770b57cec5SDimitry Andric     if (FromExpr == ToExpr)
14780b57cec5SDimitry Andric       return true;
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric     if (!FromExpr || !ToExpr)
14810b57cec5SDimitry Andric       return false;
14820b57cec5SDimitry Andric 
14830b57cec5SDimitry Andric     llvm::FoldingSetNodeID FromID, ToID;
14840b57cec5SDimitry Andric     FromExpr->Profile(FromID, Context, true);
14850b57cec5SDimitry Andric     ToExpr->Profile(ToID, Context, true);
14860b57cec5SDimitry Andric     return FromID == ToID;
14870b57cec5SDimitry Andric   }
14880b57cec5SDimitry Andric 
14890b57cec5SDimitry Andric   // These functions converts the tree representation of the template
14900b57cec5SDimitry Andric   // differences into the internal character vector.
14910b57cec5SDimitry Andric 
14920b57cec5SDimitry Andric   /// TreeToString - Converts the Tree object into a character stream which
14930b57cec5SDimitry Andric   /// will later be turned into the output string.
TreeToString(int Indent=1)14940b57cec5SDimitry Andric   void TreeToString(int Indent = 1) {
14950b57cec5SDimitry Andric     if (PrintTree) {
14960b57cec5SDimitry Andric       OS << '\n';
14970b57cec5SDimitry Andric       OS.indent(2 * Indent);
14980b57cec5SDimitry Andric       ++Indent;
14990b57cec5SDimitry Andric     }
15000b57cec5SDimitry Andric 
15010b57cec5SDimitry Andric     // Handle cases where the difference is not templates with different
15020b57cec5SDimitry Andric     // arguments.
15030b57cec5SDimitry Andric     switch (Tree.GetKind()) {
15040b57cec5SDimitry Andric       case DiffTree::Invalid:
15050b57cec5SDimitry Andric         llvm_unreachable("Template diffing failed with bad DiffNode");
15060b57cec5SDimitry Andric       case DiffTree::Type: {
15070b57cec5SDimitry Andric         QualType FromType, ToType;
15080b57cec5SDimitry Andric         Tree.GetTypeDiff(FromType, ToType);
15090b57cec5SDimitry Andric         PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),
15100b57cec5SDimitry Andric                        Tree.NodeIsSame());
15110b57cec5SDimitry Andric         return;
15120b57cec5SDimitry Andric       }
15130b57cec5SDimitry Andric       case DiffTree::Expression: {
15140b57cec5SDimitry Andric         Expr *FromExpr, *ToExpr;
15150b57cec5SDimitry Andric         Tree.GetExpressionDiff(FromExpr, ToExpr);
15160b57cec5SDimitry Andric         PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
15170b57cec5SDimitry Andric                   Tree.NodeIsSame());
15180b57cec5SDimitry Andric         return;
15190b57cec5SDimitry Andric       }
15200b57cec5SDimitry Andric       case DiffTree::TemplateTemplate: {
15210b57cec5SDimitry Andric         TemplateDecl *FromTD, *ToTD;
15220b57cec5SDimitry Andric         Tree.GetTemplateTemplateDiff(FromTD, ToTD);
15230b57cec5SDimitry Andric         PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),
15240b57cec5SDimitry Andric                               Tree.ToDefault(), Tree.NodeIsSame());
15250b57cec5SDimitry Andric         return;
15260b57cec5SDimitry Andric       }
15270b57cec5SDimitry Andric       case DiffTree::Integer: {
15280b57cec5SDimitry Andric         llvm::APSInt FromInt, ToInt;
15290b57cec5SDimitry Andric         Expr *FromExpr, *ToExpr;
15300b57cec5SDimitry Andric         bool IsValidFromInt, IsValidToInt;
15310b57cec5SDimitry Andric         QualType FromIntType, ToIntType;
15320b57cec5SDimitry Andric         Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,
15330b57cec5SDimitry Andric                             FromIntType, ToIntType, FromExpr, ToExpr);
15340b57cec5SDimitry Andric         PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,
15350b57cec5SDimitry Andric                     ToIntType, FromExpr, ToExpr, Tree.FromDefault(),
15360b57cec5SDimitry Andric                     Tree.ToDefault(), Tree.NodeIsSame());
15370b57cec5SDimitry Andric         return;
15380b57cec5SDimitry Andric       }
15390b57cec5SDimitry Andric       case DiffTree::Declaration: {
15400b57cec5SDimitry Andric         ValueDecl *FromValueDecl, *ToValueDecl;
15410b57cec5SDimitry Andric         bool FromAddressOf, ToAddressOf;
15420b57cec5SDimitry Andric         bool FromNullPtr, ToNullPtr;
15430b57cec5SDimitry Andric         Expr *FromExpr, *ToExpr;
15440b57cec5SDimitry Andric         Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf,
15450b57cec5SDimitry Andric                                 ToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
15460b57cec5SDimitry Andric                                 ToExpr);
15470b57cec5SDimitry Andric         PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
15480b57cec5SDimitry Andric                        FromNullPtr, ToNullPtr, FromExpr, ToExpr,
15490b57cec5SDimitry Andric                        Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
15500b57cec5SDimitry Andric         return;
15510b57cec5SDimitry Andric       }
15520b57cec5SDimitry Andric       case DiffTree::FromDeclarationAndToInteger: {
15530b57cec5SDimitry Andric         ValueDecl *FromValueDecl;
15540b57cec5SDimitry Andric         bool FromAddressOf;
15550b57cec5SDimitry Andric         bool FromNullPtr;
15560b57cec5SDimitry Andric         Expr *FromExpr;
15570b57cec5SDimitry Andric         llvm::APSInt ToInt;
15580b57cec5SDimitry Andric         bool IsValidToInt;
15590b57cec5SDimitry Andric         QualType ToIntType;
15600b57cec5SDimitry Andric         Expr *ToExpr;
15610b57cec5SDimitry Andric         Tree.GetFromDeclarationAndToIntegerDiff(
15620b57cec5SDimitry Andric             FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt,
15630b57cec5SDimitry Andric             IsValidToInt, ToIntType, ToExpr);
15640b57cec5SDimitry Andric         assert((FromValueDecl || FromNullPtr) && IsValidToInt);
15650b57cec5SDimitry Andric         PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr,
15660b57cec5SDimitry Andric                                  FromExpr, Tree.FromDefault(), ToInt, ToIntType,
15670b57cec5SDimitry Andric                                  ToExpr, Tree.ToDefault());
15680b57cec5SDimitry Andric         return;
15690b57cec5SDimitry Andric       }
15700b57cec5SDimitry Andric       case DiffTree::FromIntegerAndToDeclaration: {
15710b57cec5SDimitry Andric         llvm::APSInt FromInt;
15720b57cec5SDimitry Andric         bool IsValidFromInt;
15730b57cec5SDimitry Andric         QualType FromIntType;
15740b57cec5SDimitry Andric         Expr *FromExpr;
15750b57cec5SDimitry Andric         ValueDecl *ToValueDecl;
15760b57cec5SDimitry Andric         bool ToAddressOf;
15770b57cec5SDimitry Andric         bool ToNullPtr;
15780b57cec5SDimitry Andric         Expr *ToExpr;
15790b57cec5SDimitry Andric         Tree.GetFromIntegerAndToDeclarationDiff(
15800b57cec5SDimitry Andric             FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl,
15810b57cec5SDimitry Andric             ToAddressOf, ToNullPtr, ToExpr);
15820b57cec5SDimitry Andric         assert(IsValidFromInt && (ToValueDecl || ToNullPtr));
15830b57cec5SDimitry Andric         PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr,
15840b57cec5SDimitry Andric                                  Tree.FromDefault(), ToValueDecl, ToAddressOf,
15850b57cec5SDimitry Andric                                  ToNullPtr, ToExpr, Tree.ToDefault());
15860b57cec5SDimitry Andric         return;
15870b57cec5SDimitry Andric       }
15880b57cec5SDimitry Andric       case DiffTree::Template: {
15890b57cec5SDimitry Andric         // Node is root of template.  Recurse on children.
15900b57cec5SDimitry Andric         TemplateDecl *FromTD, *ToTD;
15910b57cec5SDimitry Andric         Qualifiers FromQual, ToQual;
15920b57cec5SDimitry Andric         Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual);
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric         PrintQualifiers(FromQual, ToQual);
15950b57cec5SDimitry Andric 
15960b57cec5SDimitry Andric         if (!Tree.HasChildren()) {
15970b57cec5SDimitry Andric           // If we're dealing with a template specialization with zero
15980b57cec5SDimitry Andric           // arguments, there are no children; special-case this.
1599e8d8bef9SDimitry Andric           OS << FromTD->getDeclName() << "<>";
16000b57cec5SDimitry Andric           return;
16010b57cec5SDimitry Andric         }
16020b57cec5SDimitry Andric 
1603e8d8bef9SDimitry Andric         OS << FromTD->getDeclName() << '<';
16040b57cec5SDimitry Andric         Tree.MoveToChild();
16050b57cec5SDimitry Andric         unsigned NumElideArgs = 0;
16060b57cec5SDimitry Andric         bool AllArgsElided = true;
16070b57cec5SDimitry Andric         do {
16080b57cec5SDimitry Andric           if (ElideType) {
16090b57cec5SDimitry Andric             if (Tree.NodeIsSame()) {
16100b57cec5SDimitry Andric               ++NumElideArgs;
16110b57cec5SDimitry Andric               continue;
16120b57cec5SDimitry Andric             }
16130b57cec5SDimitry Andric             AllArgsElided = false;
16140b57cec5SDimitry Andric             if (NumElideArgs > 0) {
16150b57cec5SDimitry Andric               PrintElideArgs(NumElideArgs, Indent);
16160b57cec5SDimitry Andric               NumElideArgs = 0;
16170b57cec5SDimitry Andric               OS << ", ";
16180b57cec5SDimitry Andric             }
16190b57cec5SDimitry Andric           }
16200b57cec5SDimitry Andric           TreeToString(Indent);
16210b57cec5SDimitry Andric           if (Tree.HasNextSibling())
16220b57cec5SDimitry Andric             OS << ", ";
16230b57cec5SDimitry Andric         } while (Tree.AdvanceSibling());
16240b57cec5SDimitry Andric         if (NumElideArgs > 0) {
16250b57cec5SDimitry Andric           if (AllArgsElided)
16260b57cec5SDimitry Andric             OS << "...";
16270b57cec5SDimitry Andric           else
16280b57cec5SDimitry Andric             PrintElideArgs(NumElideArgs, Indent);
16290b57cec5SDimitry Andric         }
16300b57cec5SDimitry Andric 
16310b57cec5SDimitry Andric         Tree.Parent();
16320b57cec5SDimitry Andric         OS << ">";
16330b57cec5SDimitry Andric         return;
16340b57cec5SDimitry Andric       }
16350b57cec5SDimitry Andric     }
16360b57cec5SDimitry Andric   }
16370b57cec5SDimitry Andric 
16380b57cec5SDimitry Andric   // To signal to the text printer that a certain text needs to be bolded,
16390b57cec5SDimitry Andric   // a special character is injected into the character stream which the
16400b57cec5SDimitry Andric   // text printer will later strip out.
16410b57cec5SDimitry Andric 
16420b57cec5SDimitry Andric   /// Bold - Start bolding text.
Bold()16430b57cec5SDimitry Andric   void Bold() {
16440b57cec5SDimitry Andric     assert(!IsBold && "Attempting to bold text that is already bold.");
16450b57cec5SDimitry Andric     IsBold = true;
16460b57cec5SDimitry Andric     if (ShowColor)
16470b57cec5SDimitry Andric       OS << ToggleHighlight;
16480b57cec5SDimitry Andric   }
16490b57cec5SDimitry Andric 
16500b57cec5SDimitry Andric   /// Unbold - Stop bolding text.
Unbold()16510b57cec5SDimitry Andric   void Unbold() {
16520b57cec5SDimitry Andric     assert(IsBold && "Attempting to remove bold from unbold text.");
16530b57cec5SDimitry Andric     IsBold = false;
16540b57cec5SDimitry Andric     if (ShowColor)
16550b57cec5SDimitry Andric       OS << ToggleHighlight;
16560b57cec5SDimitry Andric   }
16570b57cec5SDimitry Andric 
16580b57cec5SDimitry Andric   // Functions to print out the arguments and highlighting the difference.
16590b57cec5SDimitry Andric 
16600b57cec5SDimitry Andric   /// PrintTypeNames - prints the typenames, bolding differences.  Will detect
16610b57cec5SDimitry Andric   /// typenames that are the same and attempt to disambiguate them by using
16620b57cec5SDimitry Andric   /// canonical typenames.
PrintTypeNames(QualType FromType,QualType ToType,bool FromDefault,bool ToDefault,bool Same)16630b57cec5SDimitry Andric   void PrintTypeNames(QualType FromType, QualType ToType,
16640b57cec5SDimitry Andric                       bool FromDefault, bool ToDefault, bool Same) {
16650b57cec5SDimitry Andric     assert((!FromType.isNull() || !ToType.isNull()) &&
16660b57cec5SDimitry Andric            "Only one template argument may be missing.");
16670b57cec5SDimitry Andric 
16680b57cec5SDimitry Andric     if (Same) {
16690b57cec5SDimitry Andric       OS << FromType.getAsString(Policy);
16700b57cec5SDimitry Andric       return;
16710b57cec5SDimitry Andric     }
16720b57cec5SDimitry Andric 
16730b57cec5SDimitry Andric     if (!FromType.isNull() && !ToType.isNull() &&
16740b57cec5SDimitry Andric         FromType.getLocalUnqualifiedType() ==
16750b57cec5SDimitry Andric         ToType.getLocalUnqualifiedType()) {
16760b57cec5SDimitry Andric       Qualifiers FromQual = FromType.getLocalQualifiers(),
16770b57cec5SDimitry Andric                  ToQual = ToType.getLocalQualifiers();
16780b57cec5SDimitry Andric       PrintQualifiers(FromQual, ToQual);
16790b57cec5SDimitry Andric       FromType.getLocalUnqualifiedType().print(OS, Policy);
16800b57cec5SDimitry Andric       return;
16810b57cec5SDimitry Andric     }
16820b57cec5SDimitry Andric 
16830b57cec5SDimitry Andric     std::string FromTypeStr = FromType.isNull() ? "(no argument)"
16840b57cec5SDimitry Andric                                                 : FromType.getAsString(Policy);
16850b57cec5SDimitry Andric     std::string ToTypeStr = ToType.isNull() ? "(no argument)"
16860b57cec5SDimitry Andric                                             : ToType.getAsString(Policy);
1687bdd1243dSDimitry Andric     // Print without ElaboratedType sugar if it is better.
16880b57cec5SDimitry Andric     // TODO: merge this with other aka printing above.
16890b57cec5SDimitry Andric     if (FromTypeStr == ToTypeStr) {
1690bdd1243dSDimitry Andric       const auto *FromElTy = dyn_cast<ElaboratedType>(FromType),
1691bdd1243dSDimitry Andric                  *ToElTy = dyn_cast<ElaboratedType>(ToType);
1692bdd1243dSDimitry Andric       if (FromElTy || ToElTy) {
1693bdd1243dSDimitry Andric         std::string FromNamedTypeStr =
1694bdd1243dSDimitry Andric             FromElTy ? FromElTy->getNamedType().getAsString(Policy)
1695bdd1243dSDimitry Andric                      : FromTypeStr;
1696bdd1243dSDimitry Andric         std::string ToNamedTypeStr =
1697bdd1243dSDimitry Andric             ToElTy ? ToElTy->getNamedType().getAsString(Policy) : ToTypeStr;
1698bdd1243dSDimitry Andric         if (FromNamedTypeStr != ToNamedTypeStr) {
1699bdd1243dSDimitry Andric           FromTypeStr = FromNamedTypeStr;
1700bdd1243dSDimitry Andric           ToTypeStr = ToNamedTypeStr;
1701bdd1243dSDimitry Andric           goto PrintTypes;
1702bdd1243dSDimitry Andric         }
1703bdd1243dSDimitry Andric       }
1704bdd1243dSDimitry Andric       // Switch to canonical typename if it is better.
17050b57cec5SDimitry Andric       std::string FromCanTypeStr =
17060b57cec5SDimitry Andric           FromType.getCanonicalType().getAsString(Policy);
17070b57cec5SDimitry Andric       std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy);
17080b57cec5SDimitry Andric       if (FromCanTypeStr != ToCanTypeStr) {
17090b57cec5SDimitry Andric         FromTypeStr = FromCanTypeStr;
17100b57cec5SDimitry Andric         ToTypeStr = ToCanTypeStr;
17110b57cec5SDimitry Andric       }
17120b57cec5SDimitry Andric     }
17130b57cec5SDimitry Andric 
1714bdd1243dSDimitry Andric   PrintTypes:
17150b57cec5SDimitry Andric     if (PrintTree) OS << '[';
17160b57cec5SDimitry Andric     OS << (FromDefault ? "(default) " : "");
17170b57cec5SDimitry Andric     Bold();
17180b57cec5SDimitry Andric     OS << FromTypeStr;
17190b57cec5SDimitry Andric     Unbold();
17200b57cec5SDimitry Andric     if (PrintTree) {
17210b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) " : "");
17220b57cec5SDimitry Andric       Bold();
17230b57cec5SDimitry Andric       OS << ToTypeStr;
17240b57cec5SDimitry Andric       Unbold();
17250b57cec5SDimitry Andric       OS << "]";
17260b57cec5SDimitry Andric     }
17270b57cec5SDimitry Andric   }
17280b57cec5SDimitry Andric 
17290b57cec5SDimitry Andric   /// PrintExpr - Prints out the expr template arguments, highlighting argument
17300b57cec5SDimitry Andric   /// differences.
PrintExpr(const Expr * FromExpr,const Expr * ToExpr,bool FromDefault,bool ToDefault,bool Same)17310b57cec5SDimitry Andric   void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault,
17320b57cec5SDimitry Andric                  bool ToDefault, bool Same) {
17330b57cec5SDimitry Andric     assert((FromExpr || ToExpr) &&
17340b57cec5SDimitry Andric             "Only one template argument may be missing.");
17350b57cec5SDimitry Andric     if (Same) {
17360b57cec5SDimitry Andric       PrintExpr(FromExpr);
17370b57cec5SDimitry Andric     } else if (!PrintTree) {
17380b57cec5SDimitry Andric       OS << (FromDefault ? "(default) " : "");
17390b57cec5SDimitry Andric       Bold();
17400b57cec5SDimitry Andric       PrintExpr(FromExpr);
17410b57cec5SDimitry Andric       Unbold();
17420b57cec5SDimitry Andric     } else {
17430b57cec5SDimitry Andric       OS << (FromDefault ? "[(default) " : "[");
17440b57cec5SDimitry Andric       Bold();
17450b57cec5SDimitry Andric       PrintExpr(FromExpr);
17460b57cec5SDimitry Andric       Unbold();
17470b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) " : "");
17480b57cec5SDimitry Andric       Bold();
17490b57cec5SDimitry Andric       PrintExpr(ToExpr);
17500b57cec5SDimitry Andric       Unbold();
17510b57cec5SDimitry Andric       OS << ']';
17520b57cec5SDimitry Andric     }
17530b57cec5SDimitry Andric   }
17540b57cec5SDimitry Andric 
17550b57cec5SDimitry Andric   /// PrintExpr - Actual formatting and printing of expressions.
PrintExpr(const Expr * E)17560b57cec5SDimitry Andric   void PrintExpr(const Expr *E) {
17570b57cec5SDimitry Andric     if (E) {
17580b57cec5SDimitry Andric       E->printPretty(OS, nullptr, Policy);
17590b57cec5SDimitry Andric       return;
17600b57cec5SDimitry Andric     }
17610b57cec5SDimitry Andric     OS << "(no argument)";
17620b57cec5SDimitry Andric   }
17630b57cec5SDimitry Andric 
17640b57cec5SDimitry Andric   /// PrintTemplateTemplate - Handles printing of template template arguments,
17650b57cec5SDimitry Andric   /// highlighting argument differences.
PrintTemplateTemplate(TemplateDecl * FromTD,TemplateDecl * ToTD,bool FromDefault,bool ToDefault,bool Same)17660b57cec5SDimitry Andric   void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,
17670b57cec5SDimitry Andric                              bool FromDefault, bool ToDefault, bool Same) {
17680b57cec5SDimitry Andric     assert((FromTD || ToTD) && "Only one template argument may be missing.");
17690b57cec5SDimitry Andric 
17705ffd83dbSDimitry Andric     std::string FromName =
17715ffd83dbSDimitry Andric         std::string(FromTD ? FromTD->getName() : "(no argument)");
17725ffd83dbSDimitry Andric     std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");
17730b57cec5SDimitry Andric     if (FromTD && ToTD && FromName == ToName) {
17740b57cec5SDimitry Andric       FromName = FromTD->getQualifiedNameAsString();
17750b57cec5SDimitry Andric       ToName = ToTD->getQualifiedNameAsString();
17760b57cec5SDimitry Andric     }
17770b57cec5SDimitry Andric 
17780b57cec5SDimitry Andric     if (Same) {
1779e8d8bef9SDimitry Andric       OS << "template " << FromTD->getDeclName();
17800b57cec5SDimitry Andric     } else if (!PrintTree) {
17810b57cec5SDimitry Andric       OS << (FromDefault ? "(default) template " : "template ");
17820b57cec5SDimitry Andric       Bold();
17830b57cec5SDimitry Andric       OS << FromName;
17840b57cec5SDimitry Andric       Unbold();
17850b57cec5SDimitry Andric     } else {
17860b57cec5SDimitry Andric       OS << (FromDefault ? "[(default) template " : "[template ");
17870b57cec5SDimitry Andric       Bold();
17880b57cec5SDimitry Andric       OS << FromName;
17890b57cec5SDimitry Andric       Unbold();
17900b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) template " : "template ");
17910b57cec5SDimitry Andric       Bold();
17920b57cec5SDimitry Andric       OS << ToName;
17930b57cec5SDimitry Andric       Unbold();
17940b57cec5SDimitry Andric       OS << ']';
17950b57cec5SDimitry Andric     }
17960b57cec5SDimitry Andric   }
17970b57cec5SDimitry Andric 
17980b57cec5SDimitry Andric   /// PrintAPSInt - Handles printing of integral arguments, highlighting
17990b57cec5SDimitry Andric   /// argument differences.
PrintAPSInt(const llvm::APSInt & FromInt,const llvm::APSInt & ToInt,bool IsValidFromInt,bool IsValidToInt,QualType FromIntType,QualType ToIntType,Expr * FromExpr,Expr * ToExpr,bool FromDefault,bool ToDefault,bool Same)18000b57cec5SDimitry Andric   void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
18010b57cec5SDimitry Andric                    bool IsValidFromInt, bool IsValidToInt, QualType FromIntType,
18020b57cec5SDimitry Andric                    QualType ToIntType, Expr *FromExpr, Expr *ToExpr,
18030b57cec5SDimitry Andric                    bool FromDefault, bool ToDefault, bool Same) {
18040b57cec5SDimitry Andric     assert((IsValidFromInt || IsValidToInt) &&
18050b57cec5SDimitry Andric            "Only one integral argument may be missing.");
18060b57cec5SDimitry Andric 
18070b57cec5SDimitry Andric     if (Same) {
18080b57cec5SDimitry Andric       if (FromIntType->isBooleanType()) {
18090b57cec5SDimitry Andric         OS << ((FromInt == 0) ? "false" : "true");
18100b57cec5SDimitry Andric       } else {
1811fe6060f1SDimitry Andric         OS << toString(FromInt, 10);
18120b57cec5SDimitry Andric       }
18130b57cec5SDimitry Andric       return;
18140b57cec5SDimitry Andric     }
18150b57cec5SDimitry Andric 
18160b57cec5SDimitry Andric     bool PrintType = IsValidFromInt && IsValidToInt &&
18170b57cec5SDimitry Andric                      !Context.hasSameType(FromIntType, ToIntType);
18180b57cec5SDimitry Andric 
18190b57cec5SDimitry Andric     if (!PrintTree) {
18200b57cec5SDimitry Andric       OS << (FromDefault ? "(default) " : "");
18210b57cec5SDimitry Andric       PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
18220b57cec5SDimitry Andric     } else {
18230b57cec5SDimitry Andric       OS << (FromDefault ? "[(default) " : "[");
18240b57cec5SDimitry Andric       PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
18250b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) " : "");
18260b57cec5SDimitry Andric       PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType);
18270b57cec5SDimitry Andric       OS << ']';
18280b57cec5SDimitry Andric     }
18290b57cec5SDimitry Andric   }
18300b57cec5SDimitry Andric 
18310b57cec5SDimitry Andric   /// PrintAPSInt - If valid, print the APSInt.  If the expression is
18320b57cec5SDimitry Andric   /// gives more information, print it too.
PrintAPSInt(const llvm::APSInt & Val,Expr * E,bool Valid,QualType IntType,bool PrintType)18330b57cec5SDimitry Andric   void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid,
18340b57cec5SDimitry Andric                    QualType IntType, bool PrintType) {
18350b57cec5SDimitry Andric     Bold();
18360b57cec5SDimitry Andric     if (Valid) {
18370b57cec5SDimitry Andric       if (HasExtraInfo(E)) {
18380b57cec5SDimitry Andric         PrintExpr(E);
18390b57cec5SDimitry Andric         Unbold();
18400b57cec5SDimitry Andric         OS << " aka ";
18410b57cec5SDimitry Andric         Bold();
18420b57cec5SDimitry Andric       }
18430b57cec5SDimitry Andric       if (PrintType) {
18440b57cec5SDimitry Andric         Unbold();
18450b57cec5SDimitry Andric         OS << "(";
18460b57cec5SDimitry Andric         Bold();
18470b57cec5SDimitry Andric         IntType.print(OS, Context.getPrintingPolicy());
18480b57cec5SDimitry Andric         Unbold();
18490b57cec5SDimitry Andric         OS << ") ";
18500b57cec5SDimitry Andric         Bold();
18510b57cec5SDimitry Andric       }
18520b57cec5SDimitry Andric       if (IntType->isBooleanType()) {
18530b57cec5SDimitry Andric         OS << ((Val == 0) ? "false" : "true");
18540b57cec5SDimitry Andric       } else {
1855fe6060f1SDimitry Andric         OS << toString(Val, 10);
18560b57cec5SDimitry Andric       }
18570b57cec5SDimitry Andric     } else if (E) {
18580b57cec5SDimitry Andric       PrintExpr(E);
18590b57cec5SDimitry Andric     } else {
18600b57cec5SDimitry Andric       OS << "(no argument)";
18610b57cec5SDimitry Andric     }
18620b57cec5SDimitry Andric     Unbold();
18630b57cec5SDimitry Andric   }
18640b57cec5SDimitry Andric 
18650b57cec5SDimitry Andric   /// HasExtraInfo - Returns true if E is not an integer literal, the
18660b57cec5SDimitry Andric   /// negation of an integer literal, or a boolean literal.
HasExtraInfo(Expr * E)18670b57cec5SDimitry Andric   bool HasExtraInfo(Expr *E) {
18680b57cec5SDimitry Andric     if (!E) return false;
18690b57cec5SDimitry Andric 
18700b57cec5SDimitry Andric     E = E->IgnoreImpCasts();
18710b57cec5SDimitry Andric 
18720b57cec5SDimitry Andric     if (isa<IntegerLiteral>(E)) return false;
18730b57cec5SDimitry Andric 
18740b57cec5SDimitry Andric     if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))
18750b57cec5SDimitry Andric       if (UO->getOpcode() == UO_Minus)
18760b57cec5SDimitry Andric         if (isa<IntegerLiteral>(UO->getSubExpr()))
18770b57cec5SDimitry Andric           return false;
18780b57cec5SDimitry Andric 
18790b57cec5SDimitry Andric     if (isa<CXXBoolLiteralExpr>(E))
18800b57cec5SDimitry Andric       return false;
18810b57cec5SDimitry Andric 
18820b57cec5SDimitry Andric     return true;
18830b57cec5SDimitry Andric   }
18840b57cec5SDimitry Andric 
PrintValueDecl(ValueDecl * VD,bool AddressOf,Expr * E,bool NullPtr)18850b57cec5SDimitry Andric   void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) {
18860b57cec5SDimitry Andric     if (VD) {
18870b57cec5SDimitry Andric       if (AddressOf)
18880b57cec5SDimitry Andric         OS << "&";
1889e8d8bef9SDimitry Andric       else if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD)) {
1890e8d8bef9SDimitry Andric         // FIXME: Diffing the APValue would be neat.
1891e8d8bef9SDimitry Andric         // FIXME: Suppress this and use the full name of the declaration if the
1892e8d8bef9SDimitry Andric         // parameter is a pointer or reference.
18935f757f3fSDimitry Andric         TPO->getType().getUnqualifiedType().print(OS, Policy);
189481ad6265SDimitry Andric         TPO->printAsInit(OS, Policy);
1895e8d8bef9SDimitry Andric         return;
1896e8d8bef9SDimitry Andric       }
1897bdd1243dSDimitry Andric       VD->printName(OS, Policy);
18980b57cec5SDimitry Andric       return;
18990b57cec5SDimitry Andric     }
19000b57cec5SDimitry Andric 
19010b57cec5SDimitry Andric     if (NullPtr) {
19020b57cec5SDimitry Andric       if (E && !isa<CXXNullPtrLiteralExpr>(E)) {
19030b57cec5SDimitry Andric         PrintExpr(E);
19040b57cec5SDimitry Andric         if (IsBold) {
19050b57cec5SDimitry Andric           Unbold();
19060b57cec5SDimitry Andric           OS << " aka ";
19070b57cec5SDimitry Andric           Bold();
19080b57cec5SDimitry Andric         } else {
19090b57cec5SDimitry Andric           OS << " aka ";
19100b57cec5SDimitry Andric         }
19110b57cec5SDimitry Andric       }
19120b57cec5SDimitry Andric 
19130b57cec5SDimitry Andric       OS << "nullptr";
19140b57cec5SDimitry Andric       return;
19150b57cec5SDimitry Andric     }
19160b57cec5SDimitry Andric 
19170b57cec5SDimitry Andric     OS << "(no argument)";
19180b57cec5SDimitry Andric   }
19190b57cec5SDimitry Andric 
19200b57cec5SDimitry Andric   /// PrintDecl - Handles printing of Decl arguments, highlighting
19210b57cec5SDimitry Andric   /// argument differences.
PrintValueDecl(ValueDecl * FromValueDecl,ValueDecl * ToValueDecl,bool FromAddressOf,bool ToAddressOf,bool FromNullPtr,bool ToNullPtr,Expr * FromExpr,Expr * ToExpr,bool FromDefault,bool ToDefault,bool Same)19220b57cec5SDimitry Andric   void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
19230b57cec5SDimitry Andric                       bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,
19240b57cec5SDimitry Andric                       bool ToNullPtr, Expr *FromExpr, Expr *ToExpr,
19250b57cec5SDimitry Andric                       bool FromDefault, bool ToDefault, bool Same) {
19260b57cec5SDimitry Andric     assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&
19270b57cec5SDimitry Andric            "Only one Decl argument may be NULL");
19280b57cec5SDimitry Andric 
19290b57cec5SDimitry Andric     if (Same) {
19300b57cec5SDimitry Andric       PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
19310b57cec5SDimitry Andric     } else if (!PrintTree) {
19320b57cec5SDimitry Andric       OS << (FromDefault ? "(default) " : "");
19330b57cec5SDimitry Andric       Bold();
19340b57cec5SDimitry Andric       PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
19350b57cec5SDimitry Andric       Unbold();
19360b57cec5SDimitry Andric     } else {
19370b57cec5SDimitry Andric       OS << (FromDefault ? "[(default) " : "[");
19380b57cec5SDimitry Andric       Bold();
19390b57cec5SDimitry Andric       PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
19400b57cec5SDimitry Andric       Unbold();
19410b57cec5SDimitry Andric       OS << " != " << (ToDefault ? "(default) " : "");
19420b57cec5SDimitry Andric       Bold();
19430b57cec5SDimitry Andric       PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr);
19440b57cec5SDimitry Andric       Unbold();
19450b57cec5SDimitry Andric       OS << ']';
19460b57cec5SDimitry Andric     }
19470b57cec5SDimitry Andric   }
19480b57cec5SDimitry Andric 
19490b57cec5SDimitry Andric   /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and
19500b57cec5SDimitry Andric   /// APSInt to print a mixed difference.
PrintValueDeclAndInteger(ValueDecl * VD,bool NeedAddressOf,bool IsNullPtr,Expr * VDExpr,bool DefaultDecl,const llvm::APSInt & Val,QualType IntType,Expr * IntExpr,bool DefaultInt)19510b57cec5SDimitry Andric   void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf,
19520b57cec5SDimitry Andric                                 bool IsNullPtr, Expr *VDExpr, bool DefaultDecl,
19530b57cec5SDimitry Andric                                 const llvm::APSInt &Val, QualType IntType,
19540b57cec5SDimitry Andric                                 Expr *IntExpr, bool DefaultInt) {
19550b57cec5SDimitry Andric     if (!PrintTree) {
19560b57cec5SDimitry Andric       OS << (DefaultDecl ? "(default) " : "");
19570b57cec5SDimitry Andric       Bold();
19580b57cec5SDimitry Andric       PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
19590b57cec5SDimitry Andric       Unbold();
19600b57cec5SDimitry Andric     } else {
19610b57cec5SDimitry Andric       OS << (DefaultDecl ? "[(default) " : "[");
19620b57cec5SDimitry Andric       Bold();
19630b57cec5SDimitry Andric       PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
19640b57cec5SDimitry Andric       Unbold();
19650b57cec5SDimitry Andric       OS << " != " << (DefaultInt ? "(default) " : "");
19660b57cec5SDimitry Andric       PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
19670b57cec5SDimitry Andric       OS << ']';
19680b57cec5SDimitry Andric     }
19690b57cec5SDimitry Andric   }
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric   /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and
19720b57cec5SDimitry Andric   /// ValueDecl to print a mixed difference.
PrintIntegerAndValueDecl(const llvm::APSInt & Val,QualType IntType,Expr * IntExpr,bool DefaultInt,ValueDecl * VD,bool NeedAddressOf,bool IsNullPtr,Expr * VDExpr,bool DefaultDecl)19730b57cec5SDimitry Andric   void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType,
19740b57cec5SDimitry Andric                                 Expr *IntExpr, bool DefaultInt, ValueDecl *VD,
19750b57cec5SDimitry Andric                                 bool NeedAddressOf, bool IsNullPtr,
19760b57cec5SDimitry Andric                                 Expr *VDExpr, bool DefaultDecl) {
19770b57cec5SDimitry Andric     if (!PrintTree) {
19780b57cec5SDimitry Andric       OS << (DefaultInt ? "(default) " : "");
19790b57cec5SDimitry Andric       PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
19800b57cec5SDimitry Andric     } else {
19810b57cec5SDimitry Andric       OS << (DefaultInt ? "[(default) " : "[");
19820b57cec5SDimitry Andric       PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);
19830b57cec5SDimitry Andric       OS << " != " << (DefaultDecl ? "(default) " : "");
19840b57cec5SDimitry Andric       Bold();
19850b57cec5SDimitry Andric       PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
19860b57cec5SDimitry Andric       Unbold();
19870b57cec5SDimitry Andric       OS << ']';
19880b57cec5SDimitry Andric     }
19890b57cec5SDimitry Andric   }
19900b57cec5SDimitry Andric 
19910b57cec5SDimitry Andric   // Prints the appropriate placeholder for elided template arguments.
PrintElideArgs(unsigned NumElideArgs,unsigned Indent)19920b57cec5SDimitry Andric   void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
19930b57cec5SDimitry Andric     if (PrintTree) {
19940b57cec5SDimitry Andric       OS << '\n';
19950b57cec5SDimitry Andric       for (unsigned i = 0; i < Indent; ++i)
19960b57cec5SDimitry Andric         OS << "  ";
19970b57cec5SDimitry Andric     }
19980b57cec5SDimitry Andric     if (NumElideArgs == 0) return;
19990b57cec5SDimitry Andric     if (NumElideArgs == 1)
20000b57cec5SDimitry Andric       OS << "[...]";
20010b57cec5SDimitry Andric     else
20020b57cec5SDimitry Andric       OS << "[" << NumElideArgs << " * ...]";
20030b57cec5SDimitry Andric   }
20040b57cec5SDimitry Andric 
20050b57cec5SDimitry Andric   // Prints and highlights differences in Qualifiers.
PrintQualifiers(Qualifiers FromQual,Qualifiers ToQual)20060b57cec5SDimitry Andric   void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {
20070b57cec5SDimitry Andric     // Both types have no qualifiers
20080b57cec5SDimitry Andric     if (FromQual.empty() && ToQual.empty())
20090b57cec5SDimitry Andric       return;
20100b57cec5SDimitry Andric 
20110b57cec5SDimitry Andric     // Both types have same qualifiers
20120b57cec5SDimitry Andric     if (FromQual == ToQual) {
20130b57cec5SDimitry Andric       PrintQualifier(FromQual, /*ApplyBold*/false);
20140b57cec5SDimitry Andric       return;
20150b57cec5SDimitry Andric     }
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric     // Find common qualifiers and strip them from FromQual and ToQual.
20180b57cec5SDimitry Andric     Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual,
20190b57cec5SDimitry Andric                                                                ToQual);
20200b57cec5SDimitry Andric 
20210b57cec5SDimitry Andric     // The qualifiers are printed before the template name.
20220b57cec5SDimitry Andric     // Inline printing:
20230b57cec5SDimitry Andric     // The common qualifiers are printed.  Then, qualifiers only in this type
20240b57cec5SDimitry Andric     // are printed and highlighted.  Finally, qualifiers only in the other
20250b57cec5SDimitry Andric     // type are printed and highlighted inside parentheses after "missing".
20260b57cec5SDimitry Andric     // Tree printing:
20270b57cec5SDimitry Andric     // Qualifiers are printed next to each other, inside brackets, and
20280b57cec5SDimitry Andric     // separated by "!=".  The printing order is:
20290b57cec5SDimitry Andric     // common qualifiers, highlighted from qualifiers, "!=",
20300b57cec5SDimitry Andric     // common qualifiers, highlighted to qualifiers
20310b57cec5SDimitry Andric     if (PrintTree) {
20320b57cec5SDimitry Andric       OS << "[";
20330b57cec5SDimitry Andric       if (CommonQual.empty() && FromQual.empty()) {
20340b57cec5SDimitry Andric         Bold();
20350b57cec5SDimitry Andric         OS << "(no qualifiers) ";
20360b57cec5SDimitry Andric         Unbold();
20370b57cec5SDimitry Andric       } else {
20380b57cec5SDimitry Andric         PrintQualifier(CommonQual, /*ApplyBold*/false);
20390b57cec5SDimitry Andric         PrintQualifier(FromQual, /*ApplyBold*/true);
20400b57cec5SDimitry Andric       }
20410b57cec5SDimitry Andric       OS << "!= ";
20420b57cec5SDimitry Andric       if (CommonQual.empty() && ToQual.empty()) {
20430b57cec5SDimitry Andric         Bold();
20440b57cec5SDimitry Andric         OS << "(no qualifiers)";
20450b57cec5SDimitry Andric         Unbold();
20460b57cec5SDimitry Andric       } else {
20470b57cec5SDimitry Andric         PrintQualifier(CommonQual, /*ApplyBold*/false,
20480b57cec5SDimitry Andric                        /*appendSpaceIfNonEmpty*/!ToQual.empty());
20490b57cec5SDimitry Andric         PrintQualifier(ToQual, /*ApplyBold*/true,
20500b57cec5SDimitry Andric                        /*appendSpaceIfNonEmpty*/false);
20510b57cec5SDimitry Andric       }
20520b57cec5SDimitry Andric       OS << "] ";
20530b57cec5SDimitry Andric     } else {
20540b57cec5SDimitry Andric       PrintQualifier(CommonQual, /*ApplyBold*/false);
20550b57cec5SDimitry Andric       PrintQualifier(FromQual, /*ApplyBold*/true);
20560b57cec5SDimitry Andric     }
20570b57cec5SDimitry Andric   }
20580b57cec5SDimitry Andric 
PrintQualifier(Qualifiers Q,bool ApplyBold,bool AppendSpaceIfNonEmpty=true)20590b57cec5SDimitry Andric   void PrintQualifier(Qualifiers Q, bool ApplyBold,
20600b57cec5SDimitry Andric                       bool AppendSpaceIfNonEmpty = true) {
20610b57cec5SDimitry Andric     if (Q.empty()) return;
20620b57cec5SDimitry Andric     if (ApplyBold) Bold();
20630b57cec5SDimitry Andric     Q.print(OS, Policy, AppendSpaceIfNonEmpty);
20640b57cec5SDimitry Andric     if (ApplyBold) Unbold();
20650b57cec5SDimitry Andric   }
20660b57cec5SDimitry Andric 
20670b57cec5SDimitry Andric public:
20680b57cec5SDimitry Andric 
TemplateDiff(raw_ostream & OS,ASTContext & Context,QualType FromType,QualType ToType,bool PrintTree,bool PrintFromType,bool ElideType,bool ShowColor)20690b57cec5SDimitry Andric   TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType,
20700b57cec5SDimitry Andric                QualType ToType, bool PrintTree, bool PrintFromType,
20710b57cec5SDimitry Andric                bool ElideType, bool ShowColor)
20720b57cec5SDimitry Andric     : Context(Context),
20730b57cec5SDimitry Andric       Policy(Context.getLangOpts()),
20740b57cec5SDimitry Andric       ElideType(ElideType),
20750b57cec5SDimitry Andric       PrintTree(PrintTree),
20760b57cec5SDimitry Andric       ShowColor(ShowColor),
20770b57cec5SDimitry Andric       // When printing a single type, the FromType is the one printed.
20780b57cec5SDimitry Andric       FromTemplateType(PrintFromType ? FromType : ToType),
20790b57cec5SDimitry Andric       ToTemplateType(PrintFromType ? ToType : FromType),
20800b57cec5SDimitry Andric       OS(OS),
20810b57cec5SDimitry Andric       IsBold(false) {
20820b57cec5SDimitry Andric   }
20830b57cec5SDimitry Andric 
20840b57cec5SDimitry Andric   /// DiffTemplate - Start the template type diffing.
DiffTemplate()20850b57cec5SDimitry Andric   void DiffTemplate() {
20860b57cec5SDimitry Andric     Qualifiers FromQual = FromTemplateType.getQualifiers(),
20870b57cec5SDimitry Andric                ToQual = ToTemplateType.getQualifiers();
20880b57cec5SDimitry Andric 
20890b57cec5SDimitry Andric     const TemplateSpecializationType *FromOrigTST =
20900b57cec5SDimitry Andric         GetTemplateSpecializationType(Context, FromTemplateType);
20910b57cec5SDimitry Andric     const TemplateSpecializationType *ToOrigTST =
20920b57cec5SDimitry Andric         GetTemplateSpecializationType(Context, ToTemplateType);
20930b57cec5SDimitry Andric 
20940b57cec5SDimitry Andric     // Only checking templates.
20950b57cec5SDimitry Andric     if (!FromOrigTST || !ToOrigTST)
20960b57cec5SDimitry Andric       return;
20970b57cec5SDimitry Andric 
20980b57cec5SDimitry Andric     // Different base templates.
20990b57cec5SDimitry Andric     if (!hasSameTemplate(FromOrigTST, ToOrigTST)) {
21000b57cec5SDimitry Andric       return;
21010b57cec5SDimitry Andric     }
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric     FromQual -= QualType(FromOrigTST, 0).getQualifiers();
21040b57cec5SDimitry Andric     ToQual -= QualType(ToOrigTST, 0).getQualifiers();
21050b57cec5SDimitry Andric 
21060b57cec5SDimitry Andric     // Same base template, but different arguments.
21070b57cec5SDimitry Andric     Tree.SetTemplateDiff(FromOrigTST->getTemplateName().getAsTemplateDecl(),
21080b57cec5SDimitry Andric                          ToOrigTST->getTemplateName().getAsTemplateDecl(),
21090b57cec5SDimitry Andric                          FromQual, ToQual, false /*FromDefault*/,
21100b57cec5SDimitry Andric                          false /*ToDefault*/);
21110b57cec5SDimitry Andric 
21120b57cec5SDimitry Andric     DiffTemplate(FromOrigTST, ToOrigTST);
21130b57cec5SDimitry Andric   }
21140b57cec5SDimitry Andric 
21150b57cec5SDimitry Andric   /// Emit - When the two types given are templated types with the same
21160b57cec5SDimitry Andric   /// base template, a string representation of the type difference will be
21170b57cec5SDimitry Andric   /// emitted to the stream and return true.  Otherwise, return false.
Emit()21180b57cec5SDimitry Andric   bool Emit() {
21190b57cec5SDimitry Andric     Tree.StartTraverse();
21200b57cec5SDimitry Andric     if (Tree.Empty())
21210b57cec5SDimitry Andric       return false;
21220b57cec5SDimitry Andric 
21230b57cec5SDimitry Andric     TreeToString();
21240b57cec5SDimitry Andric     assert(!IsBold && "Bold is applied to end of string.");
21250b57cec5SDimitry Andric     return true;
21260b57cec5SDimitry Andric   }
21270b57cec5SDimitry Andric }; // end class TemplateDiff
21280b57cec5SDimitry Andric }  // end anonymous namespace
21290b57cec5SDimitry Andric 
21300b57cec5SDimitry Andric /// FormatTemplateTypeDiff - A helper static function to start the template
21310b57cec5SDimitry Andric /// diff and return the properly formatted string.  Returns true if the diff
21320b57cec5SDimitry Andric /// is successful.
FormatTemplateTypeDiff(ASTContext & Context,QualType FromType,QualType ToType,bool PrintTree,bool PrintFromType,bool ElideType,bool ShowColors,raw_ostream & OS)21330b57cec5SDimitry Andric static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
21340b57cec5SDimitry Andric                                    QualType ToType, bool PrintTree,
21350b57cec5SDimitry Andric                                    bool PrintFromType, bool ElideType,
21360b57cec5SDimitry Andric                                    bool ShowColors, raw_ostream &OS) {
21370b57cec5SDimitry Andric   if (PrintTree)
21380b57cec5SDimitry Andric     PrintFromType = true;
21390b57cec5SDimitry Andric   TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType,
21400b57cec5SDimitry Andric                   ElideType, ShowColors);
21410b57cec5SDimitry Andric   TD.DiffTemplate();
21420b57cec5SDimitry Andric   return TD.Emit();
21430b57cec5SDimitry Andric }
2144