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