brintos

brintos / llvm-project-archived public Read only

0
0
Text · 81.0 KiB · b8023cb Raw
2222 lines · cpp
1//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements a diagnostic formatting hook for AST elements.10//11//===----------------------------------------------------------------------===//12 13#include "clang/AST/ASTDiagnostic.h"14#include "clang/AST/ASTContext.h"15#include "clang/AST/ASTLambda.h"16#include "clang/AST/Attr.h"17#include "clang/AST/DeclObjC.h"18#include "clang/AST/DeclTemplate.h"19#include "clang/AST/ExprCXX.h"20#include "clang/AST/TemplateBase.h"21#include "clang/AST/Type.h"22#include "llvm/ADT/StringExtras.h"23#include "llvm/Support/ConvertUTF.h"24#include "llvm/Support/Format.h"25#include "llvm/Support/raw_ostream.h"26 27using namespace clang;28 29// Returns a desugared version of the QualType, and marks ShouldAKA as true30// whenever we remove significant sugar from the type. Make sure ShouldAKA31// is initialized before passing it in.32QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,33                                     bool &ShouldAKA) {34  QualifierCollector QC;35 36  while (true) {37    const Type *Ty = QC.strip(QT);38 39    // ... or a using type ...40    if (const UsingType *UT = dyn_cast<UsingType>(Ty)) {41      QT = UT->desugar();42      continue;43    }44    // ... or a paren type ...45    if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {46      QT = PT->desugar();47      continue;48    }49    // ... or a macro defined type ...50    if (const MacroQualifiedType *MDT = dyn_cast<MacroQualifiedType>(Ty)) {51      QT = MDT->desugar();52      continue;53    }54    // ...or a substituted template type parameter ...55    if (const SubstTemplateTypeParmType *ST =56          dyn_cast<SubstTemplateTypeParmType>(Ty)) {57      QT = ST->desugar();58      continue;59    }60    // ...or an attributed type...61    if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) {62      QT = AT->desugar();63      continue;64    }65    // ...or an adjusted type...66    if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) {67      QT = AT->desugar();68      continue;69    }70    // ... or an auto type.71    if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {72      if (!AT->isSugared())73        break;74      QT = AT->desugar();75      continue;76    }77 78    // Desugar FunctionType if return type or any parameter type should be79    // desugared. Preserve nullability attribute on desugared types.80    if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) {81      bool DesugarReturn = false;82      QualType SugarRT = FT->getReturnType();83      QualType RT = desugarForDiagnostic(Context, SugarRT, DesugarReturn);84      if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {85        RT = Context.getAttributedType(*nullability, RT, RT);86      }87 88      bool DesugarArgument = false;89      SmallVector<QualType, 4> Args;90      const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);91      if (FPT) {92        for (QualType SugarPT : FPT->param_types()) {93          QualType PT = desugarForDiagnostic(Context, SugarPT, DesugarArgument);94          if (auto nullability =95                  AttributedType::stripOuterNullability(SugarPT)) {96            PT = Context.getAttributedType(*nullability, PT, PT);97          }98          Args.push_back(PT);99        }100      }101 102      if (DesugarReturn || DesugarArgument) {103        ShouldAKA = true;104        QT = FPT ? Context.getFunctionType(RT, Args, FPT->getExtProtoInfo())105                 : Context.getFunctionNoProtoType(RT, FT->getExtInfo());106        break;107      }108    }109 110    // Desugar template specializations if any template argument should be111    // desugared.112    if (const TemplateSpecializationType *TST =113            dyn_cast<TemplateSpecializationType>(Ty)) {114      if (!TST->isTypeAlias()) {115        bool DesugarArgument = false;116        SmallVector<TemplateArgument, 4> Args;117        for (const TemplateArgument &Arg : TST->template_arguments()) {118          if (Arg.getKind() == TemplateArgument::Type)119            Args.push_back(desugarForDiagnostic(Context, Arg.getAsType(),120                                                DesugarArgument));121          else122            Args.push_back(Arg);123        }124 125        if (DesugarArgument) {126          ShouldAKA = true;127          QT = Context.getTemplateSpecializationType(128              TST->getKeyword(), TST->getTemplateName(), Args,129              /*CanonicalArgs=*/{}, QT);130        }131        break;132      }133    }134 135    if (const auto *AT = dyn_cast<ArrayType>(Ty)) {136      QualType ElementTy =137          desugarForDiagnostic(Context, AT->getElementType(), ShouldAKA);138      if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))139        QT = Context.getConstantArrayType(140            ElementTy, CAT->getSize(), CAT->getSizeExpr(),141            CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());142      else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))143        QT = Context.getVariableArrayType(ElementTy, VAT->getSizeExpr(),144                                          VAT->getSizeModifier(),145                                          VAT->getIndexTypeCVRQualifiers());146      else if (const auto *DSAT = dyn_cast<DependentSizedArrayType>(AT))147        QT = Context.getDependentSizedArrayType(148            ElementTy, DSAT->getSizeExpr(), DSAT->getSizeModifier(),149            DSAT->getIndexTypeCVRQualifiers());150      else if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT))151        QT = Context.getIncompleteArrayType(ElementTy, IAT->getSizeModifier(),152                                            IAT->getIndexTypeCVRQualifiers());153      else154        llvm_unreachable("Unhandled array type");155      break;156    }157 158    // Don't desugar magic Objective-C types.159    if (QualType(Ty,0) == Context.getObjCIdType() ||160        QualType(Ty,0) == Context.getObjCClassType() ||161        QualType(Ty,0) == Context.getObjCSelType() ||162        QualType(Ty,0) == Context.getObjCProtoType())163      break;164 165    // Don't desugar va_list.166    if (QualType(Ty, 0) == Context.getBuiltinVaListType() ||167        QualType(Ty, 0) == Context.getBuiltinMSVaListType())168      break;169 170    // Otherwise, do a single-step desugar.171    QualType Underlying;172    bool IsSugar = false;173    switch (Ty->getTypeClass()) {174#define ABSTRACT_TYPE(Class, Base)175#define TYPE(Class, Base) \176case Type::Class: { \177const Class##Type *CTy = cast<Class##Type>(Ty); \178if (CTy->isSugared()) { \179IsSugar = true; \180Underlying = CTy->desugar(); \181} \182break; \183}184#include "clang/AST/TypeNodes.inc"185    }186 187    // If it wasn't sugared, we're done.188    if (!IsSugar)189      break;190 191    // If the desugared type is a vector type, we don't want to expand192    // it, it will turn into an attribute mess. People want their "vec4".193    if (isa<VectorType>(Underlying))194      break;195 196    // Don't desugar through the primary typedef of an anonymous type.197    if (const TagType *UTT = Underlying->getAs<TagType>())198      if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))199        if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())200          break;201 202    // Record that we actually looked through an opaque type here.203    ShouldAKA = true;204    QT = Underlying;205  }206 207  // If we have a pointer-like type, desugar the pointee as well.208  // FIXME: Handle other pointer-like types.209  if (const PointerType *Ty = QT->getAs<PointerType>()) {210    QT = Context.getPointerType(211        desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));212  } else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) {213    QT = Context.getObjCObjectPointerType(214        desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));215  } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {216    QT = Context.getLValueReferenceType(217        desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));218  } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {219    QT = Context.getRValueReferenceType(220        desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));221  } else if (const auto *Ty = QT->getAs<ObjCObjectType>()) {222    if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {223      QualType BaseType =224          desugarForDiagnostic(Context, Ty->getBaseType(), ShouldAKA);225      QT = Context.getObjCObjectType(226          BaseType, Ty->getTypeArgsAsWritten(),227          ArrayRef(Ty->qual_begin(), Ty->getNumProtocols()),228          Ty->isKindOfTypeAsWritten());229    }230  }231 232  return QC.apply(Context, QT);233}234 235/// Convert the given type to a string suitable for printing as part of236/// a diagnostic.237///238/// There are four main criteria when determining whether we should have an239/// a.k.a. clause when pretty-printing a type:240///241/// 1) Some types provide very minimal sugar that doesn't impede the242///    user's understanding --- for example, elaborated type243///    specifiers.  If this is all the sugar we see, we don't want an244///    a.k.a. clause.245/// 2) Some types are technically sugared but are much more familiar246///    when seen in their sugared form --- for example, va_list,247///    vector types, and the magic Objective C types.  We don't248///    want to desugar these, even if we do produce an a.k.a. clause.249/// 3) Some types may have already been desugared previously in this diagnostic.250///    if this is the case, doing another "aka" would just be clutter.251/// 4) Two different types within the same diagnostic have the same output252///    string.  In this case, force an a.k.a with the desugared type when253///    doing so will provide additional information.254///255/// \param Context the context in which the type was allocated256/// \param Ty the type to print257/// \param QualTypeVals pointer values to QualTypes which are used in the258/// diagnostic message259static std::string260ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,261                            ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,262                            ArrayRef<intptr_t> QualTypeVals) {263  // FIXME: Playing with std::string is really slow.264  bool ForceAKA = false;265  QualType CanTy = Ty.getCanonicalType();266  std::string S = Ty.getAsString(Context.getPrintingPolicy());267  std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());268 269  for (const intptr_t &QualTypeVal : QualTypeVals) {270    QualType CompareTy =271        QualType::getFromOpaquePtr(reinterpret_cast<void *>(QualTypeVal));272    if (CompareTy.isNull())273      continue;274    if (CompareTy == Ty)275      continue;  // Same types276    QualType CompareCanTy = CompareTy.getCanonicalType();277    if (CompareCanTy == CanTy)278      continue;  // Same canonical types279    std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());280    bool ShouldAKA = false;281    QualType CompareDesugar =282        desugarForDiagnostic(Context, CompareTy, ShouldAKA);283    std::string CompareDesugarStr =284        CompareDesugar.getAsString(Context.getPrintingPolicy());285    if (CompareS != S && CompareDesugarStr != S)286      continue;  // The type string is different than the comparison string287                 // and the desugared comparison string.288    std::string CompareCanS =289        CompareCanTy.getAsString(Context.getPrintingPolicy());290 291    if (CompareCanS == CanS)292      continue;  // No new info from canonical type293 294    ForceAKA = true;295    break;296  }297 298  // Check to see if we already desugared this type in this299  // diagnostic.  If so, don't do it again.300  bool Repeated = false;301  for (const auto &PrevArg : PrevArgs) {302    // TODO: Handle ak_declcontext case.303    if (PrevArg.first == DiagnosticsEngine::ak_qualtype) {304      QualType PrevTy(305          QualType::getFromOpaquePtr(reinterpret_cast<void *>(PrevArg.second)));306      if (PrevTy == Ty) {307        Repeated = true;308        break;309      }310    }311  }312 313  // Consider producing an a.k.a. clause if removing all the direct314  // sugar gives us something "significantly different".315  if (!Repeated) {316    bool ShouldAKA = false;317    QualType DesugaredTy = desugarForDiagnostic(Context, Ty, ShouldAKA);318    if (ShouldAKA || ForceAKA) {319      if (DesugaredTy == Ty) {320        DesugaredTy = Ty.getCanonicalType();321      }322      std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy());323      if (akaStr != S) {324        S = "'" + S + "' (aka '" + akaStr + "')";325        return S;326      }327    }328 329    // Give some additional info on vector types. These are either not desugared330    // or displaying complex __attribute__ expressions so add details of the331    // type and element count.332    if (const auto *VTy = Ty->getAs<VectorType>()) {333      std::string DecoratedString;334      llvm::raw_string_ostream OS(DecoratedString);335      const char *Values = VTy->getNumElements() > 1 ? "values" : "value";336      OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '"337         << VTy->getElementType().getAsString(Context.getPrintingPolicy())338         << "' " << Values << ")";339      return DecoratedString;340    }341  }342 343  S = "'" + S + "'";344  return S;345}346 347static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,348                                   QualType ToType, bool PrintTree,349                                   bool PrintFromType, bool ElideType,350                                   bool ShowColors, raw_ostream &OS);351 352void clang::FormatASTNodeDiagnosticArgument(353    DiagnosticsEngine::ArgumentKind Kind,354    intptr_t Val,355    StringRef Modifier,356    StringRef Argument,357    ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,358    SmallVectorImpl<char> &Output,359    void *Cookie,360    ArrayRef<intptr_t> QualTypeVals) {361  ASTContext &Context = *static_cast<ASTContext*>(Cookie);362 363  size_t OldEnd = Output.size();364  llvm::raw_svector_ostream OS(Output);365  bool NeedQuotes = true;366 367  switch (Kind) {368    default: llvm_unreachable("unknown ArgumentKind");369    case DiagnosticsEngine::ak_addrspace: {370      assert(Modifier.empty() && Argument.empty() &&371             "Invalid modifier for Qualifiers argument");372 373      auto S = Qualifiers::getAddrSpaceAsString(static_cast<LangAS>(Val));374      if (S.empty()) {375        OS << (Context.getLangOpts().OpenCL ? "default" : "generic");376        OS << " address space";377      } else {378        OS << "address space";379        OS << " '" << S << "'";380      }381      NeedQuotes = false;382      break;383    }384    case DiagnosticsEngine::ak_qual: {385      assert(Modifier.empty() && Argument.empty() &&386             "Invalid modifier for Qualifiers argument");387 388      Qualifiers Q(Qualifiers::fromOpaqueValue(Val));389      auto S = Q.getAsString();390      if (S.empty()) {391        OS << "unqualified";392        NeedQuotes = false;393      } else {394        OS << S;395      }396      break;397    }398    case DiagnosticsEngine::ak_qualtype_pair: {399      TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val);400      QualType FromType =401          QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType));402      QualType ToType =403          QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType));404 405      if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree,406                                 TDT.PrintFromType, TDT.ElideType,407                                 TDT.ShowColors, OS)) {408        NeedQuotes = !TDT.PrintTree;409        TDT.TemplateDiffUsed = true;410        break;411      }412 413      // Don't fall-back during tree printing.  The caller will handle414      // this case.415      if (TDT.PrintTree)416        return;417 418      // Attempting to do a template diff on non-templates.  Set the variables419      // and continue with regular type printing of the appropriate type.420      Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType;421      Modifier = StringRef();422      Argument = StringRef();423      // Fall through424      [[fallthrough]];425    }426    case DiagnosticsEngine::ak_qualtype: {427      assert(Modifier.empty() && Argument.empty() &&428             "Invalid modifier for QualType argument");429 430      QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));431      OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals);432      NeedQuotes = false;433      break;434    }435    case DiagnosticsEngine::ak_declarationname: {436      if (Modifier == "objcclass" && Argument.empty())437        OS << '+';438      else if (Modifier == "objcinstance" && Argument.empty())439        OS << '-';440      else441        assert(Modifier.empty() && Argument.empty() &&442               "Invalid modifier for DeclarationName argument");443 444      OS << DeclarationName::getFromOpaqueInteger(Val);445      break;446    }447    case DiagnosticsEngine::ak_nameddecl: {448      bool Qualified;449      if (Modifier == "q" && Argument.empty())450        Qualified = true;451      else {452        assert(Modifier.empty() && Argument.empty() &&453               "Invalid modifier for NamedDecl* argument");454        Qualified = false;455      }456      const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val);457      ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified);458      break;459    }460    case DiagnosticsEngine::ak_nestednamespec:461      NestedNameSpecifier::getFromVoidPointer(reinterpret_cast<void *>(Val))462          .print(OS, Context.getPrintingPolicy(),463                 /*ResolveTemplateArguments=*/false,464                 /*PrintFinalScopeResOp=*/false);465      break;466    case DiagnosticsEngine::ak_declcontext: {467      DeclContext *DC = reinterpret_cast<DeclContext *> (Val);468      assert(DC && "Should never have a null declaration context");469      NeedQuotes = false;470 471      // FIXME: Get the strings for DeclContext from some localized place472      if (DC->isTranslationUnit()) {473        if (Context.getLangOpts().CPlusPlus)474          OS << "the global namespace";475        else476          OS << "the global scope";477      } else if (DC->isClosure()) {478        OS << "block literal";479      } else if (isLambdaCallOperator(DC)) {480        OS << "lambda expression";481      } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {482        OS << ConvertTypeToDiagnosticString(483            Context, Context.getTypeDeclType(Type), PrevArgs, QualTypeVals);484      } else {485        assert(isa<NamedDecl>(DC) && "Expected a NamedDecl");486        NamedDecl *ND = cast<NamedDecl>(DC);487        if (isa<NamespaceDecl>(ND))488          OS << "namespace ";489        else if (isa<ObjCMethodDecl>(ND))490          OS << "method ";491        else if (isa<FunctionDecl>(ND))492          OS << "function ";493 494        OS << '\'';495        ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);496        OS << '\'';497      }498      break;499    }500    case DiagnosticsEngine::ak_attr: {501      const Attr *At = reinterpret_cast<Attr *>(Val);502      assert(At && "Received null Attr object!");503 504      OS << '\'';505      if (At->hasScope()) {506        OS << At->getNormalizedFullName(At->getScopeName()->getName(),507                                        At->getSpelling());508      } else {509        OS << At->getSpelling();510      }511      OS << '\'';512      NeedQuotes = false;513      break;514    }515    case DiagnosticsEngine::ak_expr: {516      const Expr *E = reinterpret_cast<Expr *>(Val);517      assert(E && "Received null Expr!");518      E->printPretty(OS, /*Helper=*/nullptr, Context.getPrintingPolicy());519      break;520    }521    case DiagnosticsEngine::ak_attr_info: {522      AttributeCommonInfo *AT = reinterpret_cast<AttributeCommonInfo *>(Val);523      assert(AT && "Received null AttributeCommonInfo object!");524 525      OS << '\'';526      if (AT->isStandardAttributeSyntax()) {527        OS << AT->getNormalizedFullName();528      } else {529        OS << AT->getAttrName()->getName();530      }531      OS << '\'';532      NeedQuotes = false;533      break;534    }535  }536 537  if (NeedQuotes) {538    Output.insert(Output.begin()+OldEnd, '\'');539    Output.push_back('\'');540  }541}542 543/// TemplateDiff - A class that constructs a pretty string for a pair of544/// QualTypes.  For the pair of types, a diff tree will be created containing545/// all the information about the templates and template arguments.  Afterwards,546/// the tree is transformed to a string according to the options passed in.547namespace {548class TemplateDiff {549  /// Context - The ASTContext which is used for comparing template arguments.550  ASTContext &Context;551 552  /// Policy - Used during expression printing.553  PrintingPolicy Policy;554 555  /// ElideType - Option to elide identical types.556  bool ElideType;557 558  /// PrintTree - Format output string as a tree.559  bool PrintTree;560 561  /// ShowColor - Diagnostics support color, so bolding will be used.562  bool ShowColor;563 564  /// FromTemplateType - When single type printing is selected, this is the565  /// type to be printed.  When tree printing is selected, this type will566  /// show up first in the tree.567  QualType FromTemplateType;568 569  /// ToTemplateType - The type that FromType is compared to.  Only in tree570  /// printing will this type be outputed.571  QualType ToTemplateType;572 573  /// OS - The stream used to construct the output strings.574  raw_ostream &OS;575 576  /// IsBold - Keeps track of the bold formatting for the output string.577  bool IsBold;578 579  /// DiffTree - A tree representation of the differences between two types.580  class DiffTree {581  public:582    /// DiffKind - The difference in a DiffNode.  Fields of583    /// TemplateArgumentInfo needed by each difference can be found in the584    /// Set* and Get* functions.585    enum DiffKind {586      /// Incomplete or invalid node.587      Invalid,588      /// Another level of templates589      Template,590      /// Type difference, all type differences except those falling under591      /// the Template difference.592      Type,593      /// Expression difference, this is only when both arguments are594      /// expressions.  If one argument is an expression and the other is595      /// Integer or Declaration, then use that diff type instead.596      Expression,597      /// Template argument difference598      TemplateTemplate,599      /// Integer difference600      Integer,601      /// Declaration difference, nullptr arguments are included here602      Declaration,603      /// One argument being integer and the other being declaration604      FromIntegerAndToDeclaration,605      FromDeclarationAndToInteger606    };607 608  private:609    /// TemplateArgumentInfo - All the information needed to pretty print610    /// a template argument.  See the Set* and Get* functions to see which611    /// fields are used for each DiffKind.612    struct TemplateArgumentInfo {613      QualType ArgType;614      Qualifiers Qual;615      llvm::APSInt Val;616      bool IsValidInt = false;617      Expr *ArgExpr = nullptr;618      TemplateDecl *TD = nullptr;619      ValueDecl *VD = nullptr;620      bool NeedAddressOf = false;621      bool IsNullPtr = false;622      bool IsDefault = false;623    };624 625    /// DiffNode - The root node stores the original type.  Each child node626    /// stores template arguments of their parents.  For templated types, the627    /// template decl is also stored.628    struct DiffNode {629      DiffKind Kind = Invalid;630 631      /// NextNode - The index of the next sibling node or 0.632      unsigned NextNode = 0;633 634      /// ChildNode - The index of the first child node or 0.635      unsigned ChildNode = 0;636 637      /// ParentNode - The index of the parent node.638      unsigned ParentNode = 0;639 640      TemplateArgumentInfo FromArgInfo, ToArgInfo;641 642      /// Same - Whether the two arguments evaluate to the same value.643      bool Same = false;644 645      DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {}646    };647 648    /// FlatTree - A flattened tree used to store the DiffNodes.649    SmallVector<DiffNode, 16> FlatTree;650 651    /// CurrentNode - The index of the current node being used.652    unsigned CurrentNode;653 654    /// NextFreeNode - The index of the next unused node.  Used when creating655    /// child nodes.656    unsigned NextFreeNode;657 658    /// ReadNode - The index of the current node being read.659    unsigned ReadNode;660 661  public:662    DiffTree() : CurrentNode(0), NextFreeNode(1), ReadNode(0) {663      FlatTree.push_back(DiffNode());664    }665 666    // Node writing functions, one for each valid DiffKind element.667    void SetTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,668                         Qualifiers FromQual, Qualifiers ToQual,669                         bool FromDefault, bool ToDefault) {670      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");671      FlatTree[CurrentNode].Kind = Template;672      FlatTree[CurrentNode].FromArgInfo.TD = FromTD;673      FlatTree[CurrentNode].ToArgInfo.TD = ToTD;674      FlatTree[CurrentNode].FromArgInfo.Qual = FromQual;675      FlatTree[CurrentNode].ToArgInfo.Qual = ToQual;676      SetDefault(FromDefault, ToDefault);677    }678 679    void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault,680                     bool ToDefault) {681      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");682      FlatTree[CurrentNode].Kind = Type;683      FlatTree[CurrentNode].FromArgInfo.ArgType = FromType;684      FlatTree[CurrentNode].ToArgInfo.ArgType = ToType;685      SetDefault(FromDefault, ToDefault);686    }687 688    void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault,689                           bool ToDefault) {690      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");691      FlatTree[CurrentNode].Kind = Expression;692      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;693      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;694      SetDefault(FromDefault, ToDefault);695    }696 697    void SetTemplateTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,698                                 bool FromDefault, bool ToDefault) {699      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");700      FlatTree[CurrentNode].Kind = TemplateTemplate;701      FlatTree[CurrentNode].FromArgInfo.TD = FromTD;702      FlatTree[CurrentNode].ToArgInfo.TD = ToTD;703      SetDefault(FromDefault, ToDefault);704    }705 706    void SetIntegerDiff(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,707                        bool IsValidFromInt, bool IsValidToInt,708                        QualType FromIntType, QualType ToIntType,709                        Expr *FromExpr, Expr *ToExpr, bool FromDefault,710                        bool ToDefault) {711      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");712      FlatTree[CurrentNode].Kind = Integer;713      FlatTree[CurrentNode].FromArgInfo.Val = FromInt;714      FlatTree[CurrentNode].ToArgInfo.Val = ToInt;715      FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;716      FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;717      FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;718      FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;719      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;720      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;721      SetDefault(FromDefault, ToDefault);722    }723 724    void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,725                            bool FromAddressOf, bool ToAddressOf,726                            bool FromNullPtr, bool ToNullPtr, Expr *FromExpr,727                            Expr *ToExpr, bool FromDefault, bool ToDefault) {728      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");729      FlatTree[CurrentNode].Kind = Declaration;730      FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;731      FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;732      FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;733      FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;734      FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;735      FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;736      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;737      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;738      SetDefault(FromDefault, ToDefault);739    }740 741    void SetFromDeclarationAndToIntegerDiff(742        ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr,743        Expr *FromExpr, const llvm::APSInt &ToInt, bool IsValidToInt,744        QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) {745      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");746      FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger;747      FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;748      FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;749      FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;750      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;751      FlatTree[CurrentNode].ToArgInfo.Val = ToInt;752      FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;753      FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;754      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;755      SetDefault(FromDefault, ToDefault);756    }757 758    void SetFromIntegerAndToDeclarationDiff(759        const llvm::APSInt &FromInt, bool IsValidFromInt, QualType FromIntType,760        Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf,761        bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) {762      assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");763      FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration;764      FlatTree[CurrentNode].FromArgInfo.Val = FromInt;765      FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;766      FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;767      FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;768      FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;769      FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;770      FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;771      FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;772      SetDefault(FromDefault, ToDefault);773    }774 775    /// SetDefault - Sets FromDefault and ToDefault flags of the current node.776    void SetDefault(bool FromDefault, bool ToDefault) {777      assert((!FromDefault || !ToDefault) && "Both arguments cannot be default.");778      FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault;779      FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault;780    }781 782    /// SetSame - Sets the same flag of the current node.783    void SetSame(bool Same) {784      FlatTree[CurrentNode].Same = Same;785    }786 787    /// SetKind - Sets the current node's type.788    void SetKind(DiffKind Kind) {789      FlatTree[CurrentNode].Kind = Kind;790    }791 792    /// Up - Changes the node to the parent of the current node.793    void Up() {794      assert(FlatTree[CurrentNode].Kind != Invalid &&795             "Cannot exit node before setting node information.");796      CurrentNode = FlatTree[CurrentNode].ParentNode;797    }798 799    /// AddNode - Adds a child node to the current node, then sets that800    /// node as the current node.801    void AddNode() {802      assert(FlatTree[CurrentNode].Kind == Template &&803             "Only Template nodes can have children nodes.");804      FlatTree.push_back(DiffNode(CurrentNode));805      DiffNode &Node = FlatTree[CurrentNode];806      if (Node.ChildNode == 0) {807        // If a child node doesn't exist, add one.808        Node.ChildNode = NextFreeNode;809      } else {810        // If a child node exists, find the last child node and add a811        // next node to it.812        unsigned i;813        for (i = Node.ChildNode; FlatTree[i].NextNode != 0;814             i = FlatTree[i].NextNode) {815        }816        FlatTree[i].NextNode = NextFreeNode;817      }818      CurrentNode = NextFreeNode;819      ++NextFreeNode;820    }821 822    // Node reading functions.823    /// StartTraverse - Prepares the tree for recursive traversal.824    void StartTraverse() {825      ReadNode = 0;826      CurrentNode = NextFreeNode;827      NextFreeNode = 0;828    }829 830    /// Parent - Move the current read node to its parent.831    void Parent() {832      ReadNode = FlatTree[ReadNode].ParentNode;833    }834 835    void GetTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD,836                         Qualifiers &FromQual, Qualifiers &ToQual) {837      assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind.");838      FromTD = FlatTree[ReadNode].FromArgInfo.TD;839      ToTD = FlatTree[ReadNode].ToArgInfo.TD;840      FromQual = FlatTree[ReadNode].FromArgInfo.Qual;841      ToQual = FlatTree[ReadNode].ToArgInfo.Qual;842    }843 844    void GetTypeDiff(QualType &FromType, QualType &ToType) {845      assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind");846      FromType = FlatTree[ReadNode].FromArgInfo.ArgType;847      ToType = FlatTree[ReadNode].ToArgInfo.ArgType;848    }849 850    void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) {851      assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind");852      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;853      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;854    }855 856    void GetTemplateTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {857      assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind.");858      FromTD = FlatTree[ReadNode].FromArgInfo.TD;859      ToTD = FlatTree[ReadNode].ToArgInfo.TD;860    }861 862    void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt,863                        bool &IsValidFromInt, bool &IsValidToInt,864                        QualType &FromIntType, QualType &ToIntType,865                        Expr *&FromExpr, Expr *&ToExpr) {866      assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind.");867      FromInt = FlatTree[ReadNode].FromArgInfo.Val;868      ToInt = FlatTree[ReadNode].ToArgInfo.Val;869      IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;870      IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;871      FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;872      ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;873      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;874      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;875    }876 877    void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,878                            bool &FromAddressOf, bool &ToAddressOf,879                            bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr,880                            Expr *&ToExpr) {881      assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind.");882      FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;883      ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;884      FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;885      ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;886      FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;887      ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;888      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;889      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;890    }891 892    void GetFromDeclarationAndToIntegerDiff(893        ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr,894        Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt,895        QualType &ToIntType, Expr *&ToExpr) {896      assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger &&897             "Unexpected kind.");898      FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;899      FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;900      FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;901      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;902      ToInt = FlatTree[ReadNode].ToArgInfo.Val;903      IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;904      ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;905      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;906    }907 908    void GetFromIntegerAndToDeclarationDiff(909        llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType,910        Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf,911        bool &ToNullPtr, Expr *&ToExpr) {912      assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration &&913             "Unexpected kind.");914      FromInt = FlatTree[ReadNode].FromArgInfo.Val;915      IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;916      FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;917      FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;918      ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;919      ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;920      ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;921      ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;922    }923 924    /// FromDefault - Return true if the from argument is the default.925    bool FromDefault() {926      return FlatTree[ReadNode].FromArgInfo.IsDefault;927    }928 929    /// ToDefault - Return true if the to argument is the default.930    bool ToDefault() {931      return FlatTree[ReadNode].ToArgInfo.IsDefault;932    }933 934    /// NodeIsSame - Returns true if the arguments are the same.935    bool NodeIsSame() {936      return FlatTree[ReadNode].Same;937    }938 939    /// HasChildren - Returns true if the node has children.940    bool HasChildren() {941      return FlatTree[ReadNode].ChildNode != 0;942    }943 944    /// MoveToChild - Moves from the current node to its child.945    void MoveToChild() {946      ReadNode = FlatTree[ReadNode].ChildNode;947    }948 949    /// AdvanceSibling - If there is a next sibling, advance to it and return950    /// true.  Otherwise, return false.951    bool AdvanceSibling() {952      if (FlatTree[ReadNode].NextNode == 0)953        return false;954 955      ReadNode = FlatTree[ReadNode].NextNode;956      return true;957    }958 959    /// HasNextSibling - Return true if the node has a next sibling.960    bool HasNextSibling() {961      return FlatTree[ReadNode].NextNode != 0;962    }963 964    /// Empty - Returns true if the tree has no information.965    bool Empty() {966      return GetKind() == Invalid;967    }968 969    /// GetKind - Returns the current node's type.970    DiffKind GetKind() {971      return FlatTree[ReadNode].Kind;972    }973  };974 975  DiffTree Tree;976 977  /// TSTiterator - a pair of iterators that walks the978  /// TemplateSpecializationType and the desugared TemplateSpecializationType.979  /// The desugared TemplateArgument should provide the canonical argument980  /// for comparisons.981  class TSTiterator {982    typedef const TemplateArgument& reference;983    typedef const TemplateArgument* pointer;984 985    /// InternalIterator - an iterator that is used to enter a986    /// TemplateSpecializationType and read TemplateArguments inside template987    /// parameter packs in order with the rest of the TemplateArguments.988    struct InternalIterator {989      /// TST - the template specialization whose arguments this iterator990      /// traverses over.991      const TemplateSpecializationType *TST;992 993      /// Index - the index of the template argument in TST.994      unsigned Index;995 996      /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA997      /// points to a TemplateArgument within a parameter pack.998      TemplateArgument::pack_iterator CurrentTA;999 1000      /// EndTA - the end iterator of a parameter pack1001      TemplateArgument::pack_iterator EndTA;1002 1003      /// InternalIterator - Constructs an iterator and sets it to the first1004      /// template argument.1005      InternalIterator(const TemplateSpecializationType *TST)1006          : TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) {1007        if (!TST) return;1008 1009        if (isEnd()) return;1010 1011        // Set to first template argument.  If not a parameter pack, done.1012        TemplateArgument TA = TST->template_arguments()[0];1013        if (TA.getKind() != TemplateArgument::Pack) return;1014 1015        // Start looking into the parameter pack.1016        CurrentTA = TA.pack_begin();1017        EndTA = TA.pack_end();1018 1019        // Found a valid template argument.1020        if (CurrentTA != EndTA) return;1021 1022        // Parameter pack is empty, use the increment to get to a valid1023        // template argument.1024        ++(*this);1025      }1026 1027      /// Return true if the iterator is non-singular.1028      bool isValid() const { return TST; }1029 1030      /// isEnd - Returns true if the iterator is one past the end.1031      bool isEnd() const {1032        assert(TST && "InternalIterator is invalid with a null TST.");1033        return Index >= TST->template_arguments().size();1034      }1035 1036      /// &operator++ - Increment the iterator to the next template argument.1037      InternalIterator &operator++() {1038        assert(TST && "InternalIterator is invalid with a null TST.");1039        if (isEnd()) {1040          return *this;1041        }1042 1043        // If in a parameter pack, advance in the parameter pack.1044        if (CurrentTA != EndTA) {1045          ++CurrentTA;1046          if (CurrentTA != EndTA)1047            return *this;1048        }1049 1050        // Loop until a template argument is found, or the end is reached.1051        while (true) {1052          // Advance to the next template argument.  Break if reached the end.1053          if (++Index == TST->template_arguments().size())1054            break;1055 1056          // If the TemplateArgument is not a parameter pack, done.1057          TemplateArgument TA = TST->template_arguments()[Index];1058          if (TA.getKind() != TemplateArgument::Pack)1059            break;1060 1061          // Handle parameter packs.1062          CurrentTA = TA.pack_begin();1063          EndTA = TA.pack_end();1064 1065          // If the parameter pack is empty, try to advance again.1066          if (CurrentTA != EndTA)1067            break;1068        }1069        return *this;1070      }1071 1072      /// operator* - Returns the appropriate TemplateArgument.1073      reference operator*() const {1074        assert(TST && "InternalIterator is invalid with a null TST.");1075        assert(!isEnd() && "Index exceeds number of arguments.");1076        if (CurrentTA == EndTA)1077          return TST->template_arguments()[Index];1078        else1079          return *CurrentTA;1080      }1081 1082      /// operator-> - Allow access to the underlying TemplateArgument.1083      pointer operator->() const {1084        assert(TST && "InternalIterator is invalid with a null TST.");1085        return &operator*();1086      }1087    };1088 1089    InternalIterator SugaredIterator;1090    InternalIterator DesugaredIterator;1091 1092  public:1093    TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)1094        : SugaredIterator(TST),1095          DesugaredIterator(1096              (TST->isSugared() && !TST->isTypeAlias())1097                  ? GetTemplateSpecializationType(Context, TST->desugar())1098                  : nullptr) {}1099 1100    /// &operator++ - Increment the iterator to the next template argument.1101    TSTiterator &operator++() {1102      ++SugaredIterator;1103      if (DesugaredIterator.isValid())1104        ++DesugaredIterator;1105      return *this;1106    }1107 1108    /// operator* - Returns the appropriate TemplateArgument.1109    reference operator*() const {1110      return *SugaredIterator;1111    }1112 1113    /// operator-> - Allow access to the underlying TemplateArgument.1114    pointer operator->() const {1115      return &operator*();1116    }1117 1118    /// isEnd - Returns true if no more TemplateArguments are available.1119    bool isEnd() const {1120      return SugaredIterator.isEnd();1121    }1122 1123    /// hasDesugaredTA - Returns true if there is another TemplateArgument1124    /// available.1125    bool hasDesugaredTA() const {1126      return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();1127    }1128 1129    /// getDesugaredTA - Returns the desugared TemplateArgument.1130    reference getDesugaredTA() const {1131      assert(DesugaredIterator.isValid() &&1132             "Desugared TemplateArgument should not be used.");1133      return *DesugaredIterator;1134    }1135  };1136 1137  // These functions build up the template diff tree, including functions to1138  // retrieve and compare template arguments.1139 1140  static const TemplateSpecializationType *1141  GetTemplateSpecializationType(ASTContext &Context, QualType Ty) {1142    if (const TemplateSpecializationType *TST =1143            Ty->getAs<TemplateSpecializationType>())1144      return TST;1145 1146    if (const auto* SubstType = Ty->getAs<SubstTemplateTypeParmType>())1147      Ty = SubstType->getReplacementType();1148 1149    const auto *RT = Ty->getAs<RecordType>();1150    if (!RT)1151      return nullptr;1152 1153    const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());1154    if (!CTSD)1155      return nullptr;1156 1157    Ty = Context.getTemplateSpecializationType(1158        ElaboratedTypeKeyword::None,1159        TemplateName(CTSD->getSpecializedTemplate()),1160        CTSD->getTemplateArgs().asArray(), /*CanonicalArgs=*/{},1161        Ty.getLocalUnqualifiedType().getCanonicalType());1162 1163    return Ty->getAs<TemplateSpecializationType>();1164  }1165 1166  /// Returns true if the DiffType is Type and false for Template.1167  static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType,1168                                  QualType ToType,1169                                  const TemplateSpecializationType *&FromArgTST,1170                                  const TemplateSpecializationType *&ToArgTST) {1171    if (FromType.isNull() || ToType.isNull())1172      return true;1173 1174    if (Context.hasSameType(FromType, ToType))1175      return true;1176 1177    FromArgTST = GetTemplateSpecializationType(Context, FromType);1178    ToArgTST = GetTemplateSpecializationType(Context, ToType);1179 1180    if (!FromArgTST || !ToArgTST)1181      return true;1182 1183    if (!hasSameTemplate(Context, FromArgTST, ToArgTST))1184      return true;1185 1186    return false;1187  }1188 1189  /// DiffTypes - Fills a DiffNode with information about a type difference.1190  void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) {1191    QualType FromType = GetType(FromIter);1192    QualType ToType = GetType(ToIter);1193 1194    bool FromDefault = FromIter.isEnd() && !FromType.isNull();1195    bool ToDefault = ToIter.isEnd() && !ToType.isNull();1196 1197    const TemplateSpecializationType *FromArgTST = nullptr;1198    const TemplateSpecializationType *ToArgTST = nullptr;1199    if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) {1200      Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault);1201      Tree.SetSame(!FromType.isNull() && !ToType.isNull() &&1202                   Context.hasSameType(FromType, ToType));1203    } else {1204      assert(FromArgTST && ToArgTST &&1205             "Both template specializations need to be valid.");1206      Qualifiers FromQual = FromType.getQualifiers(),1207                 ToQual = ToType.getQualifiers();1208      FromQual -= QualType(FromArgTST, 0).getQualifiers();1209      ToQual -= QualType(ToArgTST, 0).getQualifiers();1210      Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(),1211                           ToArgTST->getTemplateName().getAsTemplateDecl(),1212                           FromQual, ToQual, FromDefault, ToDefault);1213      DiffTemplate(FromArgTST, ToArgTST);1214    }1215  }1216 1217  /// DiffTemplateTemplates - Fills a DiffNode with information about a1218  /// template template difference.1219  void DiffTemplateTemplates(const TSTiterator &FromIter,1220                             const TSTiterator &ToIter) {1221    TemplateDecl *FromDecl = GetTemplateDecl(FromIter);1222    TemplateDecl *ToDecl = GetTemplateDecl(ToIter);1223    Tree.SetTemplateTemplateDiff(FromDecl, ToDecl, FromIter.isEnd() && FromDecl,1224                                 ToIter.isEnd() && ToDecl);1225    Tree.SetSame(FromDecl && ToDecl &&1226                 FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());1227  }1228 1229  /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes1230  static void InitializeNonTypeDiffVariables(ASTContext &Context,1231                                             const TSTiterator &Iter,1232                                             NonTypeTemplateParmDecl *Default,1233                                             llvm::APSInt &Value, bool &HasInt,1234                                             QualType &IntType, bool &IsNullPtr,1235                                             Expr *&E, ValueDecl *&VD,1236                                             bool &NeedAddressOf) {1237    if (!Iter.isEnd()) {1238      switch (Iter->getKind()) {1239      case TemplateArgument::StructuralValue:1240        // FIXME: Diffing of structural values is not implemented.1241        // There is no possible fallback in this case, this will show up1242        // as '(no argument)'.1243        return;1244      case TemplateArgument::Integral:1245        Value = Iter->getAsIntegral();1246        HasInt = true;1247        IntType = Iter->getIntegralType();1248        return;1249      case TemplateArgument::Declaration: {1250        VD = Iter->getAsDecl();1251        QualType ArgType = Iter->getParamTypeForDecl();1252        QualType VDType = VD->getType();1253        if (ArgType->isPointerType() &&1254            Context.hasSameType(ArgType->getPointeeType(), VDType))1255          NeedAddressOf = true;1256        return;1257      }1258      case TemplateArgument::NullPtr:1259        IsNullPtr = true;1260        return;1261      case TemplateArgument::Expression:1262        E = Iter->getAsExpr();1263        break;1264      case TemplateArgument::Null:1265      case TemplateArgument::Type:1266      case TemplateArgument::Template:1267      case TemplateArgument::TemplateExpansion:1268        llvm_unreachable("TemplateArgument kind is not expected for NTTP");1269      case TemplateArgument::Pack:1270        llvm_unreachable("TemplateArgument kind should be handled elsewhere");1271      }1272    } else if (!Default->isParameterPack()) {1273      E = Default->getDefaultArgument().getArgument().getAsExpr();1274    }1275 1276    if (!Iter.hasDesugaredTA())1277      return;1278 1279    const TemplateArgument &TA = Iter.getDesugaredTA();1280    switch (TA.getKind()) {1281    case TemplateArgument::StructuralValue:1282      // FIXME: Diffing of structural values is not implemented.1283      //        Just fall back to the expression.1284      return;1285    case TemplateArgument::Integral:1286      Value = TA.getAsIntegral();1287      HasInt = true;1288      IntType = TA.getIntegralType();1289      return;1290    case TemplateArgument::Declaration: {1291      VD = TA.getAsDecl();1292      QualType ArgType = TA.getParamTypeForDecl();1293      QualType VDType = VD->getType();1294      if (ArgType->isPointerType() &&1295          Context.hasSameType(ArgType->getPointeeType(), VDType))1296        NeedAddressOf = true;1297      return;1298    }1299    case TemplateArgument::NullPtr:1300      IsNullPtr = true;1301      return;1302    case TemplateArgument::Expression:1303      // TODO: Sometimes, the desugared template argument Expr differs from1304      // the sugared template argument Expr.  It may be useful in the future1305      // but for now, it is just discarded.1306      if (!E)1307        E = TA.getAsExpr();1308      return;1309    case TemplateArgument::Null:1310    case TemplateArgument::Type:1311    case TemplateArgument::Template:1312    case TemplateArgument::TemplateExpansion:1313      llvm_unreachable("TemplateArgument kind is not expected for NTTP");1314    case TemplateArgument::Pack:1315      llvm_unreachable("TemplateArgument kind should be handled elsewhere");1316    }1317    llvm_unreachable("Unexpected TemplateArgument kind");1318  }1319 1320  /// DiffNonTypes - Handles any template parameters not handled by DiffTypes1321  /// of DiffTemplatesTemplates, such as integer and declaration parameters.1322  void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,1323                    NonTypeTemplateParmDecl *FromDefaultNonTypeDecl,1324                    NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) {1325    Expr *FromExpr = nullptr, *ToExpr = nullptr;1326    llvm::APSInt FromInt, ToInt;1327    QualType FromIntType, ToIntType;1328    ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;1329    bool HasFromInt = false, HasToInt = false, FromNullPtr = false,1330         ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;1331    InitializeNonTypeDiffVariables(1332        Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt,1333        FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf);1334    InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt,1335                                   HasToInt, ToIntType, ToNullPtr, ToExpr,1336                                   ToValueDecl, NeedToAddressOf);1337 1338    bool FromDefault = FromIter.isEnd() &&1339                       (FromExpr || FromValueDecl || HasFromInt || FromNullPtr);1340    bool ToDefault = ToIter.isEnd() &&1341                     (ToExpr || ToValueDecl || HasToInt || ToNullPtr);1342 1343    bool FromDeclaration = FromValueDecl || FromNullPtr;1344    bool ToDeclaration = ToValueDecl || ToNullPtr;1345 1346    if (FromDeclaration && HasToInt) {1347      Tree.SetFromDeclarationAndToIntegerDiff(1348          FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt,1349          HasToInt, ToIntType, ToExpr, FromDefault, ToDefault);1350      Tree.SetSame(false);1351      return;1352 1353    }1354 1355    if (HasFromInt && ToDeclaration) {1356      Tree.SetFromIntegerAndToDeclarationDiff(1357          FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl,1358          NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault);1359      Tree.SetSame(false);1360      return;1361    }1362 1363    if (HasFromInt || HasToInt) {1364      Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,1365                          ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);1366      if (HasFromInt && HasToInt) {1367        Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) &&1368                     FromInt == ToInt);1369      }1370      return;1371    }1372 1373    if (FromDeclaration || ToDeclaration) {1374      Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf,1375                              NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr,1376                              ToExpr, FromDefault, ToDefault);1377      bool BothNull = FromNullPtr && ToNullPtr;1378      bool SameValueDecl =1379          FromValueDecl && ToValueDecl &&1380          NeedFromAddressOf == NeedToAddressOf &&1381          FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl();1382      Tree.SetSame(BothNull || SameValueDecl);1383      return;1384    }1385 1386    assert((FromExpr || ToExpr) && "Both template arguments cannot be empty.");1387    Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault);1388    Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));1389  }1390 1391  /// DiffTemplate - recursively visits template arguments and stores the1392  /// argument info into a tree.1393  void DiffTemplate(const TemplateSpecializationType *FromTST,1394                    const TemplateSpecializationType *ToTST) {1395    // FIXME: With P3310R0, A TST formed from a DeducedTemplateName might1396    // differ in template arguments which were not written.1397    // Begin descent into diffing template tree.1398    TemplateParameterList *ParamsFrom =1399        FromTST->getTemplateName()1400            .getAsTemplateDecl(/*IgnoreDeduced=*/true)1401            ->getTemplateParameters();1402    TemplateParameterList *ParamsTo =1403        ToTST->getTemplateName()1404            .getAsTemplateDecl(/*IgnoreDeduced=*/true)1405            ->getTemplateParameters();1406    unsigned TotalArgs = 0;1407    for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST);1408         !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {1409      Tree.AddNode();1410 1411      // Get the parameter at index TotalArgs.  If index is larger1412      // than the total number of parameters, then there is an1413      // argument pack, so re-use the last parameter.1414      unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);1415      unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1);1416      NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex);1417      NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex);1418 1419      assert(FromParamND->getKind() == ToParamND->getKind() &&1420             "Parameter Decl are not the same kind.");1421 1422      if (isa<TemplateTypeParmDecl>(FromParamND)) {1423        DiffTypes(FromIter, ToIter);1424      } else if (isa<TemplateTemplateParmDecl>(FromParamND)) {1425        DiffTemplateTemplates(FromIter, ToIter);1426      } else if (isa<NonTypeTemplateParmDecl>(FromParamND)) {1427        NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =1428            cast<NonTypeTemplateParmDecl>(FromParamND);1429        NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =1430            cast<NonTypeTemplateParmDecl>(ToParamND);1431        DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,1432                     ToDefaultNonTypeDecl);1433      } else {1434        llvm_unreachable("Unexpected Decl type.");1435      }1436 1437      ++FromIter;1438      ++ToIter;1439      Tree.Up();1440    }1441  }1442 1443  /// makeTemplateList - Dump every template alias into the vector.1444  static void makeTemplateList(1445      SmallVectorImpl<const TemplateSpecializationType *> &TemplateList,1446      const TemplateSpecializationType *TST) {1447    while (TST) {1448      TemplateList.push_back(TST);1449      if (!TST->isTypeAlias())1450        return;1451      TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();1452    }1453  }1454 1455  /// hasSameBaseTemplate - Returns true when the base templates are the same,1456  /// even if the template arguments are not.1457  static bool hasSameBaseTemplate(ASTContext &Context,1458                                  const TemplateSpecializationType *FromTST,1459                                  const TemplateSpecializationType *ToTST) {1460    return Context.getCanonicalTemplateName(FromTST->getTemplateName(),1461                                            /*IgnoreDeduced=*/true) ==1462           Context.getCanonicalTemplateName(ToTST->getTemplateName(),1463                                            /*IgnoreDeduced=*/true);1464  }1465 1466  /// hasSameTemplate - Returns true if both types are specialized from the1467  /// same template declaration.  If they come from different template aliases,1468  /// do a parallel ascension search to determine the highest template alias in1469  /// common and set the arguments to them.1470  static bool hasSameTemplate(ASTContext &Context,1471                              const TemplateSpecializationType *&FromTST,1472                              const TemplateSpecializationType *&ToTST) {1473    // Check the top templates if they are the same.1474    if (hasSameBaseTemplate(Context, FromTST, ToTST))1475      return true;1476 1477    // Create vectors of template aliases.1478    SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,1479                                                      ToTemplateList;1480 1481    makeTemplateList(FromTemplateList, FromTST);1482    makeTemplateList(ToTemplateList, ToTST);1483 1484    SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator1485        FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),1486        ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();1487 1488    // Check if the lowest template types are the same.  If not, return.1489    if (!hasSameBaseTemplate(Context, *FromIter, *ToIter))1490      return false;1491 1492    // Begin searching up the template aliases.  The bottom most template1493    // matches so move up until one pair does not match.  Use the template1494    // right before that one.1495    for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {1496      if (!hasSameBaseTemplate(Context, *FromIter, *ToIter))1497        break;1498    }1499 1500    FromTST = FromIter[-1];1501    ToTST = ToIter[-1];1502 1503    return true;1504  }1505 1506  /// GetType - Retrieves the template type arguments, including default1507  /// arguments.1508  static QualType GetType(const TSTiterator &Iter) {1509    if (!Iter.isEnd())1510      return Iter->getAsType();1511    if (Iter.hasDesugaredTA())1512      return Iter.getDesugaredTA().getAsType();1513    return QualType();1514  }1515 1516  /// GetTemplateDecl - Retrieves the template template arguments, including1517  /// default arguments.1518  static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) {1519    if (!Iter.isEnd())1520      return Iter->getAsTemplate().getAsTemplateDecl();1521    if (Iter.hasDesugaredTA())1522      return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl();1523    return nullptr;1524  }1525 1526  /// IsEqualExpr - Returns true if the expressions are the same in regards to1527  /// template arguments.  These expressions are dependent, so profile them1528  /// instead of trying to evaluate them.1529  static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {1530    if (FromExpr == ToExpr)1531      return true;1532 1533    if (!FromExpr || !ToExpr)1534      return false;1535 1536    llvm::FoldingSetNodeID FromID, ToID;1537    FromExpr->Profile(FromID, Context, true);1538    ToExpr->Profile(ToID, Context, true);1539    return FromID == ToID;1540  }1541 1542  // These functions converts the tree representation of the template1543  // differences into the internal character vector.1544 1545  /// TreeToString - Converts the Tree object into a character stream which1546  /// will later be turned into the output string.1547  void TreeToString(int Indent = 1) {1548    if (PrintTree) {1549      OS << '\n';1550      OS.indent(2 * Indent);1551      ++Indent;1552    }1553 1554    // Handle cases where the difference is not templates with different1555    // arguments.1556    switch (Tree.GetKind()) {1557      case DiffTree::Invalid:1558        llvm_unreachable("Template diffing failed with bad DiffNode");1559      case DiffTree::Type: {1560        QualType FromType, ToType;1561        Tree.GetTypeDiff(FromType, ToType);1562        PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),1563                       Tree.NodeIsSame());1564        return;1565      }1566      case DiffTree::Expression: {1567        Expr *FromExpr, *ToExpr;1568        Tree.GetExpressionDiff(FromExpr, ToExpr);1569        PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),1570                  Tree.NodeIsSame());1571        return;1572      }1573      case DiffTree::TemplateTemplate: {1574        TemplateDecl *FromTD, *ToTD;1575        Tree.GetTemplateTemplateDiff(FromTD, ToTD);1576        PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),1577                              Tree.ToDefault(), Tree.NodeIsSame());1578        return;1579      }1580      case DiffTree::Integer: {1581        llvm::APSInt FromInt, ToInt;1582        Expr *FromExpr, *ToExpr;1583        bool IsValidFromInt, IsValidToInt;1584        QualType FromIntType, ToIntType;1585        Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,1586                            FromIntType, ToIntType, FromExpr, ToExpr);1587        PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,1588                    ToIntType, FromExpr, ToExpr, Tree.FromDefault(),1589                    Tree.ToDefault(), Tree.NodeIsSame());1590        return;1591      }1592      case DiffTree::Declaration: {1593        ValueDecl *FromValueDecl, *ToValueDecl;1594        bool FromAddressOf, ToAddressOf;1595        bool FromNullPtr, ToNullPtr;1596        Expr *FromExpr, *ToExpr;1597        Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf,1598                                ToAddressOf, FromNullPtr, ToNullPtr, FromExpr,1599                                ToExpr);1600        PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,1601                       FromNullPtr, ToNullPtr, FromExpr, ToExpr,1602                       Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());1603        return;1604      }1605      case DiffTree::FromDeclarationAndToInteger: {1606        ValueDecl *FromValueDecl;1607        bool FromAddressOf;1608        bool FromNullPtr;1609        Expr *FromExpr;1610        llvm::APSInt ToInt;1611        bool IsValidToInt;1612        QualType ToIntType;1613        Expr *ToExpr;1614        Tree.GetFromDeclarationAndToIntegerDiff(1615            FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt,1616            IsValidToInt, ToIntType, ToExpr);1617        assert((FromValueDecl || FromNullPtr) && IsValidToInt);1618        PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr,1619                                 FromExpr, Tree.FromDefault(), ToInt, ToIntType,1620                                 ToExpr, Tree.ToDefault());1621        return;1622      }1623      case DiffTree::FromIntegerAndToDeclaration: {1624        llvm::APSInt FromInt;1625        bool IsValidFromInt;1626        QualType FromIntType;1627        Expr *FromExpr;1628        ValueDecl *ToValueDecl;1629        bool ToAddressOf;1630        bool ToNullPtr;1631        Expr *ToExpr;1632        Tree.GetFromIntegerAndToDeclarationDiff(1633            FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl,1634            ToAddressOf, ToNullPtr, ToExpr);1635        assert(IsValidFromInt && (ToValueDecl || ToNullPtr));1636        PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr,1637                                 Tree.FromDefault(), ToValueDecl, ToAddressOf,1638                                 ToNullPtr, ToExpr, Tree.ToDefault());1639        return;1640      }1641      case DiffTree::Template: {1642        // Node is root of template.  Recurse on children.1643        TemplateDecl *FromTD, *ToTD;1644        Qualifiers FromQual, ToQual;1645        Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual);1646 1647        PrintQualifiers(FromQual, ToQual);1648 1649        if (!Tree.HasChildren()) {1650          // If we're dealing with a template specialization with zero1651          // arguments, there are no children; special-case this.1652          OS << FromTD->getDeclName() << "<>";1653          return;1654        }1655 1656        OS << FromTD->getDeclName() << '<';1657        Tree.MoveToChild();1658        unsigned NumElideArgs = 0;1659        bool AllArgsElided = true;1660        do {1661          if (ElideType) {1662            if (Tree.NodeIsSame()) {1663              ++NumElideArgs;1664              continue;1665            }1666            AllArgsElided = false;1667            if (NumElideArgs > 0) {1668              PrintElideArgs(NumElideArgs, Indent);1669              NumElideArgs = 0;1670              OS << ", ";1671            }1672          }1673          TreeToString(Indent);1674          if (Tree.HasNextSibling())1675            OS << ", ";1676        } while (Tree.AdvanceSibling());1677        if (NumElideArgs > 0) {1678          if (AllArgsElided)1679            OS << "...";1680          else1681            PrintElideArgs(NumElideArgs, Indent);1682        }1683 1684        Tree.Parent();1685        OS << ">";1686        return;1687      }1688    }1689  }1690 1691  // To signal to the text printer that a certain text needs to be bolded,1692  // a special character is injected into the character stream which the1693  // text printer will later strip out.1694 1695  /// Bold - Start bolding text.1696  void Bold() {1697    assert(!IsBold && "Attempting to bold text that is already bold.");1698    IsBold = true;1699    if (ShowColor)1700      OS << ToggleHighlight;1701  }1702 1703  /// Unbold - Stop bolding text.1704  void Unbold() {1705    assert(IsBold && "Attempting to remove bold from unbold text.");1706    IsBold = false;1707    if (ShowColor)1708      OS << ToggleHighlight;1709  }1710 1711  // Functions to print out the arguments and highlighting the difference.1712 1713  /// PrintTypeNames - prints the typenames, bolding differences.  Will detect1714  /// typenames that are the same and attempt to disambiguate them by using1715  /// canonical typenames.1716  void PrintTypeNames(QualType FromType, QualType ToType,1717                      bool FromDefault, bool ToDefault, bool Same) {1718    assert((!FromType.isNull() || !ToType.isNull()) &&1719           "Only one template argument may be missing.");1720 1721    if (Same) {1722      OS << FromType.getAsString(Policy);1723      return;1724    }1725 1726    if (!FromType.isNull() && !ToType.isNull() &&1727        FromType.getLocalUnqualifiedType() ==1728        ToType.getLocalUnqualifiedType()) {1729      Qualifiers FromQual = FromType.getLocalQualifiers(),1730                 ToQual = ToType.getLocalQualifiers();1731      PrintQualifiers(FromQual, ToQual);1732      FromType.getLocalUnqualifiedType().print(OS, Policy);1733      return;1734    }1735 1736    std::string FromTypeStr = FromType.isNull() ? "(no argument)"1737                                                : FromType.getAsString(Policy);1738    std::string ToTypeStr =1739        ToType.isNull() ? "(no argument)" : ToType.getAsString(Policy);1740    // TODO: merge this with other aka printing above.1741    if (FromTypeStr == ToTypeStr) {1742      // Switch to canonical typename if it is better.1743      std::string FromCanTypeStr =1744          FromType.getCanonicalType().getAsString(Policy);1745      std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy);1746      if (FromCanTypeStr != ToCanTypeStr) {1747        FromTypeStr = FromCanTypeStr;1748        ToTypeStr = ToCanTypeStr;1749      }1750    }1751 1752    if (PrintTree)1753      OS << '[';1754    OS << (FromDefault ? "(default) " : "");1755    Bold();1756    OS << FromTypeStr;1757    Unbold();1758    if (PrintTree) {1759      OS << " != " << (ToDefault ? "(default) " : "");1760      Bold();1761      OS << ToTypeStr;1762      Unbold();1763      OS << "]";1764    }1765  }1766 1767  /// PrintExpr - Prints out the expr template arguments, highlighting argument1768  /// differences.1769  void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault,1770                 bool ToDefault, bool Same) {1771    assert((FromExpr || ToExpr) &&1772            "Only one template argument may be missing.");1773    if (Same) {1774      PrintExpr(FromExpr);1775    } else if (!PrintTree) {1776      OS << (FromDefault ? "(default) " : "");1777      Bold();1778      PrintExpr(FromExpr);1779      Unbold();1780    } else {1781      OS << (FromDefault ? "[(default) " : "[");1782      Bold();1783      PrintExpr(FromExpr);1784      Unbold();1785      OS << " != " << (ToDefault ? "(default) " : "");1786      Bold();1787      PrintExpr(ToExpr);1788      Unbold();1789      OS << ']';1790    }1791  }1792 1793  /// PrintExpr - Actual formatting and printing of expressions.1794  void PrintExpr(const Expr *E) {1795    if (E) {1796      E->printPretty(OS, nullptr, Policy);1797      return;1798    }1799    OS << "(no argument)";1800  }1801 1802  /// PrintTemplateTemplate - Handles printing of template template arguments,1803  /// highlighting argument differences.1804  void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,1805                             bool FromDefault, bool ToDefault, bool Same) {1806    assert((FromTD || ToTD) && "Only one template argument may be missing.");1807 1808    std::string FromName =1809        std::string(FromTD ? FromTD->getName() : "(no argument)");1810    std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");1811    if (FromTD && ToTD && FromName == ToName) {1812      FromName = FromTD->getQualifiedNameAsString();1813      ToName = ToTD->getQualifiedNameAsString();1814    }1815 1816    if (Same) {1817      OS << "template " << FromTD->getDeclName();1818    } else if (!PrintTree) {1819      OS << (FromDefault ? "(default) template " : "template ");1820      Bold();1821      OS << FromName;1822      Unbold();1823    } else {1824      OS << (FromDefault ? "[(default) template " : "[template ");1825      Bold();1826      OS << FromName;1827      Unbold();1828      OS << " != " << (ToDefault ? "(default) template " : "template ");1829      Bold();1830      OS << ToName;1831      Unbold();1832      OS << ']';1833    }1834  }1835 1836  /// PrintAPSInt - Handles printing of integral arguments, highlighting1837  /// argument differences.1838  void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,1839                   bool IsValidFromInt, bool IsValidToInt, QualType FromIntType,1840                   QualType ToIntType, Expr *FromExpr, Expr *ToExpr,1841                   bool FromDefault, bool ToDefault, bool Same) {1842    assert((IsValidFromInt || IsValidToInt) &&1843           "Only one integral argument may be missing.");1844 1845    if (Same) {1846      if (FromIntType->isBooleanType()) {1847        OS << ((FromInt == 0) ? "false" : "true");1848      } else {1849        OS << toString(FromInt, 10);1850      }1851      return;1852    }1853 1854    bool PrintType = IsValidFromInt && IsValidToInt &&1855                     !Context.hasSameType(FromIntType, ToIntType);1856 1857    if (!PrintTree) {1858      OS << (FromDefault ? "(default) " : "");1859      PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);1860    } else {1861      OS << (FromDefault ? "[(default) " : "[");1862      PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);1863      OS << " != " << (ToDefault ? "(default) " : "");1864      PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType);1865      OS << ']';1866    }1867  }1868 1869  /// PrintAPSInt - If valid, print the APSInt.  If the expression is1870  /// gives more information, print it too.1871  void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid,1872                   QualType IntType, bool PrintType) {1873    Bold();1874    if (Valid) {1875      if (HasExtraInfo(E)) {1876        PrintExpr(E);1877        Unbold();1878        OS << " aka ";1879        Bold();1880      }1881      if (PrintType) {1882        Unbold();1883        OS << "(";1884        Bold();1885        IntType.print(OS, Context.getPrintingPolicy());1886        Unbold();1887        OS << ") ";1888        Bold();1889      }1890      if (IntType->isBooleanType()) {1891        OS << ((Val == 0) ? "false" : "true");1892      } else {1893        OS << toString(Val, 10);1894      }1895    } else if (E) {1896      PrintExpr(E);1897    } else {1898      OS << "(no argument)";1899    }1900    Unbold();1901  }1902 1903  /// HasExtraInfo - Returns true if E is not an integer literal, the1904  /// negation of an integer literal, or a boolean literal.1905  bool HasExtraInfo(Expr *E) {1906    if (!E) return false;1907 1908    E = E->IgnoreImpCasts();1909 1910    auto CheckIntegerLiteral = [](Expr *E) {1911      if (auto *TemplateExpr = dyn_cast<SubstNonTypeTemplateParmExpr>(E))1912        E = TemplateExpr->getReplacement();1913      return isa<IntegerLiteral>(E);1914    };1915 1916    if (CheckIntegerLiteral(E)) return false;1917 1918    if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))1919      if (UO->getOpcode() == UO_Minus)1920        if (CheckIntegerLiteral(UO->getSubExpr()))1921          return false;1922 1923    if (isa<CXXBoolLiteralExpr>(E))1924      return false;1925 1926    return true;1927  }1928 1929  void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) {1930    if (VD) {1931      if (AddressOf)1932        OS << "&";1933      else if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD)) {1934        // FIXME: Diffing the APValue would be neat.1935        // FIXME: Suppress this and use the full name of the declaration if the1936        // parameter is a pointer or reference.1937        TPO->getType().getUnqualifiedType().print(OS, Policy);1938        TPO->printAsInit(OS, Policy);1939        return;1940      }1941      VD->printName(OS, Policy);1942      return;1943    }1944 1945    if (NullPtr) {1946      if (E && !isa<CXXNullPtrLiteralExpr>(E)) {1947        PrintExpr(E);1948        if (IsBold) {1949          Unbold();1950          OS << " aka ";1951          Bold();1952        } else {1953          OS << " aka ";1954        }1955      }1956 1957      OS << "nullptr";1958      return;1959    }1960 1961    if (E) {1962      PrintExpr(E);1963      return;1964    }1965 1966    OS << "(no argument)";1967  }1968 1969  /// PrintDecl - Handles printing of Decl arguments, highlighting1970  /// argument differences.1971  void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,1972                      bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,1973                      bool ToNullPtr, Expr *FromExpr, Expr *ToExpr,1974                      bool FromDefault, bool ToDefault, bool Same) {1975    assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&1976           "Only one Decl argument may be NULL");1977 1978    if (Same) {1979      PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);1980    } else if (!PrintTree) {1981      OS << (FromDefault ? "(default) " : "");1982      Bold();1983      PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);1984      Unbold();1985    } else {1986      OS << (FromDefault ? "[(default) " : "[");1987      Bold();1988      PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);1989      Unbold();1990      OS << " != " << (ToDefault ? "(default) " : "");1991      Bold();1992      PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr);1993      Unbold();1994      OS << ']';1995    }1996  }1997 1998  /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and1999  /// APSInt to print a mixed difference.2000  void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf,2001                                bool IsNullPtr, Expr *VDExpr, bool DefaultDecl,2002                                const llvm::APSInt &Val, QualType IntType,2003                                Expr *IntExpr, bool DefaultInt) {2004    if (!PrintTree) {2005      OS << (DefaultDecl ? "(default) " : "");2006      Bold();2007      PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);2008      Unbold();2009    } else {2010      OS << (DefaultDecl ? "[(default) " : "[");2011      Bold();2012      PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);2013      Unbold();2014      OS << " != " << (DefaultInt ? "(default) " : "");2015      PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);2016      OS << ']';2017    }2018  }2019 2020  /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and2021  /// ValueDecl to print a mixed difference.2022  void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType,2023                                Expr *IntExpr, bool DefaultInt, ValueDecl *VD,2024                                bool NeedAddressOf, bool IsNullPtr,2025                                Expr *VDExpr, bool DefaultDecl) {2026    if (!PrintTree) {2027      OS << (DefaultInt ? "(default) " : "");2028      PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);2029    } else {2030      OS << (DefaultInt ? "[(default) " : "[");2031      PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);2032      OS << " != " << (DefaultDecl ? "(default) " : "");2033      Bold();2034      PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);2035      Unbold();2036      OS << ']';2037    }2038  }2039 2040  // Prints the appropriate placeholder for elided template arguments.2041  void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {2042    if (PrintTree) {2043      OS << '\n';2044      for (unsigned i = 0; i < Indent; ++i)2045        OS << "  ";2046    }2047    if (NumElideArgs == 0) return;2048    if (NumElideArgs == 1)2049      OS << "[...]";2050    else2051      OS << "[" << NumElideArgs << " * ...]";2052  }2053 2054  // Prints and highlights differences in Qualifiers.2055  void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {2056    // Both types have no qualifiers2057    if (FromQual.empty() && ToQual.empty())2058      return;2059 2060    // Both types have same qualifiers2061    if (FromQual == ToQual) {2062      PrintQualifier(FromQual, /*ApplyBold*/false);2063      return;2064    }2065 2066    // Find common qualifiers and strip them from FromQual and ToQual.2067    Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual,2068                                                               ToQual);2069 2070    // The qualifiers are printed before the template name.2071    // Inline printing:2072    // The common qualifiers are printed.  Then, qualifiers only in this type2073    // are printed and highlighted.  Finally, qualifiers only in the other2074    // type are printed and highlighted inside parentheses after "missing".2075    // Tree printing:2076    // Qualifiers are printed next to each other, inside brackets, and2077    // separated by "!=".  The printing order is:2078    // common qualifiers, highlighted from qualifiers, "!=",2079    // common qualifiers, highlighted to qualifiers2080    if (PrintTree) {2081      OS << "[";2082      if (CommonQual.empty() && FromQual.empty()) {2083        Bold();2084        OS << "(no qualifiers) ";2085        Unbold();2086      } else {2087        PrintQualifier(CommonQual, /*ApplyBold*/false);2088        PrintQualifier(FromQual, /*ApplyBold*/true);2089      }2090      OS << "!= ";2091      if (CommonQual.empty() && ToQual.empty()) {2092        Bold();2093        OS << "(no qualifiers)";2094        Unbold();2095      } else {2096        PrintQualifier(CommonQual, /*ApplyBold*/false,2097                       /*appendSpaceIfNonEmpty*/!ToQual.empty());2098        PrintQualifier(ToQual, /*ApplyBold*/true,2099                       /*appendSpaceIfNonEmpty*/false);2100      }2101      OS << "] ";2102    } else {2103      PrintQualifier(CommonQual, /*ApplyBold*/false);2104      PrintQualifier(FromQual, /*ApplyBold*/true);2105    }2106  }2107 2108  void PrintQualifier(Qualifiers Q, bool ApplyBold,2109                      bool AppendSpaceIfNonEmpty = true) {2110    if (Q.empty()) return;2111    if (ApplyBold) Bold();2112    Q.print(OS, Policy, AppendSpaceIfNonEmpty);2113    if (ApplyBold) Unbold();2114  }2115 2116public:2117 2118  TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType,2119               QualType ToType, bool PrintTree, bool PrintFromType,2120               bool ElideType, bool ShowColor)2121    : Context(Context),2122      Policy(Context.getLangOpts()),2123      ElideType(ElideType),2124      PrintTree(PrintTree),2125      ShowColor(ShowColor),2126      // When printing a single type, the FromType is the one printed.2127      FromTemplateType(PrintFromType ? FromType : ToType),2128      ToTemplateType(PrintFromType ? ToType : FromType),2129      OS(OS),2130      IsBold(false) {2131  }2132 2133  /// DiffTemplate - Start the template type diffing.2134  void DiffTemplate() {2135    Qualifiers FromQual = FromTemplateType.getQualifiers(),2136               ToQual = ToTemplateType.getQualifiers();2137 2138    const TemplateSpecializationType *FromOrigTST =2139        GetTemplateSpecializationType(Context, FromTemplateType);2140    const TemplateSpecializationType *ToOrigTST =2141        GetTemplateSpecializationType(Context, ToTemplateType);2142 2143    // Only checking templates.2144    if (!FromOrigTST || !ToOrigTST)2145      return;2146 2147    // Different base templates.2148    if (!hasSameTemplate(Context, FromOrigTST, ToOrigTST)) {2149      return;2150    }2151 2152    FromQual -= QualType(FromOrigTST, 0).getQualifiers();2153    ToQual -= QualType(ToOrigTST, 0).getQualifiers();2154 2155    // Same base template, but different arguments.2156    Tree.SetTemplateDiff(2157        FromOrigTST->getTemplateName().getAsTemplateDecl(2158            /*IgnoreDeduced=*/true),2159        ToOrigTST->getTemplateName().getAsTemplateDecl(/*IgnoreDeduced=*/true),2160        FromQual, ToQual, false /*FromDefault*/, false /*ToDefault*/);2161 2162    DiffTemplate(FromOrigTST, ToOrigTST);2163  }2164 2165  /// Emit - When the two types given are templated types with the same2166  /// base template, a string representation of the type difference will be2167  /// emitted to the stream and return true.  Otherwise, return false.2168  bool Emit() {2169    Tree.StartTraverse();2170    if (Tree.Empty())2171      return false;2172 2173    TreeToString();2174    assert(!IsBold && "Bold is applied to end of string.");2175    return true;2176  }2177}; // end class TemplateDiff2178}  // end anonymous namespace2179 2180/// FormatTemplateTypeDiff - A helper static function to start the template2181/// diff and return the properly formatted string.  Returns true if the diff2182/// is successful.2183static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,2184                                   QualType ToType, bool PrintTree,2185                                   bool PrintFromType, bool ElideType,2186                                   bool ShowColors, raw_ostream &OS) {2187  if (PrintTree)2188    PrintFromType = true;2189  TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType,2190                  ElideType, ShowColors);2191  TD.DiffTemplate();2192  return TD.Emit();2193}2194 2195std::string clang::FormatUTFCodeUnitAsCodepoint(unsigned Value, QualType T) {2196  auto IsSingleCodeUnitCP = [](unsigned Value, QualType T) {2197    if (T->isChar8Type()) {2198      assert(Value <= 0xFF && "not a valid UTF-8 code unit");2199      return Value <= 0x7F;2200    }2201    if (T->isChar16Type()) {2202      assert(Value <= 0xFFFF && "not a valid UTF-16 code unit");2203      return llvm::IsSingleCodeUnitUTF16Codepoint(Value);2204    }2205    assert(T->isChar32Type());2206    return llvm::IsSingleCodeUnitUTF32Codepoint(Value);2207  };2208  llvm::SmallVector<char, 16> Str;2209  if (!IsSingleCodeUnitCP(Value, T)) {2210    llvm::raw_svector_ostream OS(Str);2211    OS << "<" << llvm::format_hex(Value, 1, /*Upper=*/true) << ">";2212    return std::string(Str.begin(), Str.end());2213  }2214 2215  char Buffer[UNI_MAX_UTF8_BYTES_PER_CODE_POINT];2216  char *Ptr = Buffer;2217  [[maybe_unused]] bool Converted = llvm::ConvertCodePointToUTF8(Value, Ptr);2218  assert(Converted && "trying to encode invalid code unit");2219  EscapeStringForDiagnostic(StringRef(Buffer, Ptr - Buffer), Str);2220  return std::string(Str.begin(), Str.end());2221}2222