Path: blob/main/contrib/llvm-project/clang/lib/AST/ASTDiagnostic.cpp
35260 views
//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements a diagnostic formatting hook for AST elements.9//10//===----------------------------------------------------------------------===//1112#include "clang/AST/ASTDiagnostic.h"13#include "clang/AST/ASTContext.h"14#include "clang/AST/ASTLambda.h"15#include "clang/AST/Attr.h"16#include "clang/AST/DeclObjC.h"17#include "clang/AST/DeclTemplate.h"18#include "clang/AST/ExprCXX.h"19#include "clang/AST/TemplateBase.h"20#include "clang/AST/Type.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/Support/raw_ostream.h"2324using namespace clang;2526// Returns a desugared version of the QualType, and marks ShouldAKA as true27// whenever we remove significant sugar from the type. Make sure ShouldAKA28// is initialized before passing it in.29QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,30bool &ShouldAKA) {31QualifierCollector QC;3233while (true) {34const Type *Ty = QC.strip(QT);3536// Don't aka just because we saw an elaborated type...37if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) {38QT = ET->desugar();39continue;40}41// ... or a using type ...42if (const UsingType *UT = dyn_cast<UsingType>(Ty)) {43QT = UT->desugar();44continue;45}46// ... or a paren type ...47if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {48QT = PT->desugar();49continue;50}51// ... or a macro defined type ...52if (const MacroQualifiedType *MDT = dyn_cast<MacroQualifiedType>(Ty)) {53QT = MDT->desugar();54continue;55}56// ...or a substituted template type parameter ...57if (const SubstTemplateTypeParmType *ST =58dyn_cast<SubstTemplateTypeParmType>(Ty)) {59QT = ST->desugar();60continue;61}62// ...or an attributed type...63if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) {64QT = AT->desugar();65continue;66}67// ...or an adjusted type...68if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) {69QT = AT->desugar();70continue;71}72// ... or an auto type.73if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {74if (!AT->isSugared())75break;76QT = AT->desugar();77continue;78}7980// Desugar FunctionType if return type or any parameter type should be81// desugared. Preserve nullability attribute on desugared types.82if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) {83bool DesugarReturn = false;84QualType SugarRT = FT->getReturnType();85QualType RT = desugarForDiagnostic(Context, SugarRT, DesugarReturn);86if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {87RT = Context.getAttributedType(88AttributedType::getNullabilityAttrKind(*nullability), RT, RT);89}9091bool DesugarArgument = false;92SmallVector<QualType, 4> Args;93const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);94if (FPT) {95for (QualType SugarPT : FPT->param_types()) {96QualType PT = desugarForDiagnostic(Context, SugarPT, DesugarArgument);97if (auto nullability =98AttributedType::stripOuterNullability(SugarPT)) {99PT = Context.getAttributedType(100AttributedType::getNullabilityAttrKind(*nullability), PT, PT);101}102Args.push_back(PT);103}104}105106if (DesugarReturn || DesugarArgument) {107ShouldAKA = true;108QT = FPT ? Context.getFunctionType(RT, Args, FPT->getExtProtoInfo())109: Context.getFunctionNoProtoType(RT, FT->getExtInfo());110break;111}112}113114// Desugar template specializations if any template argument should be115// desugared.116if (const TemplateSpecializationType *TST =117dyn_cast<TemplateSpecializationType>(Ty)) {118if (!TST->isTypeAlias()) {119bool DesugarArgument = false;120SmallVector<TemplateArgument, 4> Args;121for (const TemplateArgument &Arg : TST->template_arguments()) {122if (Arg.getKind() == TemplateArgument::Type)123Args.push_back(desugarForDiagnostic(Context, Arg.getAsType(),124DesugarArgument));125else126Args.push_back(Arg);127}128129if (DesugarArgument) {130ShouldAKA = true;131QT = Context.getTemplateSpecializationType(132TST->getTemplateName(), Args, QT);133}134break;135}136}137138if (const auto *AT = dyn_cast<ArrayType>(Ty)) {139QualType ElementTy =140desugarForDiagnostic(Context, AT->getElementType(), ShouldAKA);141if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))142QT = Context.getConstantArrayType(143ElementTy, CAT->getSize(), CAT->getSizeExpr(),144CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());145else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))146QT = Context.getVariableArrayType(147ElementTy, VAT->getSizeExpr(), VAT->getSizeModifier(),148VAT->getIndexTypeCVRQualifiers(), VAT->getBracketsRange());149else if (const auto *DSAT = dyn_cast<DependentSizedArrayType>(AT))150QT = Context.getDependentSizedArrayType(151ElementTy, DSAT->getSizeExpr(), DSAT->getSizeModifier(),152DSAT->getIndexTypeCVRQualifiers(), DSAT->getBracketsRange());153else if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT))154QT = Context.getIncompleteArrayType(ElementTy, IAT->getSizeModifier(),155IAT->getIndexTypeCVRQualifiers());156else157llvm_unreachable("Unhandled array type");158break;159}160161// Don't desugar magic Objective-C types.162if (QualType(Ty,0) == Context.getObjCIdType() ||163QualType(Ty,0) == Context.getObjCClassType() ||164QualType(Ty,0) == Context.getObjCSelType() ||165QualType(Ty,0) == Context.getObjCProtoType())166break;167168// Don't desugar va_list.169if (QualType(Ty, 0) == Context.getBuiltinVaListType() ||170QualType(Ty, 0) == Context.getBuiltinMSVaListType())171break;172173// Otherwise, do a single-step desugar.174QualType Underlying;175bool IsSugar = false;176switch (Ty->getTypeClass()) {177#define ABSTRACT_TYPE(Class, Base)178#define TYPE(Class, Base) \179case Type::Class: { \180const Class##Type *CTy = cast<Class##Type>(Ty); \181if (CTy->isSugared()) { \182IsSugar = true; \183Underlying = CTy->desugar(); \184} \185break; \186}187#include "clang/AST/TypeNodes.inc"188}189190// If it wasn't sugared, we're done.191if (!IsSugar)192break;193194// If the desugared type is a vector type, we don't want to expand195// it, it will turn into an attribute mess. People want their "vec4".196if (isa<VectorType>(Underlying))197break;198199// Don't desugar through the primary typedef of an anonymous type.200if (const TagType *UTT = Underlying->getAs<TagType>())201if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))202if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())203break;204205// Record that we actually looked through an opaque type here.206ShouldAKA = true;207QT = Underlying;208}209210// If we have a pointer-like type, desugar the pointee as well.211// FIXME: Handle other pointer-like types.212if (const PointerType *Ty = QT->getAs<PointerType>()) {213QT = Context.getPointerType(214desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));215} else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) {216QT = Context.getObjCObjectPointerType(217desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));218} else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {219QT = Context.getLValueReferenceType(220desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));221} else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {222QT = Context.getRValueReferenceType(223desugarForDiagnostic(Context, Ty->getPointeeType(), ShouldAKA));224} else if (const auto *Ty = QT->getAs<ObjCObjectType>()) {225if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {226QualType BaseType =227desugarForDiagnostic(Context, Ty->getBaseType(), ShouldAKA);228QT = Context.getObjCObjectType(229BaseType, Ty->getTypeArgsAsWritten(),230llvm::ArrayRef(Ty->qual_begin(), Ty->getNumProtocols()),231Ty->isKindOfTypeAsWritten());232}233}234235return QC.apply(Context, QT);236}237238/// Convert the given type to a string suitable for printing as part of239/// a diagnostic.240///241/// There are four main criteria when determining whether we should have an242/// a.k.a. clause when pretty-printing a type:243///244/// 1) Some types provide very minimal sugar that doesn't impede the245/// user's understanding --- for example, elaborated type246/// specifiers. If this is all the sugar we see, we don't want an247/// a.k.a. clause.248/// 2) Some types are technically sugared but are much more familiar249/// when seen in their sugared form --- for example, va_list,250/// vector types, and the magic Objective C types. We don't251/// want to desugar these, even if we do produce an a.k.a. clause.252/// 3) Some types may have already been desugared previously in this diagnostic.253/// if this is the case, doing another "aka" would just be clutter.254/// 4) Two different types within the same diagnostic have the same output255/// string. In this case, force an a.k.a with the desugared type when256/// doing so will provide additional information.257///258/// \param Context the context in which the type was allocated259/// \param Ty the type to print260/// \param QualTypeVals pointer values to QualTypes which are used in the261/// diagnostic message262static std::string263ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,264ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,265ArrayRef<intptr_t> QualTypeVals) {266// FIXME: Playing with std::string is really slow.267bool ForceAKA = false;268QualType CanTy = Ty.getCanonicalType();269std::string S = Ty.getAsString(Context.getPrintingPolicy());270std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());271272for (const intptr_t &QualTypeVal : QualTypeVals) {273QualType CompareTy =274QualType::getFromOpaquePtr(reinterpret_cast<void *>(QualTypeVal));275if (CompareTy.isNull())276continue;277if (CompareTy == Ty)278continue; // Same types279QualType CompareCanTy = CompareTy.getCanonicalType();280if (CompareCanTy == CanTy)281continue; // Same canonical types282std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());283bool ShouldAKA = false;284QualType CompareDesugar =285desugarForDiagnostic(Context, CompareTy, ShouldAKA);286std::string CompareDesugarStr =287CompareDesugar.getAsString(Context.getPrintingPolicy());288if (CompareS != S && CompareDesugarStr != S)289continue; // The type string is different than the comparison string290// and the desugared comparison string.291std::string CompareCanS =292CompareCanTy.getAsString(Context.getPrintingPolicy());293294if (CompareCanS == CanS)295continue; // No new info from canonical type296297ForceAKA = true;298break;299}300301// Check to see if we already desugared this type in this302// diagnostic. If so, don't do it again.303bool Repeated = false;304for (const auto &PrevArg : PrevArgs) {305// TODO: Handle ak_declcontext case.306if (PrevArg.first == DiagnosticsEngine::ak_qualtype) {307QualType PrevTy(308QualType::getFromOpaquePtr(reinterpret_cast<void *>(PrevArg.second)));309if (PrevTy == Ty) {310Repeated = true;311break;312}313}314}315316// Consider producing an a.k.a. clause if removing all the direct317// sugar gives us something "significantly different".318if (!Repeated) {319bool ShouldAKA = false;320QualType DesugaredTy = desugarForDiagnostic(Context, Ty, ShouldAKA);321if (ShouldAKA || ForceAKA) {322if (DesugaredTy == Ty) {323DesugaredTy = Ty.getCanonicalType();324}325std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy());326if (akaStr != S) {327S = "'" + S + "' (aka '" + akaStr + "')";328return S;329}330}331332// Give some additional info on vector types. These are either not desugared333// or displaying complex __attribute__ expressions so add details of the334// type and element count.335if (const auto *VTy = Ty->getAs<VectorType>()) {336std::string DecoratedString;337llvm::raw_string_ostream OS(DecoratedString);338const char *Values = VTy->getNumElements() > 1 ? "values" : "value";339OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '"340<< VTy->getElementType().getAsString(Context.getPrintingPolicy())341<< "' " << Values << ")";342return DecoratedString;343}344}345346S = "'" + S + "'";347return S;348}349350static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,351QualType ToType, bool PrintTree,352bool PrintFromType, bool ElideType,353bool ShowColors, raw_ostream &OS);354355void clang::FormatASTNodeDiagnosticArgument(356DiagnosticsEngine::ArgumentKind Kind,357intptr_t Val,358StringRef Modifier,359StringRef Argument,360ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,361SmallVectorImpl<char> &Output,362void *Cookie,363ArrayRef<intptr_t> QualTypeVals) {364ASTContext &Context = *static_cast<ASTContext*>(Cookie);365366size_t OldEnd = Output.size();367llvm::raw_svector_ostream OS(Output);368bool NeedQuotes = true;369370switch (Kind) {371default: llvm_unreachable("unknown ArgumentKind");372case DiagnosticsEngine::ak_addrspace: {373assert(Modifier.empty() && Argument.empty() &&374"Invalid modifier for Qualifiers argument");375376auto S = Qualifiers::getAddrSpaceAsString(static_cast<LangAS>(Val));377if (S.empty()) {378OS << (Context.getLangOpts().OpenCL ? "default" : "generic");379OS << " address space";380} else {381OS << "address space";382OS << " '" << S << "'";383}384NeedQuotes = false;385break;386}387case DiagnosticsEngine::ak_qual: {388assert(Modifier.empty() && Argument.empty() &&389"Invalid modifier for Qualifiers argument");390391Qualifiers Q(Qualifiers::fromOpaqueValue(Val));392auto S = Q.getAsString();393if (S.empty()) {394OS << "unqualified";395NeedQuotes = false;396} else {397OS << S;398}399break;400}401case DiagnosticsEngine::ak_qualtype_pair: {402TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val);403QualType FromType =404QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType));405QualType ToType =406QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType));407408if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree,409TDT.PrintFromType, TDT.ElideType,410TDT.ShowColors, OS)) {411NeedQuotes = !TDT.PrintTree;412TDT.TemplateDiffUsed = true;413break;414}415416// Don't fall-back during tree printing. The caller will handle417// this case.418if (TDT.PrintTree)419return;420421// Attempting to do a template diff on non-templates. Set the variables422// and continue with regular type printing of the appropriate type.423Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType;424Modifier = StringRef();425Argument = StringRef();426// Fall through427[[fallthrough]];428}429case DiagnosticsEngine::ak_qualtype: {430assert(Modifier.empty() && Argument.empty() &&431"Invalid modifier for QualType argument");432433QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val)));434OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals);435NeedQuotes = false;436break;437}438case DiagnosticsEngine::ak_declarationname: {439if (Modifier == "objcclass" && Argument.empty())440OS << '+';441else if (Modifier == "objcinstance" && Argument.empty())442OS << '-';443else444assert(Modifier.empty() && Argument.empty() &&445"Invalid modifier for DeclarationName argument");446447OS << DeclarationName::getFromOpaqueInteger(Val);448break;449}450case DiagnosticsEngine::ak_nameddecl: {451bool Qualified;452if (Modifier == "q" && Argument.empty())453Qualified = true;454else {455assert(Modifier.empty() && Argument.empty() &&456"Invalid modifier for NamedDecl* argument");457Qualified = false;458}459const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val);460ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified);461break;462}463case DiagnosticsEngine::ak_nestednamespec: {464NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val);465NNS->print(OS, Context.getPrintingPolicy());466NeedQuotes = false;467break;468}469case DiagnosticsEngine::ak_declcontext: {470DeclContext *DC = reinterpret_cast<DeclContext *> (Val);471assert(DC && "Should never have a null declaration context");472NeedQuotes = false;473474// FIXME: Get the strings for DeclContext from some localized place475if (DC->isTranslationUnit()) {476if (Context.getLangOpts().CPlusPlus)477OS << "the global namespace";478else479OS << "the global scope";480} else if (DC->isClosure()) {481OS << "block literal";482} else if (isLambdaCallOperator(DC)) {483OS << "lambda expression";484} else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) {485OS << ConvertTypeToDiagnosticString(Context,486Context.getTypeDeclType(Type),487PrevArgs, QualTypeVals);488} else {489assert(isa<NamedDecl>(DC) && "Expected a NamedDecl");490NamedDecl *ND = cast<NamedDecl>(DC);491if (isa<NamespaceDecl>(ND))492OS << "namespace ";493else if (isa<ObjCMethodDecl>(ND))494OS << "method ";495else if (isa<FunctionDecl>(ND))496OS << "function ";497498OS << '\'';499ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true);500OS << '\'';501}502break;503}504case DiagnosticsEngine::ak_attr: {505const Attr *At = reinterpret_cast<Attr *>(Val);506assert(At && "Received null Attr object!");507OS << '\'' << At->getSpelling() << '\'';508NeedQuotes = false;509break;510}511}512513if (NeedQuotes) {514Output.insert(Output.begin()+OldEnd, '\'');515Output.push_back('\'');516}517}518519/// TemplateDiff - A class that constructs a pretty string for a pair of520/// QualTypes. For the pair of types, a diff tree will be created containing521/// all the information about the templates and template arguments. Afterwards,522/// the tree is transformed to a string according to the options passed in.523namespace {524class TemplateDiff {525/// Context - The ASTContext which is used for comparing template arguments.526ASTContext &Context;527528/// Policy - Used during expression printing.529PrintingPolicy Policy;530531/// ElideType - Option to elide identical types.532bool ElideType;533534/// PrintTree - Format output string as a tree.535bool PrintTree;536537/// ShowColor - Diagnostics support color, so bolding will be used.538bool ShowColor;539540/// FromTemplateType - When single type printing is selected, this is the541/// type to be printed. When tree printing is selected, this type will542/// show up first in the tree.543QualType FromTemplateType;544545/// ToTemplateType - The type that FromType is compared to. Only in tree546/// printing will this type be outputed.547QualType ToTemplateType;548549/// OS - The stream used to construct the output strings.550raw_ostream &OS;551552/// IsBold - Keeps track of the bold formatting for the output string.553bool IsBold;554555/// DiffTree - A tree representation the differences between two types.556class DiffTree {557public:558/// DiffKind - The difference in a DiffNode. Fields of559/// TemplateArgumentInfo needed by each difference can be found in the560/// Set* and Get* functions.561enum DiffKind {562/// Incomplete or invalid node.563Invalid,564/// Another level of templates565Template,566/// Type difference, all type differences except those falling under567/// the Template difference.568Type,569/// Expression difference, this is only when both arguments are570/// expressions. If one argument is an expression and the other is571/// Integer or Declaration, then use that diff type instead.572Expression,573/// Template argument difference574TemplateTemplate,575/// Integer difference576Integer,577/// Declaration difference, nullptr arguments are included here578Declaration,579/// One argument being integer and the other being declaration580FromIntegerAndToDeclaration,581FromDeclarationAndToInteger582};583584private:585/// TemplateArgumentInfo - All the information needed to pretty print586/// a template argument. See the Set* and Get* functions to see which587/// fields are used for each DiffKind.588struct TemplateArgumentInfo {589QualType ArgType;590Qualifiers Qual;591llvm::APSInt Val;592bool IsValidInt = false;593Expr *ArgExpr = nullptr;594TemplateDecl *TD = nullptr;595ValueDecl *VD = nullptr;596bool NeedAddressOf = false;597bool IsNullPtr = false;598bool IsDefault = false;599};600601/// DiffNode - The root node stores the original type. Each child node602/// stores template arguments of their parents. For templated types, the603/// template decl is also stored.604struct DiffNode {605DiffKind Kind = Invalid;606607/// NextNode - The index of the next sibling node or 0.608unsigned NextNode = 0;609610/// ChildNode - The index of the first child node or 0.611unsigned ChildNode = 0;612613/// ParentNode - The index of the parent node.614unsigned ParentNode = 0;615616TemplateArgumentInfo FromArgInfo, ToArgInfo;617618/// Same - Whether the two arguments evaluate to the same value.619bool Same = false;620621DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {}622};623624/// FlatTree - A flattened tree used to store the DiffNodes.625SmallVector<DiffNode, 16> FlatTree;626627/// CurrentNode - The index of the current node being used.628unsigned CurrentNode;629630/// NextFreeNode - The index of the next unused node. Used when creating631/// child nodes.632unsigned NextFreeNode;633634/// ReadNode - The index of the current node being read.635unsigned ReadNode;636637public:638DiffTree() : CurrentNode(0), NextFreeNode(1), ReadNode(0) {639FlatTree.push_back(DiffNode());640}641642// Node writing functions, one for each valid DiffKind element.643void SetTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,644Qualifiers FromQual, Qualifiers ToQual,645bool FromDefault, bool ToDefault) {646assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");647FlatTree[CurrentNode].Kind = Template;648FlatTree[CurrentNode].FromArgInfo.TD = FromTD;649FlatTree[CurrentNode].ToArgInfo.TD = ToTD;650FlatTree[CurrentNode].FromArgInfo.Qual = FromQual;651FlatTree[CurrentNode].ToArgInfo.Qual = ToQual;652SetDefault(FromDefault, ToDefault);653}654655void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault,656bool ToDefault) {657assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");658FlatTree[CurrentNode].Kind = Type;659FlatTree[CurrentNode].FromArgInfo.ArgType = FromType;660FlatTree[CurrentNode].ToArgInfo.ArgType = ToType;661SetDefault(FromDefault, ToDefault);662}663664void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault,665bool ToDefault) {666assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");667FlatTree[CurrentNode].Kind = Expression;668FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;669FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;670SetDefault(FromDefault, ToDefault);671}672673void SetTemplateTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,674bool FromDefault, bool ToDefault) {675assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");676FlatTree[CurrentNode].Kind = TemplateTemplate;677FlatTree[CurrentNode].FromArgInfo.TD = FromTD;678FlatTree[CurrentNode].ToArgInfo.TD = ToTD;679SetDefault(FromDefault, ToDefault);680}681682void SetIntegerDiff(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,683bool IsValidFromInt, bool IsValidToInt,684QualType FromIntType, QualType ToIntType,685Expr *FromExpr, Expr *ToExpr, bool FromDefault,686bool ToDefault) {687assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");688FlatTree[CurrentNode].Kind = Integer;689FlatTree[CurrentNode].FromArgInfo.Val = FromInt;690FlatTree[CurrentNode].ToArgInfo.Val = ToInt;691FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;692FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;693FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;694FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;695FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;696FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;697SetDefault(FromDefault, ToDefault);698}699700void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,701bool FromAddressOf, bool ToAddressOf,702bool FromNullPtr, bool ToNullPtr, Expr *FromExpr,703Expr *ToExpr, bool FromDefault, bool ToDefault) {704assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");705FlatTree[CurrentNode].Kind = Declaration;706FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;707FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;708FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;709FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;710FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;711FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;712FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;713FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;714SetDefault(FromDefault, ToDefault);715}716717void SetFromDeclarationAndToIntegerDiff(718ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr,719Expr *FromExpr, const llvm::APSInt &ToInt, bool IsValidToInt,720QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) {721assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");722FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger;723FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;724FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;725FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;726FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;727FlatTree[CurrentNode].ToArgInfo.Val = ToInt;728FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;729FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;730FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;731SetDefault(FromDefault, ToDefault);732}733734void SetFromIntegerAndToDeclarationDiff(735const llvm::APSInt &FromInt, bool IsValidFromInt, QualType FromIntType,736Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf,737bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) {738assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");739FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration;740FlatTree[CurrentNode].FromArgInfo.Val = FromInt;741FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;742FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;743FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;744FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;745FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;746FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;747FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;748SetDefault(FromDefault, ToDefault);749}750751/// SetDefault - Sets FromDefault and ToDefault flags of the current node.752void SetDefault(bool FromDefault, bool ToDefault) {753assert((!FromDefault || !ToDefault) && "Both arguments cannot be default.");754FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault;755FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault;756}757758/// SetSame - Sets the same flag of the current node.759void SetSame(bool Same) {760FlatTree[CurrentNode].Same = Same;761}762763/// SetKind - Sets the current node's type.764void SetKind(DiffKind Kind) {765FlatTree[CurrentNode].Kind = Kind;766}767768/// Up - Changes the node to the parent of the current node.769void Up() {770assert(FlatTree[CurrentNode].Kind != Invalid &&771"Cannot exit node before setting node information.");772CurrentNode = FlatTree[CurrentNode].ParentNode;773}774775/// AddNode - Adds a child node to the current node, then sets that node776/// node as the current node.777void AddNode() {778assert(FlatTree[CurrentNode].Kind == Template &&779"Only Template nodes can have children nodes.");780FlatTree.push_back(DiffNode(CurrentNode));781DiffNode &Node = FlatTree[CurrentNode];782if (Node.ChildNode == 0) {783// If a child node doesn't exist, add one.784Node.ChildNode = NextFreeNode;785} else {786// If a child node exists, find the last child node and add a787// next node to it.788unsigned i;789for (i = Node.ChildNode; FlatTree[i].NextNode != 0;790i = FlatTree[i].NextNode) {791}792FlatTree[i].NextNode = NextFreeNode;793}794CurrentNode = NextFreeNode;795++NextFreeNode;796}797798// Node reading functions.799/// StartTraverse - Prepares the tree for recursive traversal.800void StartTraverse() {801ReadNode = 0;802CurrentNode = NextFreeNode;803NextFreeNode = 0;804}805806/// Parent - Move the current read node to its parent.807void Parent() {808ReadNode = FlatTree[ReadNode].ParentNode;809}810811void GetTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD,812Qualifiers &FromQual, Qualifiers &ToQual) {813assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind.");814FromTD = FlatTree[ReadNode].FromArgInfo.TD;815ToTD = FlatTree[ReadNode].ToArgInfo.TD;816FromQual = FlatTree[ReadNode].FromArgInfo.Qual;817ToQual = FlatTree[ReadNode].ToArgInfo.Qual;818}819820void GetTypeDiff(QualType &FromType, QualType &ToType) {821assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind");822FromType = FlatTree[ReadNode].FromArgInfo.ArgType;823ToType = FlatTree[ReadNode].ToArgInfo.ArgType;824}825826void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) {827assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind");828FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;829ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;830}831832void GetTemplateTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {833assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind.");834FromTD = FlatTree[ReadNode].FromArgInfo.TD;835ToTD = FlatTree[ReadNode].ToArgInfo.TD;836}837838void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt,839bool &IsValidFromInt, bool &IsValidToInt,840QualType &FromIntType, QualType &ToIntType,841Expr *&FromExpr, Expr *&ToExpr) {842assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind.");843FromInt = FlatTree[ReadNode].FromArgInfo.Val;844ToInt = FlatTree[ReadNode].ToArgInfo.Val;845IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;846IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;847FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;848ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;849FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;850ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;851}852853void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,854bool &FromAddressOf, bool &ToAddressOf,855bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr,856Expr *&ToExpr) {857assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind.");858FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;859ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;860FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;861ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;862FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;863ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;864FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;865ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;866}867868void GetFromDeclarationAndToIntegerDiff(869ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr,870Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt,871QualType &ToIntType, Expr *&ToExpr) {872assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger &&873"Unexpected kind.");874FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;875FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;876FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;877FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;878ToInt = FlatTree[ReadNode].ToArgInfo.Val;879IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;880ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;881ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;882}883884void GetFromIntegerAndToDeclarationDiff(885llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType,886Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf,887bool &ToNullPtr, Expr *&ToExpr) {888assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration &&889"Unexpected kind.");890FromInt = FlatTree[ReadNode].FromArgInfo.Val;891IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;892FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;893FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;894ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;895ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;896ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;897ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;898}899900/// FromDefault - Return true if the from argument is the default.901bool FromDefault() {902return FlatTree[ReadNode].FromArgInfo.IsDefault;903}904905/// ToDefault - Return true if the to argument is the default.906bool ToDefault() {907return FlatTree[ReadNode].ToArgInfo.IsDefault;908}909910/// NodeIsSame - Returns true the arguments are the same.911bool NodeIsSame() {912return FlatTree[ReadNode].Same;913}914915/// HasChildrend - Returns true if the node has children.916bool HasChildren() {917return FlatTree[ReadNode].ChildNode != 0;918}919920/// MoveToChild - Moves from the current node to its child.921void MoveToChild() {922ReadNode = FlatTree[ReadNode].ChildNode;923}924925/// AdvanceSibling - If there is a next sibling, advance to it and return926/// true. Otherwise, return false.927bool AdvanceSibling() {928if (FlatTree[ReadNode].NextNode == 0)929return false;930931ReadNode = FlatTree[ReadNode].NextNode;932return true;933}934935/// HasNextSibling - Return true if the node has a next sibling.936bool HasNextSibling() {937return FlatTree[ReadNode].NextNode != 0;938}939940/// Empty - Returns true if the tree has no information.941bool Empty() {942return GetKind() == Invalid;943}944945/// GetKind - Returns the current node's type.946DiffKind GetKind() {947return FlatTree[ReadNode].Kind;948}949};950951DiffTree Tree;952953/// TSTiterator - a pair of iterators that walks the954/// TemplateSpecializationType and the desugared TemplateSpecializationType.955/// The deseguared TemplateArgument should provide the canonical argument956/// for comparisons.957class TSTiterator {958typedef const TemplateArgument& reference;959typedef const TemplateArgument* pointer;960961/// InternalIterator - an iterator that is used to enter a962/// TemplateSpecializationType and read TemplateArguments inside template963/// parameter packs in order with the rest of the TemplateArguments.964struct InternalIterator {965/// TST - the template specialization whose arguments this iterator966/// traverse over.967const TemplateSpecializationType *TST;968969/// Index - the index of the template argument in TST.970unsigned Index;971972/// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA973/// points to a TemplateArgument within a parameter pack.974TemplateArgument::pack_iterator CurrentTA;975976/// EndTA - the end iterator of a parameter pack977TemplateArgument::pack_iterator EndTA;978979/// InternalIterator - Constructs an iterator and sets it to the first980/// template argument.981InternalIterator(const TemplateSpecializationType *TST)982: TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) {983if (!TST) return;984985if (isEnd()) return;986987// Set to first template argument. If not a parameter pack, done.988TemplateArgument TA = TST->template_arguments()[0];989if (TA.getKind() != TemplateArgument::Pack) return;990991// Start looking into the parameter pack.992CurrentTA = TA.pack_begin();993EndTA = TA.pack_end();994995// Found a valid template argument.996if (CurrentTA != EndTA) return;997998// Parameter pack is empty, use the increment to get to a valid999// template argument.1000++(*this);1001}10021003/// Return true if the iterator is non-singular.1004bool isValid() const { return TST; }10051006/// isEnd - Returns true if the iterator is one past the end.1007bool isEnd() const {1008assert(TST && "InternalIterator is invalid with a null TST.");1009return Index >= TST->template_arguments().size();1010}10111012/// &operator++ - Increment the iterator to the next template argument.1013InternalIterator &operator++() {1014assert(TST && "InternalIterator is invalid with a null TST.");1015if (isEnd()) {1016return *this;1017}10181019// If in a parameter pack, advance in the parameter pack.1020if (CurrentTA != EndTA) {1021++CurrentTA;1022if (CurrentTA != EndTA)1023return *this;1024}10251026// Loop until a template argument is found, or the end is reached.1027while (true) {1028// Advance to the next template argument. Break if reached the end.1029if (++Index == TST->template_arguments().size())1030break;10311032// If the TemplateArgument is not a parameter pack, done.1033TemplateArgument TA = TST->template_arguments()[Index];1034if (TA.getKind() != TemplateArgument::Pack)1035break;10361037// Handle parameter packs.1038CurrentTA = TA.pack_begin();1039EndTA = TA.pack_end();10401041// If the parameter pack is empty, try to advance again.1042if (CurrentTA != EndTA)1043break;1044}1045return *this;1046}10471048/// operator* - Returns the appropriate TemplateArgument.1049reference operator*() const {1050assert(TST && "InternalIterator is invalid with a null TST.");1051assert(!isEnd() && "Index exceeds number of arguments.");1052if (CurrentTA == EndTA)1053return TST->template_arguments()[Index];1054else1055return *CurrentTA;1056}10571058/// operator-> - Allow access to the underlying TemplateArgument.1059pointer operator->() const {1060assert(TST && "InternalIterator is invalid with a null TST.");1061return &operator*();1062}1063};10641065InternalIterator SugaredIterator;1066InternalIterator DesugaredIterator;10671068public:1069TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)1070: SugaredIterator(TST),1071DesugaredIterator(1072(TST->isSugared() && !TST->isTypeAlias())1073? GetTemplateSpecializationType(Context, TST->desugar())1074: nullptr) {}10751076/// &operator++ - Increment the iterator to the next template argument.1077TSTiterator &operator++() {1078++SugaredIterator;1079if (DesugaredIterator.isValid())1080++DesugaredIterator;1081return *this;1082}10831084/// operator* - Returns the appropriate TemplateArgument.1085reference operator*() const {1086return *SugaredIterator;1087}10881089/// operator-> - Allow access to the underlying TemplateArgument.1090pointer operator->() const {1091return &operator*();1092}10931094/// isEnd - Returns true if no more TemplateArguments are available.1095bool isEnd() const {1096return SugaredIterator.isEnd();1097}10981099/// hasDesugaredTA - Returns true if there is another TemplateArgument1100/// available.1101bool hasDesugaredTA() const {1102return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();1103}11041105/// getDesugaredTA - Returns the desugared TemplateArgument.1106reference getDesugaredTA() const {1107assert(DesugaredIterator.isValid() &&1108"Desugared TemplateArgument should not be used.");1109return *DesugaredIterator;1110}1111};11121113// These functions build up the template diff tree, including functions to1114// retrieve and compare template arguments.11151116static const TemplateSpecializationType *GetTemplateSpecializationType(1117ASTContext &Context, QualType Ty) {1118if (const TemplateSpecializationType *TST =1119Ty->getAs<TemplateSpecializationType>())1120return TST;11211122if (const auto* SubstType = Ty->getAs<SubstTemplateTypeParmType>())1123Ty = SubstType->getReplacementType();11241125const RecordType *RT = Ty->getAs<RecordType>();11261127if (!RT)1128return nullptr;11291130const ClassTemplateSpecializationDecl *CTSD =1131dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());11321133if (!CTSD)1134return nullptr;11351136Ty = Context.getTemplateSpecializationType(1137TemplateName(CTSD->getSpecializedTemplate()),1138CTSD->getTemplateArgs().asArray(),1139Ty.getLocalUnqualifiedType().getCanonicalType());11401141return Ty->getAs<TemplateSpecializationType>();1142}11431144/// Returns true if the DiffType is Type and false for Template.1145static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType,1146QualType ToType,1147const TemplateSpecializationType *&FromArgTST,1148const TemplateSpecializationType *&ToArgTST) {1149if (FromType.isNull() || ToType.isNull())1150return true;11511152if (Context.hasSameType(FromType, ToType))1153return true;11541155FromArgTST = GetTemplateSpecializationType(Context, FromType);1156ToArgTST = GetTemplateSpecializationType(Context, ToType);11571158if (!FromArgTST || !ToArgTST)1159return true;11601161if (!hasSameTemplate(FromArgTST, ToArgTST))1162return true;11631164return false;1165}11661167/// DiffTypes - Fills a DiffNode with information about a type difference.1168void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) {1169QualType FromType = GetType(FromIter);1170QualType ToType = GetType(ToIter);11711172bool FromDefault = FromIter.isEnd() && !FromType.isNull();1173bool ToDefault = ToIter.isEnd() && !ToType.isNull();11741175const TemplateSpecializationType *FromArgTST = nullptr;1176const TemplateSpecializationType *ToArgTST = nullptr;1177if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) {1178Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault);1179Tree.SetSame(!FromType.isNull() && !ToType.isNull() &&1180Context.hasSameType(FromType, ToType));1181} else {1182assert(FromArgTST && ToArgTST &&1183"Both template specializations need to be valid.");1184Qualifiers FromQual = FromType.getQualifiers(),1185ToQual = ToType.getQualifiers();1186FromQual -= QualType(FromArgTST, 0).getQualifiers();1187ToQual -= QualType(ToArgTST, 0).getQualifiers();1188Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(),1189ToArgTST->getTemplateName().getAsTemplateDecl(),1190FromQual, ToQual, FromDefault, ToDefault);1191DiffTemplate(FromArgTST, ToArgTST);1192}1193}11941195/// DiffTemplateTemplates - Fills a DiffNode with information about a1196/// template template difference.1197void DiffTemplateTemplates(const TSTiterator &FromIter,1198const TSTiterator &ToIter) {1199TemplateDecl *FromDecl = GetTemplateDecl(FromIter);1200TemplateDecl *ToDecl = GetTemplateDecl(ToIter);1201Tree.SetTemplateTemplateDiff(FromDecl, ToDecl, FromIter.isEnd() && FromDecl,1202ToIter.isEnd() && ToDecl);1203Tree.SetSame(FromDecl && ToDecl &&1204FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());1205}12061207/// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes1208static void InitializeNonTypeDiffVariables(ASTContext &Context,1209const TSTiterator &Iter,1210NonTypeTemplateParmDecl *Default,1211llvm::APSInt &Value, bool &HasInt,1212QualType &IntType, bool &IsNullPtr,1213Expr *&E, ValueDecl *&VD,1214bool &NeedAddressOf) {1215if (!Iter.isEnd()) {1216switch (Iter->getKind()) {1217case TemplateArgument::StructuralValue:1218// FIXME: Diffing of structural values is not implemented.1219// There is no possible fallback in this case, this will show up1220// as '(no argument)'.1221return;1222case TemplateArgument::Integral:1223Value = Iter->getAsIntegral();1224HasInt = true;1225IntType = Iter->getIntegralType();1226return;1227case TemplateArgument::Declaration: {1228VD = Iter->getAsDecl();1229QualType ArgType = Iter->getParamTypeForDecl();1230QualType VDType = VD->getType();1231if (ArgType->isPointerType() &&1232Context.hasSameType(ArgType->getPointeeType(), VDType))1233NeedAddressOf = true;1234return;1235}1236case TemplateArgument::NullPtr:1237IsNullPtr = true;1238return;1239case TemplateArgument::Expression:1240E = Iter->getAsExpr();1241break;1242case TemplateArgument::Null:1243case TemplateArgument::Type:1244case TemplateArgument::Template:1245case TemplateArgument::TemplateExpansion:1246llvm_unreachable("TemplateArgument kind is not expected for NTTP");1247case TemplateArgument::Pack:1248llvm_unreachable("TemplateArgument kind should be handled elsewhere");1249}1250} else if (!Default->isParameterPack()) {1251E = Default->getDefaultArgument().getArgument().getAsExpr();1252}12531254if (!Iter.hasDesugaredTA())1255return;12561257const TemplateArgument &TA = Iter.getDesugaredTA();1258switch (TA.getKind()) {1259case TemplateArgument::StructuralValue:1260// FIXME: Diffing of structural values is not implemented.1261// Just fall back to the expression.1262return;1263case TemplateArgument::Integral:1264Value = TA.getAsIntegral();1265HasInt = true;1266IntType = TA.getIntegralType();1267return;1268case TemplateArgument::Declaration: {1269VD = TA.getAsDecl();1270QualType ArgType = TA.getParamTypeForDecl();1271QualType VDType = VD->getType();1272if (ArgType->isPointerType() &&1273Context.hasSameType(ArgType->getPointeeType(), VDType))1274NeedAddressOf = true;1275return;1276}1277case TemplateArgument::NullPtr:1278IsNullPtr = true;1279return;1280case TemplateArgument::Expression:1281// TODO: Sometimes, the desugared template argument Expr differs from1282// the sugared template argument Expr. It may be useful in the future1283// but for now, it is just discarded.1284if (!E)1285E = TA.getAsExpr();1286return;1287case TemplateArgument::Null:1288case TemplateArgument::Type:1289case TemplateArgument::Template:1290case TemplateArgument::TemplateExpansion:1291llvm_unreachable("TemplateArgument kind is not expected for NTTP");1292case TemplateArgument::Pack:1293llvm_unreachable("TemplateArgument kind should be handled elsewhere");1294}1295llvm_unreachable("Unexpected TemplateArgument kind");1296}12971298/// DiffNonTypes - Handles any template parameters not handled by DiffTypes1299/// of DiffTemplatesTemplates, such as integer and declaration parameters.1300void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,1301NonTypeTemplateParmDecl *FromDefaultNonTypeDecl,1302NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) {1303Expr *FromExpr = nullptr, *ToExpr = nullptr;1304llvm::APSInt FromInt, ToInt;1305QualType FromIntType, ToIntType;1306ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;1307bool HasFromInt = false, HasToInt = false, FromNullPtr = false,1308ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;1309InitializeNonTypeDiffVariables(1310Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt,1311FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf);1312InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt,1313HasToInt, ToIntType, ToNullPtr, ToExpr,1314ToValueDecl, NeedToAddressOf);13151316bool FromDefault = FromIter.isEnd() &&1317(FromExpr || FromValueDecl || HasFromInt || FromNullPtr);1318bool ToDefault = ToIter.isEnd() &&1319(ToExpr || ToValueDecl || HasToInt || ToNullPtr);13201321bool FromDeclaration = FromValueDecl || FromNullPtr;1322bool ToDeclaration = ToValueDecl || ToNullPtr;13231324if (FromDeclaration && HasToInt) {1325Tree.SetFromDeclarationAndToIntegerDiff(1326FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt,1327HasToInt, ToIntType, ToExpr, FromDefault, ToDefault);1328Tree.SetSame(false);1329return;13301331}13321333if (HasFromInt && ToDeclaration) {1334Tree.SetFromIntegerAndToDeclarationDiff(1335FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl,1336NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault);1337Tree.SetSame(false);1338return;1339}13401341if (HasFromInt || HasToInt) {1342Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,1343ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);1344if (HasFromInt && HasToInt) {1345Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) &&1346FromInt == ToInt);1347}1348return;1349}13501351if (FromDeclaration || ToDeclaration) {1352Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf,1353NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr,1354ToExpr, FromDefault, ToDefault);1355bool BothNull = FromNullPtr && ToNullPtr;1356bool SameValueDecl =1357FromValueDecl && ToValueDecl &&1358NeedFromAddressOf == NeedToAddressOf &&1359FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl();1360Tree.SetSame(BothNull || SameValueDecl);1361return;1362}13631364assert((FromExpr || ToExpr) && "Both template arguments cannot be empty.");1365Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault);1366Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));1367}13681369/// DiffTemplate - recursively visits template arguments and stores the1370/// argument info into a tree.1371void DiffTemplate(const TemplateSpecializationType *FromTST,1372const TemplateSpecializationType *ToTST) {1373// Begin descent into diffing template tree.1374TemplateParameterList *ParamsFrom =1375FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();1376TemplateParameterList *ParamsTo =1377ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();1378unsigned TotalArgs = 0;1379for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST);1380!FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {1381Tree.AddNode();13821383// Get the parameter at index TotalArgs. If index is larger1384// than the total number of parameters, then there is an1385// argument pack, so re-use the last parameter.1386unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);1387unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1);1388NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex);1389NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex);13901391assert(FromParamND->getKind() == ToParamND->getKind() &&1392"Parameter Decl are not the same kind.");13931394if (isa<TemplateTypeParmDecl>(FromParamND)) {1395DiffTypes(FromIter, ToIter);1396} else if (isa<TemplateTemplateParmDecl>(FromParamND)) {1397DiffTemplateTemplates(FromIter, ToIter);1398} else if (isa<NonTypeTemplateParmDecl>(FromParamND)) {1399NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =1400cast<NonTypeTemplateParmDecl>(FromParamND);1401NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =1402cast<NonTypeTemplateParmDecl>(ToParamND);1403DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,1404ToDefaultNonTypeDecl);1405} else {1406llvm_unreachable("Unexpected Decl type.");1407}14081409++FromIter;1410++ToIter;1411Tree.Up();1412}1413}14141415/// makeTemplateList - Dump every template alias into the vector.1416static void makeTemplateList(1417SmallVectorImpl<const TemplateSpecializationType *> &TemplateList,1418const TemplateSpecializationType *TST) {1419while (TST) {1420TemplateList.push_back(TST);1421if (!TST->isTypeAlias())1422return;1423TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();1424}1425}14261427/// hasSameBaseTemplate - Returns true when the base templates are the same,1428/// even if the template arguments are not.1429static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST,1430const TemplateSpecializationType *ToTST) {1431return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() ==1432ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl();1433}14341435/// hasSameTemplate - Returns true if both types are specialized from the1436/// same template declaration. If they come from different template aliases,1437/// do a parallel ascension search to determine the highest template alias in1438/// common and set the arguments to them.1439static bool hasSameTemplate(const TemplateSpecializationType *&FromTST,1440const TemplateSpecializationType *&ToTST) {1441// Check the top templates if they are the same.1442if (hasSameBaseTemplate(FromTST, ToTST))1443return true;14441445// Create vectors of template aliases.1446SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,1447ToTemplateList;14481449makeTemplateList(FromTemplateList, FromTST);1450makeTemplateList(ToTemplateList, ToTST);14511452SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator1453FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),1454ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();14551456// Check if the lowest template types are the same. If not, return.1457if (!hasSameBaseTemplate(*FromIter, *ToIter))1458return false;14591460// Begin searching up the template aliases. The bottom most template1461// matches so move up until one pair does not match. Use the template1462// right before that one.1463for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {1464if (!hasSameBaseTemplate(*FromIter, *ToIter))1465break;1466}14671468FromTST = FromIter[-1];1469ToTST = ToIter[-1];14701471return true;1472}14731474/// GetType - Retrieves the template type arguments, including default1475/// arguments.1476static QualType GetType(const TSTiterator &Iter) {1477if (!Iter.isEnd())1478return Iter->getAsType();1479if (Iter.hasDesugaredTA())1480return Iter.getDesugaredTA().getAsType();1481return QualType();1482}14831484/// GetTemplateDecl - Retrieves the template template arguments, including1485/// default arguments.1486static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) {1487if (!Iter.isEnd())1488return Iter->getAsTemplate().getAsTemplateDecl();1489if (Iter.hasDesugaredTA())1490return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl();1491return nullptr;1492}14931494/// IsEqualExpr - Returns true if the expressions are the same in regards to1495/// template arguments. These expressions are dependent, so profile them1496/// instead of trying to evaluate them.1497static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {1498if (FromExpr == ToExpr)1499return true;15001501if (!FromExpr || !ToExpr)1502return false;15031504llvm::FoldingSetNodeID FromID, ToID;1505FromExpr->Profile(FromID, Context, true);1506ToExpr->Profile(ToID, Context, true);1507return FromID == ToID;1508}15091510// These functions converts the tree representation of the template1511// differences into the internal character vector.15121513/// TreeToString - Converts the Tree object into a character stream which1514/// will later be turned into the output string.1515void TreeToString(int Indent = 1) {1516if (PrintTree) {1517OS << '\n';1518OS.indent(2 * Indent);1519++Indent;1520}15211522// Handle cases where the difference is not templates with different1523// arguments.1524switch (Tree.GetKind()) {1525case DiffTree::Invalid:1526llvm_unreachable("Template diffing failed with bad DiffNode");1527case DiffTree::Type: {1528QualType FromType, ToType;1529Tree.GetTypeDiff(FromType, ToType);1530PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),1531Tree.NodeIsSame());1532return;1533}1534case DiffTree::Expression: {1535Expr *FromExpr, *ToExpr;1536Tree.GetExpressionDiff(FromExpr, ToExpr);1537PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),1538Tree.NodeIsSame());1539return;1540}1541case DiffTree::TemplateTemplate: {1542TemplateDecl *FromTD, *ToTD;1543Tree.GetTemplateTemplateDiff(FromTD, ToTD);1544PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),1545Tree.ToDefault(), Tree.NodeIsSame());1546return;1547}1548case DiffTree::Integer: {1549llvm::APSInt FromInt, ToInt;1550Expr *FromExpr, *ToExpr;1551bool IsValidFromInt, IsValidToInt;1552QualType FromIntType, ToIntType;1553Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,1554FromIntType, ToIntType, FromExpr, ToExpr);1555PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,1556ToIntType, FromExpr, ToExpr, Tree.FromDefault(),1557Tree.ToDefault(), Tree.NodeIsSame());1558return;1559}1560case DiffTree::Declaration: {1561ValueDecl *FromValueDecl, *ToValueDecl;1562bool FromAddressOf, ToAddressOf;1563bool FromNullPtr, ToNullPtr;1564Expr *FromExpr, *ToExpr;1565Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf,1566ToAddressOf, FromNullPtr, ToNullPtr, FromExpr,1567ToExpr);1568PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,1569FromNullPtr, ToNullPtr, FromExpr, ToExpr,1570Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());1571return;1572}1573case DiffTree::FromDeclarationAndToInteger: {1574ValueDecl *FromValueDecl;1575bool FromAddressOf;1576bool FromNullPtr;1577Expr *FromExpr;1578llvm::APSInt ToInt;1579bool IsValidToInt;1580QualType ToIntType;1581Expr *ToExpr;1582Tree.GetFromDeclarationAndToIntegerDiff(1583FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt,1584IsValidToInt, ToIntType, ToExpr);1585assert((FromValueDecl || FromNullPtr) && IsValidToInt);1586PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr,1587FromExpr, Tree.FromDefault(), ToInt, ToIntType,1588ToExpr, Tree.ToDefault());1589return;1590}1591case DiffTree::FromIntegerAndToDeclaration: {1592llvm::APSInt FromInt;1593bool IsValidFromInt;1594QualType FromIntType;1595Expr *FromExpr;1596ValueDecl *ToValueDecl;1597bool ToAddressOf;1598bool ToNullPtr;1599Expr *ToExpr;1600Tree.GetFromIntegerAndToDeclarationDiff(1601FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl,1602ToAddressOf, ToNullPtr, ToExpr);1603assert(IsValidFromInt && (ToValueDecl || ToNullPtr));1604PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr,1605Tree.FromDefault(), ToValueDecl, ToAddressOf,1606ToNullPtr, ToExpr, Tree.ToDefault());1607return;1608}1609case DiffTree::Template: {1610// Node is root of template. Recurse on children.1611TemplateDecl *FromTD, *ToTD;1612Qualifiers FromQual, ToQual;1613Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual);16141615PrintQualifiers(FromQual, ToQual);16161617if (!Tree.HasChildren()) {1618// If we're dealing with a template specialization with zero1619// arguments, there are no children; special-case this.1620OS << FromTD->getDeclName() << "<>";1621return;1622}16231624OS << FromTD->getDeclName() << '<';1625Tree.MoveToChild();1626unsigned NumElideArgs = 0;1627bool AllArgsElided = true;1628do {1629if (ElideType) {1630if (Tree.NodeIsSame()) {1631++NumElideArgs;1632continue;1633}1634AllArgsElided = false;1635if (NumElideArgs > 0) {1636PrintElideArgs(NumElideArgs, Indent);1637NumElideArgs = 0;1638OS << ", ";1639}1640}1641TreeToString(Indent);1642if (Tree.HasNextSibling())1643OS << ", ";1644} while (Tree.AdvanceSibling());1645if (NumElideArgs > 0) {1646if (AllArgsElided)1647OS << "...";1648else1649PrintElideArgs(NumElideArgs, Indent);1650}16511652Tree.Parent();1653OS << ">";1654return;1655}1656}1657}16581659// To signal to the text printer that a certain text needs to be bolded,1660// a special character is injected into the character stream which the1661// text printer will later strip out.16621663/// Bold - Start bolding text.1664void Bold() {1665assert(!IsBold && "Attempting to bold text that is already bold.");1666IsBold = true;1667if (ShowColor)1668OS << ToggleHighlight;1669}16701671/// Unbold - Stop bolding text.1672void Unbold() {1673assert(IsBold && "Attempting to remove bold from unbold text.");1674IsBold = false;1675if (ShowColor)1676OS << ToggleHighlight;1677}16781679// Functions to print out the arguments and highlighting the difference.16801681/// PrintTypeNames - prints the typenames, bolding differences. Will detect1682/// typenames that are the same and attempt to disambiguate them by using1683/// canonical typenames.1684void PrintTypeNames(QualType FromType, QualType ToType,1685bool FromDefault, bool ToDefault, bool Same) {1686assert((!FromType.isNull() || !ToType.isNull()) &&1687"Only one template argument may be missing.");16881689if (Same) {1690OS << FromType.getAsString(Policy);1691return;1692}16931694if (!FromType.isNull() && !ToType.isNull() &&1695FromType.getLocalUnqualifiedType() ==1696ToType.getLocalUnqualifiedType()) {1697Qualifiers FromQual = FromType.getLocalQualifiers(),1698ToQual = ToType.getLocalQualifiers();1699PrintQualifiers(FromQual, ToQual);1700FromType.getLocalUnqualifiedType().print(OS, Policy);1701return;1702}17031704std::string FromTypeStr = FromType.isNull() ? "(no argument)"1705: FromType.getAsString(Policy);1706std::string ToTypeStr = ToType.isNull() ? "(no argument)"1707: ToType.getAsString(Policy);1708// Print without ElaboratedType sugar if it is better.1709// TODO: merge this with other aka printing above.1710if (FromTypeStr == ToTypeStr) {1711const auto *FromElTy = dyn_cast<ElaboratedType>(FromType),1712*ToElTy = dyn_cast<ElaboratedType>(ToType);1713if (FromElTy || ToElTy) {1714std::string FromNamedTypeStr =1715FromElTy ? FromElTy->getNamedType().getAsString(Policy)1716: FromTypeStr;1717std::string ToNamedTypeStr =1718ToElTy ? ToElTy->getNamedType().getAsString(Policy) : ToTypeStr;1719if (FromNamedTypeStr != ToNamedTypeStr) {1720FromTypeStr = FromNamedTypeStr;1721ToTypeStr = ToNamedTypeStr;1722goto PrintTypes;1723}1724}1725// Switch to canonical typename if it is better.1726std::string FromCanTypeStr =1727FromType.getCanonicalType().getAsString(Policy);1728std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy);1729if (FromCanTypeStr != ToCanTypeStr) {1730FromTypeStr = FromCanTypeStr;1731ToTypeStr = ToCanTypeStr;1732}1733}17341735PrintTypes:1736if (PrintTree) OS << '[';1737OS << (FromDefault ? "(default) " : "");1738Bold();1739OS << FromTypeStr;1740Unbold();1741if (PrintTree) {1742OS << " != " << (ToDefault ? "(default) " : "");1743Bold();1744OS << ToTypeStr;1745Unbold();1746OS << "]";1747}1748}17491750/// PrintExpr - Prints out the expr template arguments, highlighting argument1751/// differences.1752void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault,1753bool ToDefault, bool Same) {1754assert((FromExpr || ToExpr) &&1755"Only one template argument may be missing.");1756if (Same) {1757PrintExpr(FromExpr);1758} else if (!PrintTree) {1759OS << (FromDefault ? "(default) " : "");1760Bold();1761PrintExpr(FromExpr);1762Unbold();1763} else {1764OS << (FromDefault ? "[(default) " : "[");1765Bold();1766PrintExpr(FromExpr);1767Unbold();1768OS << " != " << (ToDefault ? "(default) " : "");1769Bold();1770PrintExpr(ToExpr);1771Unbold();1772OS << ']';1773}1774}17751776/// PrintExpr - Actual formatting and printing of expressions.1777void PrintExpr(const Expr *E) {1778if (E) {1779E->printPretty(OS, nullptr, Policy);1780return;1781}1782OS << "(no argument)";1783}17841785/// PrintTemplateTemplate - Handles printing of template template arguments,1786/// highlighting argument differences.1787void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,1788bool FromDefault, bool ToDefault, bool Same) {1789assert((FromTD || ToTD) && "Only one template argument may be missing.");17901791std::string FromName =1792std::string(FromTD ? FromTD->getName() : "(no argument)");1793std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");1794if (FromTD && ToTD && FromName == ToName) {1795FromName = FromTD->getQualifiedNameAsString();1796ToName = ToTD->getQualifiedNameAsString();1797}17981799if (Same) {1800OS << "template " << FromTD->getDeclName();1801} else if (!PrintTree) {1802OS << (FromDefault ? "(default) template " : "template ");1803Bold();1804OS << FromName;1805Unbold();1806} else {1807OS << (FromDefault ? "[(default) template " : "[template ");1808Bold();1809OS << FromName;1810Unbold();1811OS << " != " << (ToDefault ? "(default) template " : "template ");1812Bold();1813OS << ToName;1814Unbold();1815OS << ']';1816}1817}18181819/// PrintAPSInt - Handles printing of integral arguments, highlighting1820/// argument differences.1821void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,1822bool IsValidFromInt, bool IsValidToInt, QualType FromIntType,1823QualType ToIntType, Expr *FromExpr, Expr *ToExpr,1824bool FromDefault, bool ToDefault, bool Same) {1825assert((IsValidFromInt || IsValidToInt) &&1826"Only one integral argument may be missing.");18271828if (Same) {1829if (FromIntType->isBooleanType()) {1830OS << ((FromInt == 0) ? "false" : "true");1831} else {1832OS << toString(FromInt, 10);1833}1834return;1835}18361837bool PrintType = IsValidFromInt && IsValidToInt &&1838!Context.hasSameType(FromIntType, ToIntType);18391840if (!PrintTree) {1841OS << (FromDefault ? "(default) " : "");1842PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);1843} else {1844OS << (FromDefault ? "[(default) " : "[");1845PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);1846OS << " != " << (ToDefault ? "(default) " : "");1847PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType);1848OS << ']';1849}1850}18511852/// PrintAPSInt - If valid, print the APSInt. If the expression is1853/// gives more information, print it too.1854void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid,1855QualType IntType, bool PrintType) {1856Bold();1857if (Valid) {1858if (HasExtraInfo(E)) {1859PrintExpr(E);1860Unbold();1861OS << " aka ";1862Bold();1863}1864if (PrintType) {1865Unbold();1866OS << "(";1867Bold();1868IntType.print(OS, Context.getPrintingPolicy());1869Unbold();1870OS << ") ";1871Bold();1872}1873if (IntType->isBooleanType()) {1874OS << ((Val == 0) ? "false" : "true");1875} else {1876OS << toString(Val, 10);1877}1878} else if (E) {1879PrintExpr(E);1880} else {1881OS << "(no argument)";1882}1883Unbold();1884}18851886/// HasExtraInfo - Returns true if E is not an integer literal, the1887/// negation of an integer literal, or a boolean literal.1888bool HasExtraInfo(Expr *E) {1889if (!E) return false;18901891E = E->IgnoreImpCasts();18921893if (isa<IntegerLiteral>(E)) return false;18941895if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E))1896if (UO->getOpcode() == UO_Minus)1897if (isa<IntegerLiteral>(UO->getSubExpr()))1898return false;18991900if (isa<CXXBoolLiteralExpr>(E))1901return false;19021903return true;1904}19051906void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) {1907if (VD) {1908if (AddressOf)1909OS << "&";1910else if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(VD)) {1911// FIXME: Diffing the APValue would be neat.1912// FIXME: Suppress this and use the full name of the declaration if the1913// parameter is a pointer or reference.1914TPO->getType().getUnqualifiedType().print(OS, Policy);1915TPO->printAsInit(OS, Policy);1916return;1917}1918VD->printName(OS, Policy);1919return;1920}19211922if (NullPtr) {1923if (E && !isa<CXXNullPtrLiteralExpr>(E)) {1924PrintExpr(E);1925if (IsBold) {1926Unbold();1927OS << " aka ";1928Bold();1929} else {1930OS << " aka ";1931}1932}19331934OS << "nullptr";1935return;1936}19371938if (E) {1939PrintExpr(E);1940return;1941}19421943OS << "(no argument)";1944}19451946/// PrintDecl - Handles printing of Decl arguments, highlighting1947/// argument differences.1948void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,1949bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,1950bool ToNullPtr, Expr *FromExpr, Expr *ToExpr,1951bool FromDefault, bool ToDefault, bool Same) {1952assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&1953"Only one Decl argument may be NULL");19541955if (Same) {1956PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);1957} else if (!PrintTree) {1958OS << (FromDefault ? "(default) " : "");1959Bold();1960PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);1961Unbold();1962} else {1963OS << (FromDefault ? "[(default) " : "[");1964Bold();1965PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);1966Unbold();1967OS << " != " << (ToDefault ? "(default) " : "");1968Bold();1969PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr);1970Unbold();1971OS << ']';1972}1973}19741975/// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and1976/// APSInt to print a mixed difference.1977void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf,1978bool IsNullPtr, Expr *VDExpr, bool DefaultDecl,1979const llvm::APSInt &Val, QualType IntType,1980Expr *IntExpr, bool DefaultInt) {1981if (!PrintTree) {1982OS << (DefaultDecl ? "(default) " : "");1983Bold();1984PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);1985Unbold();1986} else {1987OS << (DefaultDecl ? "[(default) " : "[");1988Bold();1989PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);1990Unbold();1991OS << " != " << (DefaultInt ? "(default) " : "");1992PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);1993OS << ']';1994}1995}19961997/// PrintIntegerAndValueDecl - Uses the print functions for APSInt and1998/// ValueDecl to print a mixed difference.1999void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType,2000Expr *IntExpr, bool DefaultInt, ValueDecl *VD,2001bool NeedAddressOf, bool IsNullPtr,2002Expr *VDExpr, bool DefaultDecl) {2003if (!PrintTree) {2004OS << (DefaultInt ? "(default) " : "");2005PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);2006} else {2007OS << (DefaultInt ? "[(default) " : "[");2008PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/);2009OS << " != " << (DefaultDecl ? "(default) " : "");2010Bold();2011PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);2012Unbold();2013OS << ']';2014}2015}20162017// Prints the appropriate placeholder for elided template arguments.2018void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {2019if (PrintTree) {2020OS << '\n';2021for (unsigned i = 0; i < Indent; ++i)2022OS << " ";2023}2024if (NumElideArgs == 0) return;2025if (NumElideArgs == 1)2026OS << "[...]";2027else2028OS << "[" << NumElideArgs << " * ...]";2029}20302031// Prints and highlights differences in Qualifiers.2032void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {2033// Both types have no qualifiers2034if (FromQual.empty() && ToQual.empty())2035return;20362037// Both types have same qualifiers2038if (FromQual == ToQual) {2039PrintQualifier(FromQual, /*ApplyBold*/false);2040return;2041}20422043// Find common qualifiers and strip them from FromQual and ToQual.2044Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual,2045ToQual);20462047// The qualifiers are printed before the template name.2048// Inline printing:2049// The common qualifiers are printed. Then, qualifiers only in this type2050// are printed and highlighted. Finally, qualifiers only in the other2051// type are printed and highlighted inside parentheses after "missing".2052// Tree printing:2053// Qualifiers are printed next to each other, inside brackets, and2054// separated by "!=". The printing order is:2055// common qualifiers, highlighted from qualifiers, "!=",2056// common qualifiers, highlighted to qualifiers2057if (PrintTree) {2058OS << "[";2059if (CommonQual.empty() && FromQual.empty()) {2060Bold();2061OS << "(no qualifiers) ";2062Unbold();2063} else {2064PrintQualifier(CommonQual, /*ApplyBold*/false);2065PrintQualifier(FromQual, /*ApplyBold*/true);2066}2067OS << "!= ";2068if (CommonQual.empty() && ToQual.empty()) {2069Bold();2070OS << "(no qualifiers)";2071Unbold();2072} else {2073PrintQualifier(CommonQual, /*ApplyBold*/false,2074/*appendSpaceIfNonEmpty*/!ToQual.empty());2075PrintQualifier(ToQual, /*ApplyBold*/true,2076/*appendSpaceIfNonEmpty*/false);2077}2078OS << "] ";2079} else {2080PrintQualifier(CommonQual, /*ApplyBold*/false);2081PrintQualifier(FromQual, /*ApplyBold*/true);2082}2083}20842085void PrintQualifier(Qualifiers Q, bool ApplyBold,2086bool AppendSpaceIfNonEmpty = true) {2087if (Q.empty()) return;2088if (ApplyBold) Bold();2089Q.print(OS, Policy, AppendSpaceIfNonEmpty);2090if (ApplyBold) Unbold();2091}20922093public:20942095TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType,2096QualType ToType, bool PrintTree, bool PrintFromType,2097bool ElideType, bool ShowColor)2098: Context(Context),2099Policy(Context.getLangOpts()),2100ElideType(ElideType),2101PrintTree(PrintTree),2102ShowColor(ShowColor),2103// When printing a single type, the FromType is the one printed.2104FromTemplateType(PrintFromType ? FromType : ToType),2105ToTemplateType(PrintFromType ? ToType : FromType),2106OS(OS),2107IsBold(false) {2108}21092110/// DiffTemplate - Start the template type diffing.2111void DiffTemplate() {2112Qualifiers FromQual = FromTemplateType.getQualifiers(),2113ToQual = ToTemplateType.getQualifiers();21142115const TemplateSpecializationType *FromOrigTST =2116GetTemplateSpecializationType(Context, FromTemplateType);2117const TemplateSpecializationType *ToOrigTST =2118GetTemplateSpecializationType(Context, ToTemplateType);21192120// Only checking templates.2121if (!FromOrigTST || !ToOrigTST)2122return;21232124// Different base templates.2125if (!hasSameTemplate(FromOrigTST, ToOrigTST)) {2126return;2127}21282129FromQual -= QualType(FromOrigTST, 0).getQualifiers();2130ToQual -= QualType(ToOrigTST, 0).getQualifiers();21312132// Same base template, but different arguments.2133Tree.SetTemplateDiff(FromOrigTST->getTemplateName().getAsTemplateDecl(),2134ToOrigTST->getTemplateName().getAsTemplateDecl(),2135FromQual, ToQual, false /*FromDefault*/,2136false /*ToDefault*/);21372138DiffTemplate(FromOrigTST, ToOrigTST);2139}21402141/// Emit - When the two types given are templated types with the same2142/// base template, a string representation of the type difference will be2143/// emitted to the stream and return true. Otherwise, return false.2144bool Emit() {2145Tree.StartTraverse();2146if (Tree.Empty())2147return false;21482149TreeToString();2150assert(!IsBold && "Bold is applied to end of string.");2151return true;2152}2153}; // end class TemplateDiff2154} // end anonymous namespace21552156/// FormatTemplateTypeDiff - A helper static function to start the template2157/// diff and return the properly formatted string. Returns true if the diff2158/// is successful.2159static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,2160QualType ToType, bool PrintTree,2161bool PrintFromType, bool ElideType,2162bool ShowColors, raw_ostream &OS) {2163if (PrintTree)2164PrintFromType = true;2165TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType,2166ElideType, ShowColors);2167TD.DiffTemplate();2168return TD.Emit();2169}217021712172