diff options
| author | 2020-08-03 15:06:44 +0000 | |
|---|---|---|
| committer | 2020-08-03 15:06:44 +0000 | |
| commit | b64793999546ed8adebaeebd9d8345d18db8927d (patch) | |
| tree | 4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp | |
| parent | Add support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff) | |
| download | wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip | |
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp | 2065 |
1 files changed, 0 insertions, 2065 deletions
diff --git a/gnu/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp b/gnu/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp deleted file mode 100644 index dd058555857..00000000000 --- a/gnu/llvm/tools/clang/lib/AST/ASTDiagnostic.cpp +++ /dev/null @@ -1,2065 +0,0 @@ -//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file implements a diagnostic formatting hook for AST elements. -// -//===----------------------------------------------------------------------===// - -#include "clang/AST/ASTDiagnostic.h" -#include "clang/AST/ASTContext.h" -#include "clang/AST/ASTLambda.h" -#include "clang/AST/Attr.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/DeclTemplate.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/TemplateBase.h" -#include "clang/AST/Type.h" -#include "llvm/Support/raw_ostream.h" - -using namespace clang; - -// Returns a desugared version of the QualType, and marks ShouldAKA as true -// whenever we remove significant sugar from the type. -static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { - QualifierCollector QC; - - while (true) { - const Type *Ty = QC.strip(QT); - - // Don't aka just because we saw an elaborated type... - if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) { - QT = ET->desugar(); - continue; - } - // ... or a paren type ... - if (const ParenType *PT = dyn_cast<ParenType>(Ty)) { - QT = PT->desugar(); - continue; - } - // ...or a substituted template type parameter ... - if (const SubstTemplateTypeParmType *ST = - dyn_cast<SubstTemplateTypeParmType>(Ty)) { - QT = ST->desugar(); - continue; - } - // ...or an attributed type... - if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) { - QT = AT->desugar(); - continue; - } - // ...or an adjusted type... - if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) { - QT = AT->desugar(); - continue; - } - // ... or an auto type. - if (const AutoType *AT = dyn_cast<AutoType>(Ty)) { - if (!AT->isSugared()) - break; - QT = AT->desugar(); - continue; - } - - // Desugar FunctionType if return type or any parameter type should be - // desugared. Preserve nullability attribute on desugared types. - if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) { - bool DesugarReturn = false; - QualType SugarRT = FT->getReturnType(); - QualType RT = Desugar(Context, SugarRT, DesugarReturn); - if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) { - RT = Context.getAttributedType( - AttributedType::getNullabilityAttrKind(*nullability), RT, RT); - } - - bool DesugarArgument = false; - SmallVector<QualType, 4> Args; - const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT); - if (FPT) { - for (QualType SugarPT : FPT->param_types()) { - QualType PT = Desugar(Context, SugarPT, DesugarArgument); - if (auto nullability = - AttributedType::stripOuterNullability(SugarPT)) { - PT = Context.getAttributedType( - AttributedType::getNullabilityAttrKind(*nullability), PT, PT); - } - Args.push_back(PT); - } - } - - if (DesugarReturn || DesugarArgument) { - ShouldAKA = true; - QT = FPT ? Context.getFunctionType(RT, Args, FPT->getExtProtoInfo()) - : Context.getFunctionNoProtoType(RT, FT->getExtInfo()); - break; - } - } - - // Desugar template specializations if any template argument should be - // desugared. - if (const TemplateSpecializationType *TST = - dyn_cast<TemplateSpecializationType>(Ty)) { - if (!TST->isTypeAlias()) { - bool DesugarArgument = false; - SmallVector<TemplateArgument, 4> Args; - for (unsigned I = 0, N = TST->getNumArgs(); I != N; ++I) { - const TemplateArgument &Arg = TST->getArg(I); - if (Arg.getKind() == TemplateArgument::Type) - Args.push_back(Desugar(Context, Arg.getAsType(), DesugarArgument)); - else - Args.push_back(Arg); - } - - if (DesugarArgument) { - ShouldAKA = true; - QT = Context.getTemplateSpecializationType( - TST->getTemplateName(), Args, QT); - } - break; - } - } - - // Don't desugar magic Objective-C types. - if (QualType(Ty,0) == Context.getObjCIdType() || - QualType(Ty,0) == Context.getObjCClassType() || - QualType(Ty,0) == Context.getObjCSelType() || - QualType(Ty,0) == Context.getObjCProtoType()) - break; - - // Don't desugar va_list. - if (QualType(Ty, 0) == Context.getBuiltinVaListType() || - QualType(Ty, 0) == Context.getBuiltinMSVaListType()) - break; - - // Otherwise, do a single-step desugar. - QualType Underlying; - bool IsSugar = false; - switch (Ty->getTypeClass()) { -#define ABSTRACT_TYPE(Class, Base) -#define TYPE(Class, Base) \ -case Type::Class: { \ -const Class##Type *CTy = cast<Class##Type>(Ty); \ -if (CTy->isSugared()) { \ -IsSugar = true; \ -Underlying = CTy->desugar(); \ -} \ -break; \ -} -#include "clang/AST/TypeNodes.def" - } - - // If it wasn't sugared, we're done. - if (!IsSugar) - break; - - // If the desugared type is a vector type, we don't want to expand - // it, it will turn into an attribute mess. People want their "vec4". - if (isa<VectorType>(Underlying)) - break; - - // Don't desugar through the primary typedef of an anonymous type. - if (const TagType *UTT = Underlying->getAs<TagType>()) - if (const TypedefType *QTT = dyn_cast<TypedefType>(QT)) - if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl()) - break; - - // Record that we actually looked through an opaque type here. - ShouldAKA = true; - QT = Underlying; - } - - // If we have a pointer-like type, desugar the pointee as well. - // FIXME: Handle other pointer-like types. - if (const PointerType *Ty = QT->getAs<PointerType>()) { - QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(), - ShouldAKA)); - } else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) { - QT = Context.getObjCObjectPointerType(Desugar(Context, Ty->getPointeeType(), - ShouldAKA)); - } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) { - QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(), - ShouldAKA)); - } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) { - QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(), - ShouldAKA)); - } else if (const auto *Ty = QT->getAs<ObjCObjectType>()) { - if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) { - QualType BaseType = Desugar(Context, Ty->getBaseType(), ShouldAKA); - QT = Context.getObjCObjectType(BaseType, Ty->getTypeArgsAsWritten(), - llvm::makeArrayRef(Ty->qual_begin(), - Ty->getNumProtocols()), - Ty->isKindOfTypeAsWritten()); - } - } - - return QC.apply(Context, QT); -} - -/// Convert the given type to a string suitable for printing as part of -/// a diagnostic. -/// -/// There are four main criteria when determining whether we should have an -/// a.k.a. clause when pretty-printing a type: -/// -/// 1) Some types provide very minimal sugar that doesn't impede the -/// user's understanding --- for example, elaborated type -/// specifiers. If this is all the sugar we see, we don't want an -/// a.k.a. clause. -/// 2) Some types are technically sugared but are much more familiar -/// when seen in their sugared form --- for example, va_list, -/// vector types, and the magic Objective C types. We don't -/// want to desugar these, even if we do produce an a.k.a. clause. -/// 3) Some types may have already been desugared previously in this diagnostic. -/// if this is the case, doing another "aka" would just be clutter. -/// 4) Two different types within the same diagnostic have the same output -/// string. In this case, force an a.k.a with the desugared type when -/// doing so will provide additional information. -/// -/// \param Context the context in which the type was allocated -/// \param Ty the type to print -/// \param QualTypeVals pointer values to QualTypes which are used in the -/// diagnostic message -static std::string -ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, - ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, - ArrayRef<intptr_t> QualTypeVals) { - // FIXME: Playing with std::string is really slow. - bool ForceAKA = false; - QualType CanTy = Ty.getCanonicalType(); - std::string S = Ty.getAsString(Context.getPrintingPolicy()); - std::string CanS = CanTy.getAsString(Context.getPrintingPolicy()); - - for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) { - QualType CompareTy = - QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I])); - if (CompareTy.isNull()) - continue; - if (CompareTy == Ty) - continue; // Same types - QualType CompareCanTy = CompareTy.getCanonicalType(); - if (CompareCanTy == CanTy) - continue; // Same canonical types - std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy()); - bool ShouldAKA = false; - QualType CompareDesugar = Desugar(Context, CompareTy, ShouldAKA); - std::string CompareDesugarStr = - CompareDesugar.getAsString(Context.getPrintingPolicy()); - if (CompareS != S && CompareDesugarStr != S) - continue; // The type string is different than the comparison string - // and the desugared comparison string. - std::string CompareCanS = - CompareCanTy.getAsString(Context.getPrintingPolicy()); - - if (CompareCanS == CanS) - continue; // No new info from canonical type - - ForceAKA = true; - break; - } - - // Check to see if we already desugared this type in this - // diagnostic. If so, don't do it again. - bool Repeated = false; - for (unsigned i = 0, e = PrevArgs.size(); i != e; ++i) { - // TODO: Handle ak_declcontext case. - if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { - void *Ptr = (void*)PrevArgs[i].second; - QualType PrevTy(QualType::getFromOpaquePtr(Ptr)); - if (PrevTy == Ty) { - Repeated = true; - break; - } - } - } - - // Consider producing an a.k.a. clause if removing all the direct - // sugar gives us something "significantly different". - if (!Repeated) { - bool ShouldAKA = false; - QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA); - if (ShouldAKA || ForceAKA) { - if (DesugaredTy == Ty) { - DesugaredTy = Ty.getCanonicalType(); - } - std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy()); - if (akaStr != S) { - S = "'" + S + "' (aka '" + akaStr + "')"; - return S; - } - } - - // Give some additional info on vector types. These are either not desugared - // or displaying complex __attribute__ expressions so add details of the - // type and element count. - if (Ty->isVectorType()) { - const VectorType *VTy = Ty->getAs<VectorType>(); - std::string DecoratedString; - llvm::raw_string_ostream OS(DecoratedString); - const char *Values = VTy->getNumElements() > 1 ? "values" : "value"; - OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '" - << VTy->getElementType().getAsString(Context.getPrintingPolicy()) - << "' " << Values << ")"; - return OS.str(); - } - } - - S = "'" + S + "'"; - return S; -} - -static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, - QualType ToType, bool PrintTree, - bool PrintFromType, bool ElideType, - bool ShowColors, raw_ostream &OS); - -void clang::FormatASTNodeDiagnosticArgument( - DiagnosticsEngine::ArgumentKind Kind, - intptr_t Val, - StringRef Modifier, - StringRef Argument, - ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, - SmallVectorImpl<char> &Output, - void *Cookie, - ArrayRef<intptr_t> QualTypeVals) { - ASTContext &Context = *static_cast<ASTContext*>(Cookie); - - size_t OldEnd = Output.size(); - llvm::raw_svector_ostream OS(Output); - bool NeedQuotes = true; - - switch (Kind) { - default: llvm_unreachable("unknown ArgumentKind"); - case DiagnosticsEngine::ak_qual: { - assert(Modifier.empty() && Argument.empty() && - "Invalid modifier for Qualfiers argument"); - - Qualifiers Q(Qualifiers::fromOpaqueValue(Val)); - auto S = Q.getAsString(); - if (S.empty()) { - OS << "unqualified"; - NeedQuotes = false; - } else { - OS << Q.getAsString(); - } - break; - } - case DiagnosticsEngine::ak_qualtype_pair: { - TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val); - QualType FromType = - QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.FromType)); - QualType ToType = - QualType::getFromOpaquePtr(reinterpret_cast<void*>(TDT.ToType)); - - if (FormatTemplateTypeDiff(Context, FromType, ToType, TDT.PrintTree, - TDT.PrintFromType, TDT.ElideType, - TDT.ShowColors, OS)) { - NeedQuotes = !TDT.PrintTree; - TDT.TemplateDiffUsed = true; - break; - } - - // Don't fall-back during tree printing. The caller will handle - // this case. - if (TDT.PrintTree) - return; - - // Attempting to do a template diff on non-templates. Set the variables - // and continue with regular type printing of the appropriate type. - Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType; - Modifier = StringRef(); - Argument = StringRef(); - // Fall through - LLVM_FALLTHROUGH; - } - case DiagnosticsEngine::ak_qualtype: { - assert(Modifier.empty() && Argument.empty() && - "Invalid modifier for QualType argument"); - - QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); - OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals); - NeedQuotes = false; - break; - } - case DiagnosticsEngine::ak_declarationname: { - if (Modifier == "objcclass" && Argument.empty()) - OS << '+'; - else if (Modifier == "objcinstance" && Argument.empty()) - OS << '-'; - else - assert(Modifier.empty() && Argument.empty() && - "Invalid modifier for DeclarationName argument"); - - OS << DeclarationName::getFromOpaqueInteger(Val); - break; - } - case DiagnosticsEngine::ak_nameddecl: { - bool Qualified; - if (Modifier == "q" && Argument.empty()) - Qualified = true; - else { - assert(Modifier.empty() && Argument.empty() && - "Invalid modifier for NamedDecl* argument"); - Qualified = false; - } - const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val); - ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified); - break; - } - case DiagnosticsEngine::ak_nestednamespec: { - NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val); - NNS->print(OS, Context.getPrintingPolicy()); - NeedQuotes = false; - break; - } - case DiagnosticsEngine::ak_declcontext: { - DeclContext *DC = reinterpret_cast<DeclContext *> (Val); - assert(DC && "Should never have a null declaration context"); - NeedQuotes = false; - - // FIXME: Get the strings for DeclContext from some localized place - if (DC->isTranslationUnit()) { - if (Context.getLangOpts().CPlusPlus) - OS << "the global namespace"; - else - OS << "the global scope"; - } else if (DC->isClosure()) { - OS << "block literal"; - } else if (isLambdaCallOperator(DC)) { - OS << "lambda expression"; - } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { - OS << ConvertTypeToDiagnosticString(Context, - Context.getTypeDeclType(Type), - PrevArgs, QualTypeVals); - } else { - assert(isa<NamedDecl>(DC) && "Expected a NamedDecl"); - NamedDecl *ND = cast<NamedDecl>(DC); - if (isa<NamespaceDecl>(ND)) - OS << "namespace "; - else if (isa<ObjCMethodDecl>(ND)) - OS << "method "; - else if (isa<FunctionDecl>(ND)) - OS << "function "; - - OS << '\''; - ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); - OS << '\''; - } - break; - } - case DiagnosticsEngine::ak_attr: { - const Attr *At = reinterpret_cast<Attr *>(Val); - assert(At && "Received null Attr object!"); - OS << '\'' << At->getSpelling() << '\''; - NeedQuotes = false; - break; - } - } - - if (NeedQuotes) { - Output.insert(Output.begin()+OldEnd, '\''); - Output.push_back('\''); - } -} - -/// TemplateDiff - A class that constructs a pretty string for a pair of -/// QualTypes. For the pair of types, a diff tree will be created containing -/// all the information about the templates and template arguments. Afterwards, -/// the tree is transformed to a string according to the options passed in. -namespace { -class TemplateDiff { - /// Context - The ASTContext which is used for comparing template arguments. - ASTContext &Context; - - /// Policy - Used during expression printing. - PrintingPolicy Policy; - - /// ElideType - Option to elide identical types. - bool ElideType; - - /// PrintTree - Format output string as a tree. - bool PrintTree; - - /// ShowColor - Diagnostics support color, so bolding will be used. - bool ShowColor; - - /// FromTemplateType - When single type printing is selected, this is the - /// type to be be printed. When tree printing is selected, this type will - /// show up first in the tree. - QualType FromTemplateType; - - /// ToTemplateType - The type that FromType is compared to. Only in tree - /// printing will this type be outputed. - QualType ToTemplateType; - - /// OS - The stream used to construct the output strings. - raw_ostream &OS; - - /// IsBold - Keeps track of the bold formatting for the output string. - bool IsBold; - - /// DiffTree - A tree representation the differences between two types. - class DiffTree { - public: - /// DiffKind - The difference in a DiffNode. Fields of - /// TemplateArgumentInfo needed by each difference can be found in the - /// Set* and Get* functions. - enum DiffKind { - /// Incomplete or invalid node. - Invalid, - /// Another level of templates - Template, - /// Type difference, all type differences except those falling under - /// the Template difference. - Type, - /// Expression difference, this is only when both arguments are - /// expressions. If one argument is an expression and the other is - /// Integer or Declaration, then use that diff type instead. - Expression, - /// Template argument difference - TemplateTemplate, - /// Integer difference - Integer, - /// Declaration difference, nullptr arguments are included here - Declaration, - /// One argument being integer and the other being declaration - FromIntegerAndToDeclaration, - FromDeclarationAndToInteger - }; - - private: - /// TemplateArgumentInfo - All the information needed to pretty print - /// a template argument. See the Set* and Get* functions to see which - /// fields are used for each DiffKind. - struct TemplateArgumentInfo { - QualType ArgType; - Qualifiers Qual; - llvm::APSInt Val; - bool IsValidInt = false; - Expr *ArgExpr = nullptr; - TemplateDecl *TD = nullptr; - ValueDecl *VD = nullptr; - bool NeedAddressOf = false; - bool IsNullPtr = false; - bool IsDefault = false; - }; - - /// DiffNode - The root node stores the original type. Each child node - /// stores template arguments of their parents. For templated types, the - /// template decl is also stored. - struct DiffNode { - DiffKind Kind = Invalid; - - /// NextNode - The index of the next sibling node or 0. - unsigned NextNode = 0; - - /// ChildNode - The index of the first child node or 0. - unsigned ChildNode = 0; - - /// ParentNode - The index of the parent node. - unsigned ParentNode = 0; - - TemplateArgumentInfo FromArgInfo, ToArgInfo; - - /// Same - Whether the two arguments evaluate to the same value. - bool Same = false; - - DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {} - }; - - /// FlatTree - A flattened tree used to store the DiffNodes. - SmallVector<DiffNode, 16> FlatTree; - - /// CurrentNode - The index of the current node being used. - unsigned CurrentNode; - - /// NextFreeNode - The index of the next unused node. Used when creating - /// child nodes. - unsigned NextFreeNode; - - /// ReadNode - The index of the current node being read. - unsigned ReadNode; - - public: - DiffTree() : - CurrentNode(0), NextFreeNode(1) { - FlatTree.push_back(DiffNode()); - } - - // Node writing functions, one for each valid DiffKind element. - void SetTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD, - Qualifiers FromQual, Qualifiers ToQual, - bool FromDefault, bool ToDefault) { - assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); - FlatTree[CurrentNode].Kind = Template; - FlatTree[CurrentNode].FromArgInfo.TD = FromTD; - FlatTree[CurrentNode].ToArgInfo.TD = ToTD; - FlatTree[CurrentNode].FromArgInfo.Qual = FromQual; - FlatTree[CurrentNode].ToArgInfo.Qual = ToQual; - SetDefault(FromDefault, ToDefault); - } - - void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault, - bool ToDefault) { - assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); - FlatTree[CurrentNode].Kind = Type; - FlatTree[CurrentNode].FromArgInfo.ArgType = FromType; - FlatTree[CurrentNode].ToArgInfo.ArgType = ToType; - SetDefault(FromDefault, ToDefault); - } - - void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault, - bool ToDefault) { - assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); - FlatTree[CurrentNode].Kind = Expression; - FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; - FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; - SetDefault(FromDefault, ToDefault); - } - - void SetTemplateTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD, - bool FromDefault, bool ToDefault) { - assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); - FlatTree[CurrentNode].Kind = TemplateTemplate; - FlatTree[CurrentNode].FromArgInfo.TD = FromTD; - FlatTree[CurrentNode].ToArgInfo.TD = ToTD; - SetDefault(FromDefault, ToDefault); - } - - void SetIntegerDiff(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt, - bool IsValidFromInt, bool IsValidToInt, - QualType FromIntType, QualType ToIntType, - Expr *FromExpr, Expr *ToExpr, bool FromDefault, - bool ToDefault) { - assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); - FlatTree[CurrentNode].Kind = Integer; - FlatTree[CurrentNode].FromArgInfo.Val = FromInt; - FlatTree[CurrentNode].ToArgInfo.Val = ToInt; - FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt; - FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt; - FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType; - FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType; - FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; - FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; - SetDefault(FromDefault, ToDefault); - } - - void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, - bool FromAddressOf, bool ToAddressOf, - bool FromNullPtr, bool ToNullPtr, Expr *FromExpr, - Expr *ToExpr, bool FromDefault, bool ToDefault) { - assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); - FlatTree[CurrentNode].Kind = Declaration; - FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl; - FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl; - FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf; - FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf; - FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr; - FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr; - FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; - FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; - SetDefault(FromDefault, ToDefault); - } - - void SetFromDeclarationAndToIntegerDiff( - ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr, - Expr *FromExpr, const llvm::APSInt &ToInt, bool IsValidToInt, - QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) { - assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); - FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger; - FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl; - FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf; - FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr; - FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; - FlatTree[CurrentNode].ToArgInfo.Val = ToInt; - FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt; - FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType; - FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; - SetDefault(FromDefault, ToDefault); - } - - void SetFromIntegerAndToDeclarationDiff( - const llvm::APSInt &FromInt, bool IsValidFromInt, QualType FromIntType, - Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf, - bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) { - assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty."); - FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration; - FlatTree[CurrentNode].FromArgInfo.Val = FromInt; - FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt; - FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType; - FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr; - FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl; - FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf; - FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr; - FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr; - SetDefault(FromDefault, ToDefault); - } - - /// SetDefault - Sets FromDefault and ToDefault flags of the current node. - void SetDefault(bool FromDefault, bool ToDefault) { - assert((!FromDefault || !ToDefault) && "Both arguments cannot be default."); - FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault; - FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault; - } - - /// SetSame - Sets the same flag of the current node. - void SetSame(bool Same) { - FlatTree[CurrentNode].Same = Same; - } - - /// SetKind - Sets the current node's type. - void SetKind(DiffKind Kind) { - FlatTree[CurrentNode].Kind = Kind; - } - - /// Up - Changes the node to the parent of the current node. - void Up() { - assert(FlatTree[CurrentNode].Kind != Invalid && - "Cannot exit node before setting node information."); - CurrentNode = FlatTree[CurrentNode].ParentNode; - } - - /// AddNode - Adds a child node to the current node, then sets that node - /// node as the current node. - void AddNode() { - assert(FlatTree[CurrentNode].Kind == Template && - "Only Template nodes can have children nodes."); - FlatTree.push_back(DiffNode(CurrentNode)); - DiffNode &Node = FlatTree[CurrentNode]; - if (Node.ChildNode == 0) { - // If a child node doesn't exist, add one. - Node.ChildNode = NextFreeNode; - } else { - // If a child node exists, find the last child node and add a - // next node to it. - unsigned i; - for (i = Node.ChildNode; FlatTree[i].NextNode != 0; - i = FlatTree[i].NextNode) { - } - FlatTree[i].NextNode = NextFreeNode; - } - CurrentNode = NextFreeNode; - ++NextFreeNode; - } - - // Node reading functions. - /// StartTraverse - Prepares the tree for recursive traversal. - void StartTraverse() { - ReadNode = 0; - CurrentNode = NextFreeNode; - NextFreeNode = 0; - } - - /// Parent - Move the current read node to its parent. - void Parent() { - ReadNode = FlatTree[ReadNode].ParentNode; - } - - void GetTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD, - Qualifiers &FromQual, Qualifiers &ToQual) { - assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind."); - FromTD = FlatTree[ReadNode].FromArgInfo.TD; - ToTD = FlatTree[ReadNode].ToArgInfo.TD; - FromQual = FlatTree[ReadNode].FromArgInfo.Qual; - ToQual = FlatTree[ReadNode].ToArgInfo.Qual; - } - - void GetTypeDiff(QualType &FromType, QualType &ToType) { - assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind"); - FromType = FlatTree[ReadNode].FromArgInfo.ArgType; - ToType = FlatTree[ReadNode].ToArgInfo.ArgType; - } - - void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) { - assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind"); - FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; - ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; - } - - void GetTemplateTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD) { - assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind."); - FromTD = FlatTree[ReadNode].FromArgInfo.TD; - ToTD = FlatTree[ReadNode].ToArgInfo.TD; - } - - void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt, - bool &IsValidFromInt, bool &IsValidToInt, - QualType &FromIntType, QualType &ToIntType, - Expr *&FromExpr, Expr *&ToExpr) { - assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind."); - FromInt = FlatTree[ReadNode].FromArgInfo.Val; - ToInt = FlatTree[ReadNode].ToArgInfo.Val; - IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt; - IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt; - FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType; - ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType; - FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; - ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; - } - - void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl, - bool &FromAddressOf, bool &ToAddressOf, - bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr, - Expr *&ToExpr) { - assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind."); - FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD; - ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD; - FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf; - ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf; - FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr; - ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr; - FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; - ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; - } - - void GetFromDeclarationAndToIntegerDiff( - ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr, - Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt, - QualType &ToIntType, Expr *&ToExpr) { - assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger && - "Unexpected kind."); - FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD; - FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf; - FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr; - FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; - ToInt = FlatTree[ReadNode].ToArgInfo.Val; - IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt; - ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType; - ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; - } - - void GetFromIntegerAndToDeclarationDiff( - llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType, - Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf, - bool &ToNullPtr, Expr *&ToExpr) { - assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration && - "Unexpected kind."); - FromInt = FlatTree[ReadNode].FromArgInfo.Val; - IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt; - FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType; - FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr; - ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD; - ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf; - ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr; - ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr; - } - - /// FromDefault - Return true if the from argument is the default. - bool FromDefault() { - return FlatTree[ReadNode].FromArgInfo.IsDefault; - } - - /// ToDefault - Return true if the to argument is the default. - bool ToDefault() { - return FlatTree[ReadNode].ToArgInfo.IsDefault; - } - - /// NodeIsSame - Returns true the arguments are the same. - bool NodeIsSame() { - return FlatTree[ReadNode].Same; - } - - /// HasChildrend - Returns true if the node has children. - bool HasChildren() { - return FlatTree[ReadNode].ChildNode != 0; - } - - /// MoveToChild - Moves from the current node to its child. - void MoveToChild() { - ReadNode = FlatTree[ReadNode].ChildNode; - } - - /// AdvanceSibling - If there is a next sibling, advance to it and return - /// true. Otherwise, return false. - bool AdvanceSibling() { - if (FlatTree[ReadNode].NextNode == 0) - return false; - - ReadNode = FlatTree[ReadNode].NextNode; - return true; - } - - /// HasNextSibling - Return true if the node has a next sibling. - bool HasNextSibling() { - return FlatTree[ReadNode].NextNode != 0; - } - - /// Empty - Returns true if the tree has no information. - bool Empty() { - return GetKind() == Invalid; - } - - /// GetKind - Returns the current node's type. - DiffKind GetKind() { - return FlatTree[ReadNode].Kind; - } - }; - - DiffTree Tree; - - /// TSTiterator - a pair of iterators that walks the - /// TemplateSpecializationType and the desugared TemplateSpecializationType. - /// The deseguared TemplateArgument should provide the canonical argument - /// for comparisons. - class TSTiterator { - typedef const TemplateArgument& reference; - typedef const TemplateArgument* pointer; - - /// InternalIterator - an iterator that is used to enter a - /// TemplateSpecializationType and read TemplateArguments inside template - /// parameter packs in order with the rest of the TemplateArguments. - struct InternalIterator { - /// TST - the template specialization whose arguments this iterator - /// traverse over. - const TemplateSpecializationType *TST; - - /// Index - the index of the template argument in TST. - unsigned Index; - - /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA - /// points to a TemplateArgument within a parameter pack. - TemplateArgument::pack_iterator CurrentTA; - - /// EndTA - the end iterator of a parameter pack - TemplateArgument::pack_iterator EndTA; - - /// InternalIterator - Constructs an iterator and sets it to the first - /// template argument. - InternalIterator(const TemplateSpecializationType *TST) - : TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) { - if (!TST) return; - - if (isEnd()) return; - - // Set to first template argument. If not a parameter pack, done. - TemplateArgument TA = TST->getArg(0); - if (TA.getKind() != TemplateArgument::Pack) return; - - // Start looking into the parameter pack. - CurrentTA = TA.pack_begin(); - EndTA = TA.pack_end(); - - // Found a valid template argument. - if (CurrentTA != EndTA) return; - - // Parameter pack is empty, use the increment to get to a valid - // template argument. - ++(*this); - } - - /// Return true if the iterator is non-singular. - bool isValid() const { return TST; } - - /// isEnd - Returns true if the iterator is one past the end. - bool isEnd() const { - assert(TST && "InternalIterator is invalid with a null TST."); - return Index >= TST->getNumArgs(); - } - - /// &operator++ - Increment the iterator to the next template argument. - InternalIterator &operator++() { - assert(TST && "InternalIterator is invalid with a null TST."); - if (isEnd()) { - return *this; - } - - // If in a parameter pack, advance in the parameter pack. - if (CurrentTA != EndTA) { - ++CurrentTA; - if (CurrentTA != EndTA) - return *this; - } - - // Loop until a template argument is found, or the end is reached. - while (true) { - // Advance to the next template argument. Break if reached the end. - if (++Index == TST->getNumArgs()) - break; - - // If the TemplateArgument is not a parameter pack, done. - TemplateArgument TA = TST->getArg(Index); - if (TA.getKind() != TemplateArgument::Pack) - break; - - // Handle parameter packs. - CurrentTA = TA.pack_begin(); - EndTA = TA.pack_end(); - - // If the parameter pack is empty, try to advance again. - if (CurrentTA != EndTA) - break; - } - return *this; - } - - /// operator* - Returns the appropriate TemplateArgument. - reference operator*() const { - assert(TST && "InternalIterator is invalid with a null TST."); - assert(!isEnd() && "Index exceeds number of arguments."); - if (CurrentTA == EndTA) - return TST->getArg(Index); - else - return *CurrentTA; - } - - /// operator-> - Allow access to the underlying TemplateArgument. - pointer operator->() const { - assert(TST && "InternalIterator is invalid with a null TST."); - return &operator*(); - } - }; - - InternalIterator SugaredIterator; - InternalIterator DesugaredIterator; - - public: - TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) - : SugaredIterator(TST), - DesugaredIterator( - (TST->isSugared() && !TST->isTypeAlias()) - ? GetTemplateSpecializationType(Context, TST->desugar()) - : nullptr) {} - - /// &operator++ - Increment the iterator to the next template argument. - TSTiterator &operator++() { - ++SugaredIterator; - if (DesugaredIterator.isValid()) - ++DesugaredIterator; - return *this; - } - - /// operator* - Returns the appropriate TemplateArgument. - reference operator*() const { - return *SugaredIterator; - } - - /// operator-> - Allow access to the underlying TemplateArgument. - pointer operator->() const { - return &operator*(); - } - - /// isEnd - Returns true if no more TemplateArguments are available. - bool isEnd() const { - return SugaredIterator.isEnd(); - } - - /// hasDesugaredTA - Returns true if there is another TemplateArgument - /// available. - bool hasDesugaredTA() const { - return DesugaredIterator.isValid() && !DesugaredIterator.isEnd(); - } - - /// getDesugaredTA - Returns the desugared TemplateArgument. - reference getDesugaredTA() const { - assert(DesugaredIterator.isValid() && - "Desugared TemplateArgument should not be used."); - return *DesugaredIterator; - } - }; - - // These functions build up the template diff tree, including functions to - // retrieve and compare template arguments. - - static const TemplateSpecializationType *GetTemplateSpecializationType( - ASTContext &Context, QualType Ty) { - if (const TemplateSpecializationType *TST = - Ty->getAs<TemplateSpecializationType>()) - return TST; - - const RecordType *RT = Ty->getAs<RecordType>(); - - if (!RT) - return nullptr; - - const ClassTemplateSpecializationDecl *CTSD = - dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); - - if (!CTSD) - return nullptr; - - Ty = Context.getTemplateSpecializationType( - TemplateName(CTSD->getSpecializedTemplate()), - CTSD->getTemplateArgs().asArray(), - Ty.getLocalUnqualifiedType().getCanonicalType()); - - return Ty->getAs<TemplateSpecializationType>(); - } - - /// Returns true if the DiffType is Type and false for Template. - static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType, - QualType ToType, - const TemplateSpecializationType *&FromArgTST, - const TemplateSpecializationType *&ToArgTST) { - if (FromType.isNull() || ToType.isNull()) - return true; - - if (Context.hasSameType(FromType, ToType)) - return true; - - FromArgTST = GetTemplateSpecializationType(Context, FromType); - ToArgTST = GetTemplateSpecializationType(Context, ToType); - - if (!FromArgTST || !ToArgTST) - return true; - - if (!hasSameTemplate(FromArgTST, ToArgTST)) - return true; - - return false; - } - - /// DiffTypes - Fills a DiffNode with information about a type difference. - void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) { - QualType FromType = GetType(FromIter); - QualType ToType = GetType(ToIter); - - bool FromDefault = FromIter.isEnd() && !FromType.isNull(); - bool ToDefault = ToIter.isEnd() && !ToType.isNull(); - - const TemplateSpecializationType *FromArgTST = nullptr; - const TemplateSpecializationType *ToArgTST = nullptr; - if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) { - Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault); - Tree.SetSame(!FromType.isNull() && !ToType.isNull() && - Context.hasSameType(FromType, ToType)); - } else { - assert(FromArgTST && ToArgTST && - "Both template specializations need to be valid."); - Qualifiers FromQual = FromType.getQualifiers(), - ToQual = ToType.getQualifiers(); - FromQual -= QualType(FromArgTST, 0).getQualifiers(); - ToQual -= QualType(ToArgTST, 0).getQualifiers(); - Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(), - ToArgTST->getTemplateName().getAsTemplateDecl(), - FromQual, ToQual, FromDefault, ToDefault); - DiffTemplate(FromArgTST, ToArgTST); - } - } - - /// DiffTemplateTemplates - Fills a DiffNode with information about a - /// template template difference. - void DiffTemplateTemplates(const TSTiterator &FromIter, - const TSTiterator &ToIter) { - TemplateDecl *FromDecl = GetTemplateDecl(FromIter); - TemplateDecl *ToDecl = GetTemplateDecl(ToIter); - Tree.SetTemplateTemplateDiff(FromDecl, ToDecl, FromIter.isEnd() && FromDecl, - ToIter.isEnd() && ToDecl); - Tree.SetSame(FromDecl && ToDecl && - FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); - } - - /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes - static void InitializeNonTypeDiffVariables(ASTContext &Context, - const TSTiterator &Iter, - NonTypeTemplateParmDecl *Default, - llvm::APSInt &Value, bool &HasInt, - QualType &IntType, bool &IsNullPtr, - Expr *&E, ValueDecl *&VD, - bool &NeedAddressOf) { - if (!Iter.isEnd()) { - switch (Iter->getKind()) { - default: - llvm_unreachable("unknown ArgumentKind"); - case TemplateArgument::Integral: - Value = Iter->getAsIntegral(); - HasInt = true; - IntType = Iter->getIntegralType(); - return; - case TemplateArgument::Declaration: { - VD = Iter->getAsDecl(); - QualType ArgType = Iter->getParamTypeForDecl(); - QualType VDType = VD->getType(); - if (ArgType->isPointerType() && - Context.hasSameType(ArgType->getPointeeType(), VDType)) - NeedAddressOf = true; - return; - } - case TemplateArgument::NullPtr: - IsNullPtr = true; - return; - case TemplateArgument::Expression: - E = Iter->getAsExpr(); - } - } else if (!Default->isParameterPack()) { - E = Default->getDefaultArgument(); - } - - if (!Iter.hasDesugaredTA()) return; - - const TemplateArgument& TA = Iter.getDesugaredTA(); - switch (TA.getKind()) { - default: - llvm_unreachable("unknown ArgumentKind"); - case TemplateArgument::Integral: - Value = TA.getAsIntegral(); - HasInt = true; - IntType = TA.getIntegralType(); - return; - case TemplateArgument::Declaration: { - VD = TA.getAsDecl(); - QualType ArgType = TA.getParamTypeForDecl(); - QualType VDType = VD->getType(); - if (ArgType->isPointerType() && - Context.hasSameType(ArgType->getPointeeType(), VDType)) - NeedAddressOf = true; - return; - } - case TemplateArgument::NullPtr: - IsNullPtr = true; - return; - case TemplateArgument::Expression: - // TODO: Sometimes, the desugared template argument Expr differs from - // the sugared template argument Expr. It may be useful in the future - // but for now, it is just discarded. - if (!E) - E = TA.getAsExpr(); - return; - } - } - - /// DiffNonTypes - Handles any template parameters not handled by DiffTypes - /// of DiffTemplatesTemplates, such as integer and declaration parameters. - void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter, - NonTypeTemplateParmDecl *FromDefaultNonTypeDecl, - NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) { - Expr *FromExpr = nullptr, *ToExpr = nullptr; - llvm::APSInt FromInt, ToInt; - QualType FromIntType, ToIntType; - ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr; - bool HasFromInt = false, HasToInt = false, FromNullPtr = false, - ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false; - InitializeNonTypeDiffVariables( - Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt, - FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf); - InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt, - HasToInt, ToIntType, ToNullPtr, ToExpr, - ToValueDecl, NeedToAddressOf); - - bool FromDefault = FromIter.isEnd() && - (FromExpr || FromValueDecl || HasFromInt || FromNullPtr); - bool ToDefault = ToIter.isEnd() && - (ToExpr || ToValueDecl || HasToInt || ToNullPtr); - - bool FromDeclaration = FromValueDecl || FromNullPtr; - bool ToDeclaration = ToValueDecl || ToNullPtr; - - if (FromDeclaration && HasToInt) { - Tree.SetFromDeclarationAndToIntegerDiff( - FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt, - HasToInt, ToIntType, ToExpr, FromDefault, ToDefault); - Tree.SetSame(false); - return; - - } - - if (HasFromInt && ToDeclaration) { - Tree.SetFromIntegerAndToDeclarationDiff( - FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl, - NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault); - Tree.SetSame(false); - return; - } - - if (HasFromInt || HasToInt) { - Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType, - ToIntType, FromExpr, ToExpr, FromDefault, ToDefault); - if (HasFromInt && HasToInt) { - Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) && - FromInt == ToInt); - } - return; - } - - if (FromDeclaration || ToDeclaration) { - Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf, - NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr, - ToExpr, FromDefault, ToDefault); - bool BothNull = FromNullPtr && ToNullPtr; - bool SameValueDecl = - FromValueDecl && ToValueDecl && - NeedFromAddressOf == NeedToAddressOf && - FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl(); - Tree.SetSame(BothNull || SameValueDecl); - return; - } - - assert((FromExpr || ToExpr) && "Both template arguments cannot be empty."); - Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault); - Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr)); - } - - /// DiffTemplate - recursively visits template arguments and stores the - /// argument info into a tree. - void DiffTemplate(const TemplateSpecializationType *FromTST, - const TemplateSpecializationType *ToTST) { - // Begin descent into diffing template tree. - TemplateParameterList *ParamsFrom = - FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); - TemplateParameterList *ParamsTo = - ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters(); - unsigned TotalArgs = 0; - for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST); - !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) { - Tree.AddNode(); - - // Get the parameter at index TotalArgs. If index is larger - // than the total number of parameters, then there is an - // argument pack, so re-use the last parameter. - unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1); - unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1); - NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex); - NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex); - - assert(FromParamND->getKind() == ToParamND->getKind() && - "Parameter Decl are not the same kind."); - - if (isa<TemplateTypeParmDecl>(FromParamND)) { - DiffTypes(FromIter, ToIter); - } else if (isa<TemplateTemplateParmDecl>(FromParamND)) { - DiffTemplateTemplates(FromIter, ToIter); - } else if (isa<NonTypeTemplateParmDecl>(FromParamND)) { - NonTypeTemplateParmDecl *FromDefaultNonTypeDecl = - cast<NonTypeTemplateParmDecl>(FromParamND); - NonTypeTemplateParmDecl *ToDefaultNonTypeDecl = - cast<NonTypeTemplateParmDecl>(ToParamND); - DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl, - ToDefaultNonTypeDecl); - } else { - llvm_unreachable("Unexpected Decl type."); - } - - ++FromIter; - ++ToIter; - Tree.Up(); - } - } - - /// makeTemplateList - Dump every template alias into the vector. - static void makeTemplateList( - SmallVectorImpl<const TemplateSpecializationType *> &TemplateList, - const TemplateSpecializationType *TST) { - while (TST) { - TemplateList.push_back(TST); - if (!TST->isTypeAlias()) - return; - TST = TST->getAliasedType()->getAs<TemplateSpecializationType>(); - } - } - - /// hasSameBaseTemplate - Returns true when the base templates are the same, - /// even if the template arguments are not. - static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST, - const TemplateSpecializationType *ToTST) { - return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() == - ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl(); - } - - /// hasSameTemplate - Returns true if both types are specialized from the - /// same template declaration. If they come from different template aliases, - /// do a parallel ascension search to determine the highest template alias in - /// common and set the arguments to them. - static bool hasSameTemplate(const TemplateSpecializationType *&FromTST, - const TemplateSpecializationType *&ToTST) { - // Check the top templates if they are the same. - if (hasSameBaseTemplate(FromTST, ToTST)) - return true; - - // Create vectors of template aliases. - SmallVector<const TemplateSpecializationType*, 1> FromTemplateList, - ToTemplateList; - - makeTemplateList(FromTemplateList, FromTST); - makeTemplateList(ToTemplateList, ToTST); - - SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator - FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(), - ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend(); - - // Check if the lowest template types are the same. If not, return. - if (!hasSameBaseTemplate(*FromIter, *ToIter)) - return false; - - // Begin searching up the template aliases. The bottom most template - // matches so move up until one pair does not match. Use the template - // right before that one. - for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) { - if (!hasSameBaseTemplate(*FromIter, *ToIter)) - break; - } - - FromTST = FromIter[-1]; - ToTST = ToIter[-1]; - - return true; - } - - /// GetType - Retrieves the template type arguments, including default - /// arguments. - static QualType GetType(const TSTiterator &Iter) { - if (!Iter.isEnd()) - return Iter->getAsType(); - if (Iter.hasDesugaredTA()) - return Iter.getDesugaredTA().getAsType(); - return QualType(); - } - - /// GetTemplateDecl - Retrieves the template template arguments, including - /// default arguments. - static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) { - if (!Iter.isEnd()) - return Iter->getAsTemplate().getAsTemplateDecl(); - if (Iter.hasDesugaredTA()) - return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl(); - return nullptr; - } - - /// IsEqualExpr - Returns true if the expressions are the same in regards to - /// template arguments. These expressions are dependent, so profile them - /// instead of trying to evaluate them. - static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) { - if (FromExpr == ToExpr) - return true; - - if (!FromExpr || !ToExpr) - return false; - - llvm::FoldingSetNodeID FromID, ToID; - FromExpr->Profile(FromID, Context, true); - ToExpr->Profile(ToID, Context, true); - return FromID == ToID; - } - - // These functions converts the tree representation of the template - // differences into the internal character vector. - - /// TreeToString - Converts the Tree object into a character stream which - /// will later be turned into the output string. - void TreeToString(int Indent = 1) { - if (PrintTree) { - OS << '\n'; - OS.indent(2 * Indent); - ++Indent; - } - - // Handle cases where the difference is not templates with different - // arguments. - switch (Tree.GetKind()) { - case DiffTree::Invalid: - llvm_unreachable("Template diffing failed with bad DiffNode"); - case DiffTree::Type: { - QualType FromType, ToType; - Tree.GetTypeDiff(FromType, ToType); - PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(), - Tree.NodeIsSame()); - return; - } - case DiffTree::Expression: { - Expr *FromExpr, *ToExpr; - Tree.GetExpressionDiff(FromExpr, ToExpr); - PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), - Tree.NodeIsSame()); - return; - } - case DiffTree::TemplateTemplate: { - TemplateDecl *FromTD, *ToTD; - Tree.GetTemplateTemplateDiff(FromTD, ToTD); - PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(), - Tree.ToDefault(), Tree.NodeIsSame()); - return; - } - case DiffTree::Integer: { - llvm::APSInt FromInt, ToInt; - Expr *FromExpr, *ToExpr; - bool IsValidFromInt, IsValidToInt; - QualType FromIntType, ToIntType; - Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt, - FromIntType, ToIntType, FromExpr, ToExpr); - PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType, - ToIntType, FromExpr, ToExpr, Tree.FromDefault(), - Tree.ToDefault(), Tree.NodeIsSame()); - return; - } - case DiffTree::Declaration: { - ValueDecl *FromValueDecl, *ToValueDecl; - bool FromAddressOf, ToAddressOf; - bool FromNullPtr, ToNullPtr; - Expr *FromExpr, *ToExpr; - Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf, - ToAddressOf, FromNullPtr, ToNullPtr, FromExpr, - ToExpr); - PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf, - FromNullPtr, ToNullPtr, FromExpr, ToExpr, - Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); - return; - } - case DiffTree::FromDeclarationAndToInteger: { - ValueDecl *FromValueDecl; - bool FromAddressOf; - bool FromNullPtr; - Expr *FromExpr; - llvm::APSInt ToInt; - bool IsValidToInt; - QualType ToIntType; - Expr *ToExpr; - Tree.GetFromDeclarationAndToIntegerDiff( - FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt, - IsValidToInt, ToIntType, ToExpr); - assert((FromValueDecl || FromNullPtr) && IsValidToInt); - PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr, - FromExpr, Tree.FromDefault(), ToInt, ToIntType, - ToExpr, Tree.ToDefault()); - return; - } - case DiffTree::FromIntegerAndToDeclaration: { - llvm::APSInt FromInt; - bool IsValidFromInt; - QualType FromIntType; - Expr *FromExpr; - ValueDecl *ToValueDecl; - bool ToAddressOf; - bool ToNullPtr; - Expr *ToExpr; - Tree.GetFromIntegerAndToDeclarationDiff( - FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl, - ToAddressOf, ToNullPtr, ToExpr); - assert(IsValidFromInt && (ToValueDecl || ToNullPtr)); - PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr, - Tree.FromDefault(), ToValueDecl, ToAddressOf, - ToNullPtr, ToExpr, Tree.ToDefault()); - return; - } - case DiffTree::Template: { - // Node is root of template. Recurse on children. - TemplateDecl *FromTD, *ToTD; - Qualifiers FromQual, ToQual; - Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual); - - PrintQualifiers(FromQual, ToQual); - - if (!Tree.HasChildren()) { - // If we're dealing with a template specialization with zero - // arguments, there are no children; special-case this. - OS << FromTD->getNameAsString() << "<>"; - return; - } - - OS << FromTD->getNameAsString() << '<'; - Tree.MoveToChild(); - unsigned NumElideArgs = 0; - bool AllArgsElided = true; - do { - if (ElideType) { - if (Tree.NodeIsSame()) { - ++NumElideArgs; - continue; - } - AllArgsElided = false; - if (NumElideArgs > 0) { - PrintElideArgs(NumElideArgs, Indent); - NumElideArgs = 0; - OS << ", "; - } - } - TreeToString(Indent); - if (Tree.HasNextSibling()) - OS << ", "; - } while (Tree.AdvanceSibling()); - if (NumElideArgs > 0) { - if (AllArgsElided) - OS << "..."; - else - PrintElideArgs(NumElideArgs, Indent); - } - - Tree.Parent(); - OS << ">"; - return; - } - } - } - - // To signal to the text printer that a certain text needs to be bolded, - // a special character is injected into the character stream which the - // text printer will later strip out. - - /// Bold - Start bolding text. - void Bold() { - assert(!IsBold && "Attempting to bold text that is already bold."); - IsBold = true; - if (ShowColor) - OS << ToggleHighlight; - } - - /// Unbold - Stop bolding text. - void Unbold() { - assert(IsBold && "Attempting to remove bold from unbold text."); - IsBold = false; - if (ShowColor) - OS << ToggleHighlight; - } - - // Functions to print out the arguments and highlighting the difference. - - /// PrintTypeNames - prints the typenames, bolding differences. Will detect - /// typenames that are the same and attempt to disambiguate them by using - /// canonical typenames. - void PrintTypeNames(QualType FromType, QualType ToType, - bool FromDefault, bool ToDefault, bool Same) { - assert((!FromType.isNull() || !ToType.isNull()) && - "Only one template argument may be missing."); - - if (Same) { - OS << FromType.getAsString(Policy); - return; - } - - if (!FromType.isNull() && !ToType.isNull() && - FromType.getLocalUnqualifiedType() == - ToType.getLocalUnqualifiedType()) { - Qualifiers FromQual = FromType.getLocalQualifiers(), - ToQual = ToType.getLocalQualifiers(); - PrintQualifiers(FromQual, ToQual); - FromType.getLocalUnqualifiedType().print(OS, Policy); - return; - } - - std::string FromTypeStr = FromType.isNull() ? "(no argument)" - : FromType.getAsString(Policy); - std::string ToTypeStr = ToType.isNull() ? "(no argument)" - : ToType.getAsString(Policy); - // Switch to canonical typename if it is better. - // TODO: merge this with other aka printing above. - if (FromTypeStr == ToTypeStr) { - std::string FromCanTypeStr = - FromType.getCanonicalType().getAsString(Policy); - std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy); - if (FromCanTypeStr != ToCanTypeStr) { - FromTypeStr = FromCanTypeStr; - ToTypeStr = ToCanTypeStr; - } - } - - if (PrintTree) OS << '['; - OS << (FromDefault ? "(default) " : ""); - Bold(); - OS << FromTypeStr; - Unbold(); - if (PrintTree) { - OS << " != " << (ToDefault ? "(default) " : ""); - Bold(); - OS << ToTypeStr; - Unbold(); - OS << "]"; - } - } - - /// PrintExpr - Prints out the expr template arguments, highlighting argument - /// differences. - void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault, - bool ToDefault, bool Same) { - assert((FromExpr || ToExpr) && - "Only one template argument may be missing."); - if (Same) { - PrintExpr(FromExpr); - } else if (!PrintTree) { - OS << (FromDefault ? "(default) " : ""); - Bold(); - PrintExpr(FromExpr); - Unbold(); - } else { - OS << (FromDefault ? "[(default) " : "["); - Bold(); - PrintExpr(FromExpr); - Unbold(); - OS << " != " << (ToDefault ? "(default) " : ""); - Bold(); - PrintExpr(ToExpr); - Unbold(); - OS << ']'; - } - } - - /// PrintExpr - Actual formatting and printing of expressions. - void PrintExpr(const Expr *E) { - if (E) { - E->printPretty(OS, nullptr, Policy); - return; - } - OS << "(no argument)"; - } - - /// PrintTemplateTemplate - Handles printing of template template arguments, - /// highlighting argument differences. - void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD, - bool FromDefault, bool ToDefault, bool Same) { - assert((FromTD || ToTD) && "Only one template argument may be missing."); - - std::string FromName = FromTD ? FromTD->getName() : "(no argument)"; - std::string ToName = ToTD ? ToTD->getName() : "(no argument)"; - if (FromTD && ToTD && FromName == ToName) { - FromName = FromTD->getQualifiedNameAsString(); - ToName = ToTD->getQualifiedNameAsString(); - } - - if (Same) { - OS << "template " << FromTD->getNameAsString(); - } else if (!PrintTree) { - OS << (FromDefault ? "(default) template " : "template "); - Bold(); - OS << FromName; - Unbold(); - } else { - OS << (FromDefault ? "[(default) template " : "[template "); - Bold(); - OS << FromName; - Unbold(); - OS << " != " << (ToDefault ? "(default) template " : "template "); - Bold(); - OS << ToName; - Unbold(); - OS << ']'; - } - } - - /// PrintAPSInt - Handles printing of integral arguments, highlighting - /// argument differences. - void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt, - bool IsValidFromInt, bool IsValidToInt, QualType FromIntType, - QualType ToIntType, Expr *FromExpr, Expr *ToExpr, - bool FromDefault, bool ToDefault, bool Same) { - assert((IsValidFromInt || IsValidToInt) && - "Only one integral argument may be missing."); - - if (Same) { - if (FromIntType->isBooleanType()) { - OS << ((FromInt == 0) ? "false" : "true"); - } else { - OS << FromInt.toString(10); - } - return; - } - - bool PrintType = IsValidFromInt && IsValidToInt && - !Context.hasSameType(FromIntType, ToIntType); - - if (!PrintTree) { - OS << (FromDefault ? "(default) " : ""); - PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType); - } else { - OS << (FromDefault ? "[(default) " : "["); - PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType); - OS << " != " << (ToDefault ? "(default) " : ""); - PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType); - OS << ']'; - } - } - - /// PrintAPSInt - If valid, print the APSInt. If the expression is - /// gives more information, print it too. - void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid, - QualType IntType, bool PrintType) { - Bold(); - if (Valid) { - if (HasExtraInfo(E)) { - PrintExpr(E); - Unbold(); - OS << " aka "; - Bold(); - } - if (PrintType) { - Unbold(); - OS << "("; - Bold(); - IntType.print(OS, Context.getPrintingPolicy()); - Unbold(); - OS << ") "; - Bold(); - } - if (IntType->isBooleanType()) { - OS << ((Val == 0) ? "false" : "true"); - } else { - OS << Val.toString(10); - } - } else if (E) { - PrintExpr(E); - } else { - OS << "(no argument)"; - } - Unbold(); - } - - /// HasExtraInfo - Returns true if E is not an integer literal, the - /// negation of an integer literal, or a boolean literal. - bool HasExtraInfo(Expr *E) { - if (!E) return false; - - E = E->IgnoreImpCasts(); - - if (isa<IntegerLiteral>(E)) return false; - - if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) - if (UO->getOpcode() == UO_Minus) - if (isa<IntegerLiteral>(UO->getSubExpr())) - return false; - - if (isa<CXXBoolLiteralExpr>(E)) - return false; - - return true; - } - - void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) { - if (VD) { - if (AddressOf) - OS << "&"; - OS << VD->getName(); - return; - } - - if (NullPtr) { - if (E && !isa<CXXNullPtrLiteralExpr>(E)) { - PrintExpr(E); - if (IsBold) { - Unbold(); - OS << " aka "; - Bold(); - } else { - OS << " aka "; - } - } - - OS << "nullptr"; - return; - } - - OS << "(no argument)"; - } - - /// PrintDecl - Handles printing of Decl arguments, highlighting - /// argument differences. - void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, - bool FromAddressOf, bool ToAddressOf, bool FromNullPtr, - bool ToNullPtr, Expr *FromExpr, Expr *ToExpr, - bool FromDefault, bool ToDefault, bool Same) { - assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) && - "Only one Decl argument may be NULL"); - - if (Same) { - PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr); - } else if (!PrintTree) { - OS << (FromDefault ? "(default) " : ""); - Bold(); - PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr); - Unbold(); - } else { - OS << (FromDefault ? "[(default) " : "["); - Bold(); - PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr); - Unbold(); - OS << " != " << (ToDefault ? "(default) " : ""); - Bold(); - PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr); - Unbold(); - OS << ']'; - } - } - - /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and - /// APSInt to print a mixed difference. - void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf, - bool IsNullPtr, Expr *VDExpr, bool DefaultDecl, - const llvm::APSInt &Val, QualType IntType, - Expr *IntExpr, bool DefaultInt) { - if (!PrintTree) { - OS << (DefaultDecl ? "(default) " : ""); - Bold(); - PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); - Unbold(); - } else { - OS << (DefaultDecl ? "[(default) " : "["); - Bold(); - PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); - Unbold(); - OS << " != " << (DefaultInt ? "(default) " : ""); - PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); - OS << ']'; - } - } - - /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and - /// ValueDecl to print a mixed difference. - void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType, - Expr *IntExpr, bool DefaultInt, ValueDecl *VD, - bool NeedAddressOf, bool IsNullPtr, - Expr *VDExpr, bool DefaultDecl) { - if (!PrintTree) { - OS << (DefaultInt ? "(default) " : ""); - PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); - } else { - OS << (DefaultInt ? "[(default) " : "["); - PrintAPSInt(Val, IntExpr, true /*Valid*/, IntType, false /*PrintType*/); - OS << " != " << (DefaultDecl ? "(default) " : ""); - Bold(); - PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr); - Unbold(); - OS << ']'; - } - } - - // Prints the appropriate placeholder for elided template arguments. - void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) { - if (PrintTree) { - OS << '\n'; - for (unsigned i = 0; i < Indent; ++i) - OS << " "; - } - if (NumElideArgs == 0) return; - if (NumElideArgs == 1) - OS << "[...]"; - else - OS << "[" << NumElideArgs << " * ...]"; - } - - // Prints and highlights differences in Qualifiers. - void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) { - // Both types have no qualifiers - if (FromQual.empty() && ToQual.empty()) - return; - - // Both types have same qualifiers - if (FromQual == ToQual) { - PrintQualifier(FromQual, /*ApplyBold*/false); - return; - } - - // Find common qualifiers and strip them from FromQual and ToQual. - Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(FromQual, - ToQual); - - // The qualifiers are printed before the template name. - // Inline printing: - // The common qualifiers are printed. Then, qualifiers only in this type - // are printed and highlighted. Finally, qualifiers only in the other - // type are printed and highlighted inside parentheses after "missing". - // Tree printing: - // Qualifiers are printed next to each other, inside brackets, and - // separated by "!=". The printing order is: - // common qualifiers, highlighted from qualifiers, "!=", - // common qualifiers, highlighted to qualifiers - if (PrintTree) { - OS << "["; - if (CommonQual.empty() && FromQual.empty()) { - Bold(); - OS << "(no qualifiers) "; - Unbold(); - } else { - PrintQualifier(CommonQual, /*ApplyBold*/false); - PrintQualifier(FromQual, /*ApplyBold*/true); - } - OS << "!= "; - if (CommonQual.empty() && ToQual.empty()) { - Bold(); - OS << "(no qualifiers)"; - Unbold(); - } else { - PrintQualifier(CommonQual, /*ApplyBold*/false, - /*appendSpaceIfNonEmpty*/!ToQual.empty()); - PrintQualifier(ToQual, /*ApplyBold*/true, - /*appendSpaceIfNonEmpty*/false); - } - OS << "] "; - } else { - PrintQualifier(CommonQual, /*ApplyBold*/false); - PrintQualifier(FromQual, /*ApplyBold*/true); - } - } - - void PrintQualifier(Qualifiers Q, bool ApplyBold, - bool AppendSpaceIfNonEmpty = true) { - if (Q.empty()) return; - if (ApplyBold) Bold(); - Q.print(OS, Policy, AppendSpaceIfNonEmpty); - if (ApplyBold) Unbold(); - } - -public: - - TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType, - QualType ToType, bool PrintTree, bool PrintFromType, - bool ElideType, bool ShowColor) - : Context(Context), - Policy(Context.getLangOpts()), - ElideType(ElideType), - PrintTree(PrintTree), - ShowColor(ShowColor), - // When printing a single type, the FromType is the one printed. - FromTemplateType(PrintFromType ? FromType : ToType), - ToTemplateType(PrintFromType ? ToType : FromType), - OS(OS), - IsBold(false) { - } - - /// DiffTemplate - Start the template type diffing. - void DiffTemplate() { - Qualifiers FromQual = FromTemplateType.getQualifiers(), - ToQual = ToTemplateType.getQualifiers(); - - const TemplateSpecializationType *FromOrigTST = - GetTemplateSpecializationType(Context, FromTemplateType); - const TemplateSpecializationType *ToOrigTST = - GetTemplateSpecializationType(Context, ToTemplateType); - - // Only checking templates. - if (!FromOrigTST || !ToOrigTST) - return; - - // Different base templates. - if (!hasSameTemplate(FromOrigTST, ToOrigTST)) { - return; - } - - FromQual -= QualType(FromOrigTST, 0).getQualifiers(); - ToQual -= QualType(ToOrigTST, 0).getQualifiers(); - - // Same base template, but different arguments. - Tree.SetTemplateDiff(FromOrigTST->getTemplateName().getAsTemplateDecl(), - ToOrigTST->getTemplateName().getAsTemplateDecl(), - FromQual, ToQual, false /*FromDefault*/, - false /*ToDefault*/); - - DiffTemplate(FromOrigTST, ToOrigTST); - } - - /// Emit - When the two types given are templated types with the same - /// base template, a string representation of the type difference will be - /// emitted to the stream and return true. Otherwise, return false. - bool Emit() { - Tree.StartTraverse(); - if (Tree.Empty()) - return false; - - TreeToString(); - assert(!IsBold && "Bold is applied to end of string."); - return true; - } -}; // end class TemplateDiff -} // end anonymous namespace - -/// FormatTemplateTypeDiff - A helper static function to start the template -/// diff and return the properly formatted string. Returns true if the diff -/// is successful. -static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, - QualType ToType, bool PrintTree, - bool PrintFromType, bool ElideType, - bool ShowColors, raw_ostream &OS) { - if (PrintTree) - PrintFromType = true; - TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType, - ElideType, ShowColors); - TD.DiffTemplate(); - return TD.Emit(); -} |
