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