1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894 |
- //===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//
- //
- // The LLVM Compiler Infrastructure
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file implements a diagnostic formatting hook for AST elements.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/AST/ASTDiagnostic.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/ASTLambda.h"
- #include "clang/AST/Attr.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/DeclTemplate.h"
- #include "clang/AST/ExprCXX.h"
- #include "clang/AST/TemplateBase.h"
- #include "clang/AST/Type.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/Support/raw_ostream.h"
- // //
- ///////////////////////////////////////////////////////////////////////////////
- using namespace clang;
- // Returns a desugared version of the QualType, and marks ShouldAKA as true
- // whenever we remove significant sugar from the type.
- static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) {
- QualifierCollector QC;
- while (true) {
- const Type *Ty = QC.strip(QT);
- // Don't aka just because we saw an elaborated type...
- if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Ty)) {
- QT = ET->desugar();
- continue;
- }
- // ... or a paren type ...
- if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
- QT = PT->desugar();
- continue;
- }
- // ...or a substituted template type parameter ...
- if (const SubstTemplateTypeParmType *ST =
- dyn_cast<SubstTemplateTypeParmType>(Ty)) {
- QT = ST->desugar();
- continue;
- }
- // ...or an attributed type...
- if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) {
- QT = AT->desugar();
- continue;
- }
- // ...or an adjusted type...
- if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) {
- QT = AT->desugar();
- continue;
- }
- // ... or an auto type.
- if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
- if (!AT->isSugared())
- break;
- QT = AT->desugar();
- continue;
- }
- // Don't desugar template specializations, unless it's an alias template.
- if (const TemplateSpecializationType *TST
- = dyn_cast<TemplateSpecializationType>(Ty))
- if (!TST->isTypeAlias())
- 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())
- break;
- // HLSL Change: don't desugar typedefs that were injected into AST.
- if (Ty->getTypeClass() == Type::TypeClass::Typedef) {
- const TypedefType* tt = cast<TypedefType>(Ty);
- if (tt->getDecl()->getLocation() == SourceLocation()) {
- break;
- }
- }
- // Otherwise, do a single-step desugar.
- QualType Underlying;
- bool IsSugar = false;
- switch (Ty->getTypeClass()) {
- #define ABSTRACT_TYPE(Class, Base)
- #define TYPE(Class, Base) \
- case Type::Class: { \
- const Class##Type *CTy = cast<Class##Type>(Ty); \
- if (CTy->isSugared()) { \
- IsSugar = true; \
- Underlying = CTy->desugar(); \
- } \
- break; \
- }
- #include "clang/AST/TypeNodes.def"
- }
- // If it wasn't sugared, we're done.
- if (!IsSugar)
- break;
- // If the desugared type is a vector type, we don't want to expand
- // it, it will turn into an attribute mess. People want their "vec4".
- if (isa<VectorType>(Underlying))
- break;
- // Don't desugar through the primary typedef of an anonymous type.
- if (const TagType *UTT = Underlying->getAs<TagType>())
- if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))
- if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
- break;
- // Record that we actually looked through an opaque type here.
- ShouldAKA = true;
- QT = Underlying;
- }
- // If we have a pointer-like type, desugar the pointee as well.
- // FIXME: Handle other pointer-like types.
- if (const PointerType *Ty = QT->getAs<PointerType>()) {
- QT = Context.getPointerType(Desugar(Context, Ty->getPointeeType(),
- ShouldAKA));
- } else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) {
- QT = Context.getObjCObjectPointerType(Desugar(Context, Ty->getPointeeType(),
- ShouldAKA));
- } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
- QT = Context.getLValueReferenceType(Desugar(Context, Ty->getPointeeType(),
- ShouldAKA));
- } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
- QT = Context.getRValueReferenceType(Desugar(Context, Ty->getPointeeType(),
- ShouldAKA));
- } else if (const auto *Ty = QT->getAs<ObjCObjectType>()) {
- if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {
- QualType BaseType = Desugar(Context, Ty->getBaseType(), ShouldAKA);
- QT = Context.getObjCObjectType(BaseType, Ty->getTypeArgsAsWritten(),
- llvm::makeArrayRef(Ty->qual_begin(),
- Ty->getNumProtocols()),
- Ty->isKindOfTypeAsWritten());
- }
- }
- return QC.apply(Context, QT);
- }
- /// \brief Convert the given type to a string suitable for printing as part of
- /// a diagnostic.
- ///
- /// There are four main criteria when determining whether we should have an
- /// a.k.a. clause when pretty-printing a type:
- ///
- /// 1) Some types provide very minimal sugar that doesn't impede the
- /// user's understanding --- for example, elaborated type
- /// specifiers. If this is all the sugar we see, we don't want an
- /// a.k.a. clause.
- /// 2) Some types are technically sugared but are much more familiar
- /// when seen in their sugared form --- for example, va_list,
- /// vector types, and the magic Objective C types. We don't
- /// want to desugar these, even if we do produce an a.k.a. clause.
- /// 3) Some types may have already been desugared previously in this diagnostic.
- /// if this is the case, doing another "aka" would just be clutter.
- /// 4) Two different types within the same diagnostic have the same output
- /// string. In this case, force an a.k.a with the desugared type when
- /// doing so will provide additional information.
- ///
- /// \param Context the context in which the type was allocated
- /// \param Ty the type to print
- /// \param QualTypeVals pointer values to QualTypes which are used in the
- /// diagnostic message
- static std::string
- ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
- ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
- ArrayRef<intptr_t> QualTypeVals) {
- // FIXME: Playing with std::string is really slow.
- bool ForceAKA = false;
- QualType CanTy = Ty.getCanonicalType();
- std::string S = Ty.getAsString(Context.getPrintingPolicy());
- std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());
- for (unsigned I = 0, E = QualTypeVals.size(); I != E; ++I) {
- QualType CompareTy =
- QualType::getFromOpaquePtr(reinterpret_cast<void*>(QualTypeVals[I]));
- if (CompareTy.isNull())
- continue;
- if (CompareTy == Ty)
- continue; // Same types
- QualType CompareCanTy = CompareTy.getCanonicalType();
- if (CompareCanTy == CanTy)
- continue; // Same canonical types
- std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
- bool ShouldAKA = false;
- QualType CompareDesugar = Desugar(Context, CompareTy, ShouldAKA);
- std::string CompareDesugarStr =
- CompareDesugar.getAsString(Context.getPrintingPolicy());
- if (CompareS != S && CompareDesugarStr != S)
- continue; // The type string is different than the comparison string
- // and the desugared comparison string.
- std::string CompareCanS =
- CompareCanTy.getAsString(Context.getPrintingPolicy());
-
- if (CompareCanS == CanS)
- continue; // No new info from canonical type
- ForceAKA = true;
- break;
- }
- // Check to see if we already desugared this type in this
- // diagnostic. If so, don't do it again.
- bool Repeated = false;
- for (unsigned i = 0, e = PrevArgs.size(); i != e; ++i) {
- // TODO: Handle ak_declcontext case.
- if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) {
- void *Ptr = (void*)PrevArgs[i].second;
- QualType PrevTy(QualType::getFromOpaquePtr(Ptr));
- if (PrevTy == Ty) {
- Repeated = true;
- break;
- }
- }
- }
- // Consider producing an a.k.a. clause if removing all the direct
- // sugar gives us something "significantly different".
- if (!Repeated) {
- bool ShouldAKA = false;
- QualType DesugaredTy = Desugar(Context, Ty, ShouldAKA);
- if (ShouldAKA || ForceAKA) {
- if (DesugaredTy == Ty) {
- DesugaredTy = Ty.getCanonicalType();
- }
- std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy());
- if (akaStr != S) {
- S = "'" + S + "' (aka '" + akaStr + "')";
- return S;
- }
- }
- // Give some additional info on vector types. These are either not desugared
- // or displaying complex __attribute__ expressions so add details of the
- // type and element count.
- if (Ty->isVectorType()) {
- const VectorType *VTy = Ty->getAs<VectorType>();
- std::string DecoratedString;
- llvm::raw_string_ostream OS(DecoratedString);
- const char *Values = VTy->getNumElements() > 1 ? "values" : "value";
- OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '"
- << VTy->getElementType().getAsString(Context.getPrintingPolicy())
- << "' " << Values << ")";
- return OS.str();
- }
- }
- S = "'" + S + "'";
- return S;
- }
- static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
- QualType ToType, bool PrintTree,
- bool PrintFromType, bool ElideType,
- bool ShowColors, raw_ostream &OS);
- void clang::FormatASTNodeDiagnosticArgument(
- DiagnosticsEngine::ArgumentKind Kind,
- intptr_t Val,
- StringRef Modifier,
- StringRef Argument,
- ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
- SmallVectorImpl<char> &Output,
- void *Cookie,
- ArrayRef<intptr_t> QualTypeVals) {
- ASTContext &Context = *static_cast<ASTContext*>(Cookie);
-
- size_t OldEnd = Output.size();
- llvm::raw_svector_ostream OS(Output);
- bool NeedQuotes = true;
-
- switch (Kind) {
- default: llvm_unreachable("unknown ArgumentKind");
- case DiagnosticsEngine::ak_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
- }
- 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;
- }
- }
- OS.flush();
- 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;
- /// FromType - When single type printing is selected, this is the type to be
- /// be printed. When tree printing is selected, this type will show up first
- /// in the tree.
- QualType FromType;
- /// ToType - The type that FromType is compared to. Only in tree printing
- /// will this type be outputed.
- QualType ToType;
- /// 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 and which fields are used.
- enum DiffKind {
- /// Incomplete or invalid node.
- Invalid,
- /// Another level of templates, uses TemplateDecl and Qualifiers
- Template,
- /// Type difference, uses QualType
- Type,
- /// Expression difference, uses Expr
- Expression,
- /// Template argument difference, uses TemplateDecl
- TemplateTemplate,
- /// Integer difference, uses APSInt and Expr
- Integer,
- /// Declaration difference, uses ValueDecl
- Declaration
- };
- private:
- /// 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;
- /// NextNode - The index of the next sibling node or 0.
- unsigned NextNode;
- /// ChildNode - The index of the first child node or 0.
- unsigned ChildNode;
- /// ParentNode - The index of the parent node.
- unsigned ParentNode;
- /// FromType, ToType - The type arguments.
- QualType FromType, ToType;
- /// FromExpr, ToExpr - The expression arguments.
- Expr *FromExpr, *ToExpr;
- /// FromNullPtr, ToNullPtr - If the template argument is a nullptr
- bool FromNullPtr, ToNullPtr;
- /// FromTD, ToTD - The template decl for template template
- /// arguments or the type arguments that are templates.
- TemplateDecl *FromTD, *ToTD;
- /// FromQual, ToQual - Qualifiers for template types.
- Qualifiers FromQual, ToQual;
- /// FromInt, ToInt - APSInt's for integral arguments.
- llvm::APSInt FromInt, ToInt;
- /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid.
- bool IsValidFromInt, IsValidToInt;
- /// FromValueDecl, ToValueDecl - Whether the argument is a decl.
- ValueDecl *FromValueDecl, *ToValueDecl;
- /// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of
- /// operator before it.
- bool FromAddressOf, ToAddressOf;
- /// FromDefault, ToDefault - Whether the argument is a default argument.
- bool FromDefault, ToDefault;
- /// Same - Whether the two arguments evaluate to the same value.
- bool Same;
- DiffNode(unsigned ParentNode = 0)
- : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode),
- FromType(), ToType(), FromExpr(nullptr), ToExpr(nullptr),
- FromNullPtr(false), ToNullPtr(false),
- FromTD(nullptr), ToTD(nullptr), IsValidFromInt(false),
- IsValidToInt(false), FromValueDecl(nullptr), ToValueDecl(nullptr),
- FromAddressOf(false), ToAddressOf(false), FromDefault(false),
- ToDefault(false), Same(false) {}
- };
- /// FlatTree - A flattened tree used to store the DiffNodes.
- SmallVector<DiffNode, 16> FlatTree;
- /// CurrentNode - The index of the current node being used.
- unsigned CurrentNode;
- /// NextFreeNode - The index of the next unused node. Used when creating
- /// child nodes.
- unsigned NextFreeNode;
- /// ReadNode - The index of the current node being read.
- unsigned ReadNode;
-
- public:
- DiffTree() :
- CurrentNode(0), NextFreeNode(1) {
- FlatTree.push_back(DiffNode());
- }
- // Node writing functions.
- /// SetNode - Sets FromTD and ToTD of the current node.
- void SetNode(TemplateDecl *FromTD, TemplateDecl *ToTD) {
- FlatTree[CurrentNode].FromTD = FromTD;
- FlatTree[CurrentNode].ToTD = ToTD;
- }
- /// SetNode - Sets FromType and ToType of the current node.
- void SetNode(QualType FromType, QualType ToType) {
- FlatTree[CurrentNode].FromType = FromType;
- FlatTree[CurrentNode].ToType = ToType;
- }
- /// SetNode - Set FromExpr and ToExpr of the current node.
- void SetNode(Expr *FromExpr, Expr *ToExpr) {
- FlatTree[CurrentNode].FromExpr = FromExpr;
- FlatTree[CurrentNode].ToExpr = ToExpr;
- }
- /// SetNode - Set FromInt and ToInt of the current node.
- void SetNode(llvm::APSInt FromInt, llvm::APSInt ToInt,
- bool IsValidFromInt, bool IsValidToInt) {
- FlatTree[CurrentNode].FromInt = FromInt;
- FlatTree[CurrentNode].ToInt = ToInt;
- FlatTree[CurrentNode].IsValidFromInt = IsValidFromInt;
- FlatTree[CurrentNode].IsValidToInt = IsValidToInt;
- }
- /// SetNode - Set FromQual and ToQual of the current node.
- void SetNode(Qualifiers FromQual, Qualifiers ToQual) {
- FlatTree[CurrentNode].FromQual = FromQual;
- FlatTree[CurrentNode].ToQual = ToQual;
- }
- /// SetNode - Set FromValueDecl and ToValueDecl of the current node.
- void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
- bool FromAddressOf, bool ToAddressOf) {
- FlatTree[CurrentNode].FromValueDecl = FromValueDecl;
- FlatTree[CurrentNode].ToValueDecl = ToValueDecl;
- FlatTree[CurrentNode].FromAddressOf = FromAddressOf;
- FlatTree[CurrentNode].ToAddressOf = ToAddressOf;
- }
- /// SetSame - Sets the same flag of the current node.
- void SetSame(bool Same) {
- FlatTree[CurrentNode].Same = Same;
- }
- /// SetNullPtr - Sets the NullPtr flags of the current node.
- void SetNullPtr(bool FromNullPtr, bool ToNullPtr) {
- FlatTree[CurrentNode].FromNullPtr = FromNullPtr;
- FlatTree[CurrentNode].ToNullPtr = ToNullPtr;
- }
- /// SetDefault - Sets FromDefault and ToDefault flags of the current node.
- void SetDefault(bool FromDefault, bool ToDefault) {
- FlatTree[CurrentNode].FromDefault = FromDefault;
- FlatTree[CurrentNode].ToDefault = ToDefault;
- }
- /// 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() {
- CurrentNode = FlatTree[CurrentNode].ParentNode;
- }
- /// AddNode - Adds a child node to the current node, then sets that node
- /// node as the current node.
- void AddNode() {
- 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;
- }
- /// GetNode - Gets the FromType and ToType.
- void GetNode(QualType &FromType, QualType &ToType) {
- FromType = FlatTree[ReadNode].FromType;
- ToType = FlatTree[ReadNode].ToType;
- }
- /// GetNode - Gets the FromExpr and ToExpr.
- void GetNode(Expr *&FromExpr, Expr *&ToExpr) {
- FromExpr = FlatTree[ReadNode].FromExpr;
- ToExpr = FlatTree[ReadNode].ToExpr;
- }
- /// GetNode - Gets the FromTD and ToTD.
- void GetNode(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {
- FromTD = FlatTree[ReadNode].FromTD;
- ToTD = FlatTree[ReadNode].ToTD;
- }
- /// GetNode - Gets the FromInt and ToInt.
- void GetNode(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
- bool &IsValidFromInt, bool &IsValidToInt) {
- FromInt = FlatTree[ReadNode].FromInt;
- ToInt = FlatTree[ReadNode].ToInt;
- IsValidFromInt = FlatTree[ReadNode].IsValidFromInt;
- IsValidToInt = FlatTree[ReadNode].IsValidToInt;
- }
- /// GetNode - Gets the FromQual and ToQual.
- void GetNode(Qualifiers &FromQual, Qualifiers &ToQual) {
- FromQual = FlatTree[ReadNode].FromQual;
- ToQual = FlatTree[ReadNode].ToQual;
- }
- /// GetNode - Gets the FromValueDecl and ToValueDecl.
- void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
- bool &FromAddressOf, bool &ToAddressOf) {
- FromValueDecl = FlatTree[ReadNode].FromValueDecl;
- ToValueDecl = FlatTree[ReadNode].ToValueDecl;
- FromAddressOf = FlatTree[ReadNode].FromAddressOf;
- ToAddressOf = FlatTree[ReadNode].ToAddressOf;
- }
- /// 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;
- }
- /// FromNullPtr - Returns true if the from argument is null.
- bool FromNullPtr() {
- return FlatTree[ReadNode].FromNullPtr;
- }
- /// ToNullPtr - Returns true if the to argument is null.
- bool ToNullPtr() {
- return FlatTree[ReadNode].ToNullPtr;
- }
- /// FromDefault - Return true if the from argument is the default.
- bool FromDefault() {
- return FlatTree[ReadNode].FromDefault;
- }
- /// ToDefault - Return true if the to argument is the default.
- bool ToDefault() {
- return FlatTree[ReadNode].ToDefault;
- }
- /// 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 - 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 TSTiterator {
- typedef const TemplateArgument& reference;
- typedef const TemplateArgument* pointer;
- /// TST - the template specialization whose arguments this iterator
- /// traverse over.
- const TemplateSpecializationType *TST;
- /// DesugarTST - desugared template specialization used to extract
- /// default argument information
- const TemplateSpecializationType *DesugarTST;
- /// 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;
- /// TSTiterator - Constructs an iterator and sets it to the first template
- /// argument.
- TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
- : TST(TST),
- DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())),
- Index(0), CurrentTA(nullptr), EndTA(nullptr) {
- if (isEnd()) return;
- // Set to first template argument. If not a parameter pack, done.
- TemplateArgument TA = TST->getArg(0);
- if (TA.getKind() != TemplateArgument::Pack) return;
- // Start looking into the parameter pack.
- CurrentTA = TA.pack_begin();
- EndTA = TA.pack_end();
- // Found a valid template argument.
- if (CurrentTA != EndTA) return;
- // Parameter pack is empty, use the increment to get to a valid
- // template argument.
- ++(*this);
- }
- /// isEnd - Returns true if the iterator is one past the end.
- bool isEnd() const {
- return Index >= TST->getNumArgs();
- }
- /// &operator++ - Increment the iterator to the next template argument.
- TSTiterator &operator++() {
- // After the end, Index should be the default argument position in
- // DesugarTST, if it exists.
- if (isEnd()) {
- ++Index;
- return *this;
- }
- // If in a parameter pack, advance in the parameter pack.
- if (CurrentTA != EndTA) {
- ++CurrentTA;
- if (CurrentTA != EndTA)
- return *this;
- }
- // Loop until a template argument is found, or the end is reached.
- while (true) {
- // Advance to the next template argument. Break if reached the end.
- if (++Index == TST->getNumArgs()) break;
- // If the TemplateArgument is not a parameter pack, done.
- TemplateArgument TA = TST->getArg(Index);
- if (TA.getKind() != TemplateArgument::Pack) break;
- // Handle parameter packs.
- CurrentTA = TA.pack_begin();
- EndTA = TA.pack_end();
- // If the parameter pack is empty, try to advance again.
- if (CurrentTA != EndTA) break;
- }
- return *this;
- }
- /// operator* - Returns the appropriate TemplateArgument.
- reference operator*() const {
- assert(!isEnd() && "Index exceeds number of arguments.");
- if (CurrentTA == EndTA)
- return TST->getArg(Index);
- else
- return *CurrentTA;
- }
- /// operator-> - Allow access to the underlying TemplateArgument.
- pointer operator->() const {
- return &operator*();
- }
- /// getDesugar - Returns the deduced template argument from DesguarTST
- reference getDesugar() const {
- return DesugarTST->getArg(Index);
- }
- };
- // These functions build up the template diff tree, including functions to
- // retrieve and compare template arguments.
- static const TemplateSpecializationType * GetTemplateSpecializationType(
- ASTContext &Context, QualType Ty) {
- if (const TemplateSpecializationType *TST =
- Ty->getAs<TemplateSpecializationType>())
- return TST;
- const RecordType *RT = Ty->getAs<RecordType>();
- if (!RT)
- return nullptr;
- const ClassTemplateSpecializationDecl *CTSD =
- dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
- if (!CTSD)
- return nullptr;
- Ty = Context.getTemplateSpecializationType(
- TemplateName(CTSD->getSpecializedTemplate()),
- CTSD->getTemplateArgs().data(),
- CTSD->getTemplateArgs().size(),
- Ty.getLocalUnqualifiedType().getCanonicalType());
- return Ty->getAs<TemplateSpecializationType>();
- }
- /// DiffTypes - Fills a DiffNode with information about a type difference.
- void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
- TemplateTypeParmDecl *FromDefaultTypeDecl,
- TemplateTypeParmDecl *ToDefaultTypeDecl) {
- QualType FromType = GetType(FromIter, FromDefaultTypeDecl);
- QualType ToType = GetType(ToIter, ToDefaultTypeDecl);
- Tree.SetNode(FromType, ToType);
- Tree.SetDefault(FromIter.isEnd() && !FromType.isNull(),
- ToIter.isEnd() && !ToType.isNull());
- Tree.SetKind(DiffTree::Type);
- if (FromType.isNull() || ToType.isNull())
- return;
- if (Context.hasSameType(FromType, ToType)) {
- Tree.SetSame(true);
- return;
- }
- const TemplateSpecializationType *FromArgTST =
- GetTemplateSpecializationType(Context, FromType);
- if (!FromArgTST)
- return;
- const TemplateSpecializationType *ToArgTST =
- GetTemplateSpecializationType(Context, ToType);
- if (!ToArgTST)
- return;
- if (!hasSameTemplate(FromArgTST, ToArgTST))
- return;
- Qualifiers FromQual = FromType.getQualifiers(),
- ToQual = ToType.getQualifiers();
- FromQual -= QualType(FromArgTST, 0).getQualifiers();
- ToQual -= QualType(ToArgTST, 0).getQualifiers();
- Tree.SetNode(FromArgTST->getTemplateName().getAsTemplateDecl(),
- ToArgTST->getTemplateName().getAsTemplateDecl());
- Tree.SetNode(FromQual, ToQual);
- Tree.SetKind(DiffTree::Template);
- DiffTemplate(FromArgTST, ToArgTST);
- }
- /// DiffTemplateTemplates - Fills a DiffNode with information about a
- /// template template difference.
- void DiffTemplateTemplates(const TSTiterator &FromIter,
- const TSTiterator &ToIter,
- TemplateTemplateParmDecl *FromDefaultTemplateDecl,
- TemplateTemplateParmDecl *ToDefaultTemplateDecl) {
- TemplateDecl *FromDecl = GetTemplateDecl(FromIter, FromDefaultTemplateDecl);
- TemplateDecl *ToDecl = GetTemplateDecl(ToIter, ToDefaultTemplateDecl);
- Tree.SetNode(FromDecl, ToDecl);
- Tree.SetSame(FromDecl && ToDecl &&
- FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());
- Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl);
- Tree.SetKind(DiffTree::TemplateTemplate);
- }
- /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes
- static void InitializeNonTypeDiffVariables(
- ASTContext &Context, const TSTiterator &Iter,
- NonTypeTemplateParmDecl *Default, bool &HasInt, bool &HasValueDecl,
- bool &IsNullPtr, Expr *&E, llvm::APSInt &Value, ValueDecl *&VD) {
- HasInt = !Iter.isEnd() && Iter->getKind() == TemplateArgument::Integral;
- HasValueDecl =
- !Iter.isEnd() && Iter->getKind() == TemplateArgument::Declaration;
- IsNullPtr = !Iter.isEnd() && Iter->getKind() == TemplateArgument::NullPtr;
- if (HasInt)
- Value = Iter->getAsIntegral();
- else if (HasValueDecl)
- VD = Iter->getAsDecl();
- else if (!IsNullPtr)
- E = GetExpr(Iter, Default);
- if (E && Default->getType()->isPointerType())
- IsNullPtr = CheckForNullPtr(Context, E);
- }
- /// NeedsAddressOf - Helper function for DiffNonTypes. Returns true if the
- /// ValueDecl needs a '&' when printed.
- static bool NeedsAddressOf(ValueDecl *VD, Expr *E,
- NonTypeTemplateParmDecl *Default) {
- if (!VD)
- return false;
- if (E) {
- if (UnaryOperator *UO = dyn_cast<UnaryOperator>(E->IgnoreParens())) {
- if (UO->getOpcode() == UO_AddrOf) {
- return true;
- }
- }
- return false;
- }
- if (!Default->getType()->isReferenceType()) {
- return true;
- }
- return false;
- }
- /// 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;
- ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
- bool HasFromInt = false, HasToInt = false, HasFromValueDecl = false,
- HasToValueDecl = false, FromNullPtr = false, ToNullPtr = false;
- InitializeNonTypeDiffVariables(Context, FromIter, FromDefaultNonTypeDecl,
- HasFromInt, HasFromValueDecl, FromNullPtr,
- FromExpr, FromInt, FromValueDecl);
- InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl,
- HasToInt, HasToValueDecl, ToNullPtr,
- ToExpr, ToInt, ToValueDecl);
- assert(((!HasFromInt && !HasToInt) ||
- (!HasFromValueDecl && !HasToValueDecl)) &&
- "Template argument cannot be both integer and declaration");
- if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) {
- Tree.SetNode(FromExpr, ToExpr);
- Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr);
- if (FromDefaultNonTypeDecl->getType()->isIntegralOrEnumerationType()) {
- if (FromExpr)
- HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt,
- FromDefaultNonTypeDecl->getType());
- if (ToExpr)
- HasToInt = GetInt(Context, ToIter, ToExpr, ToInt,
- ToDefaultNonTypeDecl->getType());
- }
- if (HasFromInt && HasToInt) {
- Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
- Tree.SetSame(FromInt == ToInt);
- Tree.SetKind(DiffTree::Integer);
- } else if (HasFromInt || HasToInt) {
- Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
- Tree.SetSame(false);
- Tree.SetKind(DiffTree::Integer);
- } else {
- Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr) ||
- (FromNullPtr && ToNullPtr));
- Tree.SetNullPtr(FromNullPtr, ToNullPtr);
- Tree.SetKind(DiffTree::Expression);
- }
- return;
- }
- if (HasFromInt || HasToInt) {
- if (!HasFromInt && FromExpr)
- HasFromInt = GetInt(Context, FromIter, FromExpr, FromInt,
- FromDefaultNonTypeDecl->getType());
- if (!HasToInt && ToExpr)
- HasToInt = GetInt(Context, ToIter, ToExpr, ToInt,
- ToDefaultNonTypeDecl->getType());
- Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt);
- if (HasFromInt && HasToInt) {
- Tree.SetSame(FromInt == ToInt);
- } else {
- Tree.SetSame(false);
- }
- Tree.SetDefault(FromIter.isEnd() && HasFromInt,
- ToIter.isEnd() && HasToInt);
- Tree.SetKind(DiffTree::Integer);
- return;
- }
- if (!HasFromValueDecl && FromExpr)
- FromValueDecl = GetValueDecl(FromIter, FromExpr);
- if (!HasToValueDecl && ToExpr)
- ToValueDecl = GetValueDecl(ToIter, ToExpr);
- bool FromAddressOf =
- NeedsAddressOf(FromValueDecl, FromExpr, FromDefaultNonTypeDecl);
- bool ToAddressOf =
- NeedsAddressOf(ToValueDecl, ToExpr, ToDefaultNonTypeDecl);
- Tree.SetNullPtr(FromNullPtr, ToNullPtr);
- Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
- Tree.SetSame(FromValueDecl && ToValueDecl &&
- FromValueDecl->getCanonicalDecl() ==
- ToValueDecl->getCanonicalDecl());
- Tree.SetDefault(FromIter.isEnd() && FromValueDecl,
- ToIter.isEnd() && ToValueDecl);
- Tree.SetKind(DiffTree::Declaration);
- }
- /// 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);
- TemplateTypeParmDecl *FromDefaultTypeDecl =
- dyn_cast<TemplateTypeParmDecl>(FromParamND);
- TemplateTypeParmDecl *ToDefaultTypeDecl =
- dyn_cast<TemplateTypeParmDecl>(ToParamND);
- if (FromDefaultTypeDecl && ToDefaultTypeDecl)
- DiffTypes(FromIter, ToIter, FromDefaultTypeDecl, ToDefaultTypeDecl);
- TemplateTemplateParmDecl *FromDefaultTemplateDecl =
- dyn_cast<TemplateTemplateParmDecl>(FromParamND);
- TemplateTemplateParmDecl *ToDefaultTemplateDecl =
- dyn_cast<TemplateTemplateParmDecl>(ToParamND);
- if (FromDefaultTemplateDecl && ToDefaultTemplateDecl)
- DiffTemplateTemplates(FromIter, ToIter, FromDefaultTemplateDecl,
- ToDefaultTemplateDecl);
- NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =
- dyn_cast<NonTypeTemplateParmDecl>(FromParamND);
- NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =
- dyn_cast<NonTypeTemplateParmDecl>(ToParamND);
- if (FromDefaultNonTypeDecl && ToDefaultNonTypeDecl)
- DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,
- ToDefaultNonTypeDecl);
- ++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,
- TemplateTypeParmDecl *DefaultTTPD) {
- bool isVariadic = DefaultTTPD->isParameterPack();
- if (!Iter.isEnd())
- return Iter->getAsType();
- if (isVariadic)
- return QualType();
- QualType ArgType = DefaultTTPD->getDefaultArgument();
- if (ArgType->isDependentType())
- return Iter.getDesugar().getAsType();
- return ArgType;
- }
- /// GetExpr - Retrieves the template expression argument, including default
- /// arguments.
- static Expr *GetExpr(const TSTiterator &Iter,
- NonTypeTemplateParmDecl *DefaultNTTPD) {
- Expr *ArgExpr = nullptr;
- bool isVariadic = DefaultNTTPD->isParameterPack();
- if (!Iter.isEnd())
- ArgExpr = Iter->getAsExpr();
- else if (!isVariadic)
- ArgExpr = DefaultNTTPD->getDefaultArgument();
- if (ArgExpr)
- while (SubstNonTypeTemplateParmExpr *SNTTPE =
- dyn_cast<SubstNonTypeTemplateParmExpr>(ArgExpr))
- ArgExpr = SNTTPE->getReplacement();
- return ArgExpr;
- }
- /// GetInt - Retrieves the template integer argument, including evaluating
- /// default arguments. If the value comes from an expression, extend the
- /// APSInt to size of IntegerType to match the behavior in
- /// Sema::CheckTemplateArgument
- static bool GetInt(ASTContext &Context, const TSTiterator &Iter,
- Expr *ArgExpr, llvm::APSInt &Int, QualType IntegerType) {
- // Default, value-depenedent expressions require fetching
- // from the desugared TemplateArgument, otherwise expression needs to
- // be evaluatable.
- if (Iter.isEnd() && ArgExpr->isValueDependent()) {
- switch (Iter.getDesugar().getKind()) {
- case TemplateArgument::Integral:
- Int = Iter.getDesugar().getAsIntegral();
- return true;
- case TemplateArgument::Expression:
- ArgExpr = Iter.getDesugar().getAsExpr();
- Int = ArgExpr->EvaluateKnownConstInt(Context);
- Int = Int.extOrTrunc(Context.getTypeSize(IntegerType));
- return true;
- default:
- llvm_unreachable("Unexpected template argument kind");
- }
- } else if (ArgExpr->isEvaluatable(Context)) {
- Int = ArgExpr->EvaluateKnownConstInt(Context);
- Int = Int.extOrTrunc(Context.getTypeSize(IntegerType));
- return true;
- }
- return false;
- }
- /// GetValueDecl - Retrieves the template Decl argument, including
- /// default expression argument.
- static ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
- // Default, value-depenedent expressions require fetching
- // from the desugared TemplateArgument
- if (Iter.isEnd() && ArgExpr->isValueDependent())
- switch (Iter.getDesugar().getKind()) {
- case TemplateArgument::Declaration:
- return Iter.getDesugar().getAsDecl();
- case TemplateArgument::Expression:
- ArgExpr = Iter.getDesugar().getAsExpr();
- return cast<DeclRefExpr>(ArgExpr)->getDecl();
- default:
- llvm_unreachable("Unexpected template argument kind");
- }
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr);
- if (!DRE) {
- UnaryOperator *UO = dyn_cast<UnaryOperator>(ArgExpr->IgnoreParens());
- if (!UO)
- return nullptr;
- DRE = cast<DeclRefExpr>(UO->getSubExpr());
- }
- return DRE->getDecl();
- }
- /// CheckForNullPtr - returns true if the expression can be evaluated as
- /// a null pointer
- static bool CheckForNullPtr(ASTContext &Context, Expr *E) {
- assert(E && "Expected expression");
- E = E->IgnoreParenCasts();
- if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull))
- return true;
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E);
- if (!DRE)
- return false;
- VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
- if (!VD || !VD->hasInit())
- return false;
- return VD->getInit()->IgnoreParenCasts()->isNullPointerConstant(
- Context, Expr::NPC_ValueDependentIsNull);
- }
- /// GetTemplateDecl - Retrieves the template template arguments, including
- /// default arguments.
- static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter,
- TemplateTemplateParmDecl *DefaultTTPD) {
- bool isVariadic = DefaultTTPD->isParameterPack();
- TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument();
- TemplateDecl *DefaultTD = nullptr;
- if (TA.getKind() != TemplateArgument::Null)
- DefaultTD = TA.getAsTemplate().getAsTemplateDecl();
- if (!Iter.isEnd())
- return Iter->getAsTemplate().getAsTemplateDecl();
- if (!isVariadic)
- return DefaultTD;
- return nullptr;
- }
- /// IsEqualExpr - Returns true if the expressions evaluate to the same value.
- static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {
- if (FromExpr == ToExpr)
- return true;
- if (!FromExpr || !ToExpr)
- return false;
- DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr->IgnoreParens()),
- *ToDRE = dyn_cast<DeclRefExpr>(ToExpr->IgnoreParens());
- if (FromDRE || ToDRE) {
- if (!FromDRE || !ToDRE)
- return false;
- return FromDRE->getDecl() == ToDRE->getDecl();
- }
- Expr::EvalResult FromResult, ToResult;
- if (!FromExpr->EvaluateAsRValue(FromResult, Context) ||
- !ToExpr->EvaluateAsRValue(ToResult, Context)) {
- llvm::FoldingSetNodeID FromID, ToID;
- FromExpr->Profile(FromID, Context, true);
- ToExpr->Profile(ToID, Context, true);
- return FromID == ToID;
- }
- APValue &FromVal = FromResult.Val;
- APValue &ToVal = ToResult.Val;
- if (FromVal.getKind() != ToVal.getKind()) return false;
- switch (FromVal.getKind()) {
- case APValue::Int:
- return FromVal.getInt() == ToVal.getInt();
- case APValue::LValue: {
- APValue::LValueBase FromBase = FromVal.getLValueBase();
- APValue::LValueBase ToBase = ToVal.getLValueBase();
- if (FromBase.isNull() && ToBase.isNull())
- return true;
- if (FromBase.isNull() || ToBase.isNull())
- return false;
- return FromBase.get<const ValueDecl*>() ==
- ToBase.get<const ValueDecl*>();
- }
- case APValue::MemberPointer:
- return FromVal.getMemberPointerDecl() == ToVal.getMemberPointerDecl();
- default:
- llvm_unreachable("Unknown template argument expression.");
- }
- }
- // 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.GetNode(FromType, ToType);
- PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),
- Tree.NodeIsSame());
- return;
- }
- case DiffTree::Expression: {
- Expr *FromExpr, *ToExpr;
- Tree.GetNode(FromExpr, ToExpr);
- PrintExpr(FromExpr, ToExpr, Tree.FromNullPtr(), Tree.ToNullPtr(),
- Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
- return;
- }
- case DiffTree::TemplateTemplate: {
- TemplateDecl *FromTD, *ToTD;
- Tree.GetNode(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;
- Tree.GetNode(FromExpr, ToExpr);
- Tree.GetNode(FromInt, ToInt, IsValidFromInt, IsValidToInt);
- PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt,
- FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
- Tree.NodeIsSame());
- return;
- }
- case DiffTree::Declaration: {
- ValueDecl *FromValueDecl, *ToValueDecl;
- bool FromAddressOf, ToAddressOf;
- Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
- PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
- Tree.FromNullPtr(), Tree.ToNullPtr(), Tree.FromDefault(),
- Tree.ToDefault(), Tree.NodeIsSame());
- return;
- }
- case DiffTree::Template: {
- // Node is root of template. Recurse on children.
- TemplateDecl *FromTD, *ToTD;
- Tree.GetNode(FromTD, ToTD);
- if (!Tree.HasChildren()) {
- // If we're dealing with a template specialization with zero
- // arguments, there are no children; special-case this.
- OS << FromTD->getNameAsString() << "<>";
- return;
- }
- Qualifiers FromQual, ToQual;
- Tree.GetNode(FromQual, ToQual);
- PrintQualifiers(FromQual, ToQual);
- OS << FromTD->getNameAsString() << '<';
- Tree.MoveToChild();
- unsigned NumElideArgs = 0;
- do {
- if (ElideType) {
- if (Tree.NodeIsSame()) {
- ++NumElideArgs;
- continue;
- }
- if (NumElideArgs > 0) {
- PrintElideArgs(NumElideArgs, Indent);
- NumElideArgs = 0;
- OS << ", ";
- }
- }
- TreeToString(Indent);
- if (Tree.HasNextSibling())
- OS << ", ";
- } while (Tree.AdvanceSibling());
- if (NumElideArgs > 0)
- PrintElideArgs(NumElideArgs, Indent);
- Tree.Parent();
- OS << ">";
- return;
- }
- }
- }
- // To signal to the text printer that a certain text needs to be bolded,
- // a special character is injected into the character stream which the
- // text printer will later strip out.
- /// Bold - Start bolding text.
- void Bold() {
- assert(!IsBold && "Attempting to bold text that is already bold.");
- IsBold = true;
- if (ShowColor)
- OS << ToggleHighlight;
- }
- /// Unbold - Stop bolding text.
- void Unbold() {
- assert(IsBold && "Attempting to remove bold from unbold text.");
- IsBold = false;
- if (ShowColor)
- OS << ToggleHighlight;
- }
- // Functions to print out the arguments and highlighting the difference.
- /// PrintTypeNames - prints the typenames, bolding differences. Will detect
- /// typenames that are the same and attempt to disambiguate them by using
- /// canonical typenames.
- void PrintTypeNames(QualType FromType, QualType ToType,
- bool FromDefault, bool ToDefault, bool Same) {
- assert((!FromType.isNull() || !ToType.isNull()) &&
- "Only one template argument may be missing.");
- if (Same) {
- OS << FromType.getAsString(Policy);
- return;
- }
- if (!FromType.isNull() && !ToType.isNull() &&
- FromType.getLocalUnqualifiedType() ==
- ToType.getLocalUnqualifiedType()) {
- Qualifiers FromQual = FromType.getLocalQualifiers(),
- ToQual = ToType.getLocalQualifiers();
- PrintQualifiers(FromQual, ToQual);
- FromType.getLocalUnqualifiedType().print(OS, Policy);
- return;
- }
- std::string FromTypeStr = FromType.isNull() ? "(no argument)"
- : FromType.getAsString(Policy);
- std::string ToTypeStr = ToType.isNull() ? "(no argument)"
- : ToType.getAsString(Policy);
- // Switch to canonical typename if it is better.
- // TODO: merge this with other aka printing above.
- if (FromTypeStr == ToTypeStr) {
- std::string FromCanTypeStr =
- FromType.getCanonicalType().getAsString(Policy);
- std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy);
- if (FromCanTypeStr != ToCanTypeStr) {
- FromTypeStr = FromCanTypeStr;
- ToTypeStr = ToCanTypeStr;
- }
- }
- if (PrintTree) OS << '[';
- OS << (FromDefault ? "(default) " : "");
- Bold();
- OS << FromTypeStr;
- Unbold();
- if (PrintTree) {
- OS << " != " << (ToDefault ? "(default) " : "");
- Bold();
- OS << ToTypeStr;
- Unbold();
- OS << "]";
- }
- return;
- }
- /// PrintExpr - Prints out the expr template arguments, highlighting argument
- /// differences.
- void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromNullPtr,
- bool ToNullPtr, bool FromDefault, bool ToDefault, bool Same) {
- assert((FromExpr || ToExpr) &&
- "Only one template argument may be missing.");
- if (Same) {
- PrintExpr(FromExpr, FromNullPtr);
- } else if (!PrintTree) {
- OS << (FromDefault ? "(default) " : "");
- Bold();
- PrintExpr(FromExpr, FromNullPtr);
- Unbold();
- } else {
- OS << (FromDefault ? "[(default) " : "[");
- Bold();
- PrintExpr(FromExpr, FromNullPtr);
- Unbold();
- OS << " != " << (ToDefault ? "(default) " : "");
- Bold();
- PrintExpr(ToExpr, ToNullPtr);
- Unbold();
- OS << ']';
- }
- }
- /// PrintExpr - Actual formatting and printing of expressions.
- void PrintExpr(const Expr *E, bool NullPtr = false) {
- if (E) {
- E->printPretty(OS, nullptr, Policy);
- return;
- }
- if (NullPtr) {
- OS << "nullptr";
- return;
- }
- OS << "(no argument)";
- }
- /// PrintTemplateTemplate - Handles printing of template template arguments,
- /// highlighting argument differences.
- void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,
- bool FromDefault, bool ToDefault, bool Same) {
- assert((FromTD || ToTD) && "Only one template argument may be missing.");
- std::string FromName = FromTD ? FromTD->getName() : "(no argument)";
- std::string ToName = ToTD ? ToTD->getName() : "(no argument)";
- if (FromTD && ToTD && FromName == ToName) {
- FromName = FromTD->getQualifiedNameAsString();
- ToName = ToTD->getQualifiedNameAsString();
- }
- if (Same) {
- OS << "template " << FromTD->getNameAsString();
- } else if (!PrintTree) {
- OS << (FromDefault ? "(default) template " : "template ");
- Bold();
- OS << FromName;
- Unbold();
- } else {
- OS << (FromDefault ? "[(default) template " : "[template ");
- Bold();
- OS << FromName;
- Unbold();
- OS << " != " << (ToDefault ? "(default) template " : "template ");
- Bold();
- OS << ToName;
- Unbold();
- OS << ']';
- }
- }
- /// PrintAPSInt - Handles printing of integral arguments, highlighting
- /// argument differences.
- void PrintAPSInt(llvm::APSInt FromInt, llvm::APSInt ToInt,
- bool IsValidFromInt, bool IsValidToInt, Expr *FromExpr,
- Expr *ToExpr, bool FromDefault, bool ToDefault, bool Same) {
- assert((IsValidFromInt || IsValidToInt) &&
- "Only one integral argument may be missing.");
- if (Same) {
- OS << FromInt.toString(10);
- } else if (!PrintTree) {
- OS << (FromDefault ? "(default) " : "");
- PrintAPSInt(FromInt, FromExpr, IsValidFromInt);
- } else {
- OS << (FromDefault ? "[(default) " : "[");
- PrintAPSInt(FromInt, FromExpr, IsValidFromInt);
- OS << " != " << (ToDefault ? "(default) " : "");
- PrintAPSInt(ToInt, ToExpr, IsValidToInt);
- OS << ']';
- }
- }
- /// PrintAPSInt - If valid, print the APSInt. If the expression is
- /// gives more information, print it too.
- void PrintAPSInt(llvm::APSInt Val, Expr *E, bool Valid) {
- Bold();
- if (Valid) {
- if (HasExtraInfo(E)) {
- PrintExpr(E);
- Unbold();
- OS << " aka ";
- Bold();
- }
- OS << Val.toString(10);
- } else if (E) {
- PrintExpr(E);
- } else {
- OS << "(no argument)";
- }
- Unbold();
- }
- /// HasExtraInfo - Returns true if E is not an integer literal or the
- /// negation of an integer 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;
- return true;
- }
- void PrintValueDecl(ValueDecl *VD, bool AddressOf, bool NullPtr) {
- if (VD) {
- if (AddressOf)
- OS << "&";
- OS << VD->getName();
- return;
- }
- if (NullPtr) {
- 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, bool FromDefault, bool ToDefault,
- bool Same) {
- assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&
- "Only one Decl argument may be NULL");
- if (Same) {
- PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
- } else if (!PrintTree) {
- OS << (FromDefault ? "(default) " : "");
- Bold();
- PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
- Unbold();
- } else {
- OS << (FromDefault ? "[(default) " : "[");
- Bold();
- PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr);
- Unbold();
- OS << " != " << (ToDefault ? "(default) " : "");
- Bold();
- PrintValueDecl(ToValueDecl, ToAddressOf, ToNullPtr);
- 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.
- FromType(PrintFromType ? FromType : ToType),
- ToType(PrintFromType ? ToType : FromType),
- OS(OS),
- IsBold(false) {
- }
- /// DiffTemplate - Start the template type diffing.
- void DiffTemplate() {
- Qualifiers FromQual = FromType.getQualifiers(),
- ToQual = ToType.getQualifiers();
- const TemplateSpecializationType *FromOrigTST =
- GetTemplateSpecializationType(Context, FromType);
- const TemplateSpecializationType *ToOrigTST =
- GetTemplateSpecializationType(Context, ToType);
- // 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();
- Tree.SetNode(FromType, ToType);
- Tree.SetNode(FromQual, ToQual);
- Tree.SetKind(DiffTree::Template);
- // Same base template, but different arguments.
- Tree.SetNode(FromOrigTST->getTemplateName().getAsTemplateDecl(),
- ToOrigTST->getTemplateName().getAsTemplateDecl());
- 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 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();
- }
|