1//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements a diagnostic formatting hook for AST elements.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/ASTDiagnostic.h"
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/ASTLambda.h"
16#include "clang/AST/Attr.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/DeclTemplate.h"
19#include "clang/AST/ExprCXX.h"
20#include "clang/AST/TemplateBase.h"
21#include "clang/AST/Type.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/raw_ostream.h"
24
25using namespace clang;
26
27// Returns a desugared version of the QualType, and marks ShouldAKA as true
28// whenever we remove significant sugar from the type. Make sure ShouldAKA
29// is initialized before passing it in.
30QualType clang::desugarForDiagnostic(ASTContext &Context, QualType QT,
31 bool &ShouldAKA) {
32 QualifierCollector QC;
33
34 while (true) {
35 const Type *Ty = QC.strip(type: QT);
36
37 // Don't aka just because we saw an elaborated type...
38 if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(Val: Ty)) {
39 QT = ET->desugar();
40 continue;
41 }
42 // ... or a using type ...
43 if (const UsingType *UT = dyn_cast<UsingType>(Val: Ty)) {
44 QT = UT->desugar();
45 continue;
46 }
47 // ... or a paren type ...
48 if (const ParenType *PT = dyn_cast<ParenType>(Val: Ty)) {
49 QT = PT->desugar();
50 continue;
51 }
52 // ... or a macro defined type ...
53 if (const MacroQualifiedType *MDT = dyn_cast<MacroQualifiedType>(Val: Ty)) {
54 QT = MDT->desugar();
55 continue;
56 }
57 // ...or a substituted template type parameter ...
58 if (const SubstTemplateTypeParmType *ST =
59 dyn_cast<SubstTemplateTypeParmType>(Val: Ty)) {
60 QT = ST->desugar();
61 continue;
62 }
63 // ...or an attributed type...
64 if (const AttributedType *AT = dyn_cast<AttributedType>(Val: Ty)) {
65 QT = AT->desugar();
66 continue;
67 }
68 // ...or an adjusted type...
69 if (const AdjustedType *AT = dyn_cast<AdjustedType>(Val: Ty)) {
70 QT = AT->desugar();
71 continue;
72 }
73 // ... or an auto type.
74 if (const AutoType *AT = dyn_cast<AutoType>(Val: Ty)) {
75 if (!AT->isSugared())
76 break;
77 QT = AT->desugar();
78 continue;
79 }
80
81 // Desugar FunctionType if return type or any parameter type should be
82 // desugared. Preserve nullability attribute on desugared types.
83 if (const FunctionType *FT = dyn_cast<FunctionType>(Val: Ty)) {
84 bool DesugarReturn = false;
85 QualType SugarRT = FT->getReturnType();
86 QualType RT = desugarForDiagnostic(Context, QT: SugarRT, ShouldAKA&: DesugarReturn);
87 if (auto nullability = AttributedType::stripOuterNullability(T&: SugarRT)) {
88 RT = Context.getAttributedType(
89 attrKind: AttributedType::getNullabilityAttrKind(kind: *nullability), modifiedType: RT, equivalentType: RT);
90 }
91
92 bool DesugarArgument = false;
93 SmallVector<QualType, 4> Args;
94 const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(Val: FT);
95 if (FPT) {
96 for (QualType SugarPT : FPT->param_types()) {
97 QualType PT = desugarForDiagnostic(Context, QT: SugarPT, ShouldAKA&: DesugarArgument);
98 if (auto nullability =
99 AttributedType::stripOuterNullability(T&: SugarPT)) {
100 PT = Context.getAttributedType(
101 attrKind: AttributedType::getNullabilityAttrKind(kind: *nullability), modifiedType: PT, equivalentType: PT);
102 }
103 Args.push_back(Elt: PT);
104 }
105 }
106
107 if (DesugarReturn || DesugarArgument) {
108 ShouldAKA = true;
109 QT = FPT ? Context.getFunctionType(ResultTy: RT, Args, EPI: FPT->getExtProtoInfo())
110 : Context.getFunctionNoProtoType(ResultTy: RT, Info: FT->getExtInfo());
111 break;
112 }
113 }
114
115 // Desugar template specializations if any template argument should be
116 // desugared.
117 if (const TemplateSpecializationType *TST =
118 dyn_cast<TemplateSpecializationType>(Val: Ty)) {
119 if (!TST->isTypeAlias()) {
120 bool DesugarArgument = false;
121 SmallVector<TemplateArgument, 4> Args;
122 for (const TemplateArgument &Arg : TST->template_arguments()) {
123 if (Arg.getKind() == TemplateArgument::Type)
124 Args.push_back(Elt: desugarForDiagnostic(Context, QT: Arg.getAsType(),
125 ShouldAKA&: DesugarArgument));
126 else
127 Args.push_back(Elt: Arg);
128 }
129
130 if (DesugarArgument) {
131 ShouldAKA = true;
132 QT = Context.getTemplateSpecializationType(
133 T: TST->getTemplateName(), Args, Canon: QT);
134 }
135 break;
136 }
137 }
138
139 if (const auto *AT = dyn_cast<ArrayType>(Val: Ty)) {
140 QualType ElementTy =
141 desugarForDiagnostic(Context, QT: AT->getElementType(), ShouldAKA);
142 if (const auto *CAT = dyn_cast<ConstantArrayType>(Val: AT))
143 QT = Context.getConstantArrayType(
144 EltTy: ElementTy, ArySize: CAT->getSize(), SizeExpr: CAT->getSizeExpr(),
145 ASM: CAT->getSizeModifier(), IndexTypeQuals: CAT->getIndexTypeCVRQualifiers());
146 else if (const auto *VAT = dyn_cast<VariableArrayType>(Val: AT))
147 QT = Context.getVariableArrayType(
148 EltTy: ElementTy, NumElts: VAT->getSizeExpr(), ASM: VAT->getSizeModifier(),
149 IndexTypeQuals: VAT->getIndexTypeCVRQualifiers(), Brackets: VAT->getBracketsRange());
150 else if (const auto *DSAT = dyn_cast<DependentSizedArrayType>(Val: AT))
151 QT = Context.getDependentSizedArrayType(
152 EltTy: ElementTy, NumElts: DSAT->getSizeExpr(), ASM: DSAT->getSizeModifier(),
153 IndexTypeQuals: DSAT->getIndexTypeCVRQualifiers(), Brackets: DSAT->getBracketsRange());
154 else if (const auto *IAT = dyn_cast<IncompleteArrayType>(Val: AT))
155 QT = Context.getIncompleteArrayType(EltTy: ElementTy, ASM: IAT->getSizeModifier(),
156 IndexTypeQuals: IAT->getIndexTypeCVRQualifiers());
157 else
158 llvm_unreachable("Unhandled array type");
159 break;
160 }
161
162 // Don't desugar magic Objective-C types.
163 if (QualType(Ty,0) == Context.getObjCIdType() ||
164 QualType(Ty,0) == Context.getObjCClassType() ||
165 QualType(Ty,0) == Context.getObjCSelType() ||
166 QualType(Ty,0) == Context.getObjCProtoType())
167 break;
168
169 // Don't desugar va_list.
170 if (QualType(Ty, 0) == Context.getBuiltinVaListType() ||
171 QualType(Ty, 0) == Context.getBuiltinMSVaListType())
172 break;
173
174 // Otherwise, do a single-step desugar.
175 QualType Underlying;
176 bool IsSugar = false;
177 switch (Ty->getTypeClass()) {
178#define ABSTRACT_TYPE(Class, Base)
179#define TYPE(Class, Base) \
180case Type::Class: { \
181const Class##Type *CTy = cast<Class##Type>(Ty); \
182if (CTy->isSugared()) { \
183IsSugar = true; \
184Underlying = CTy->desugar(); \
185} \
186break; \
187}
188#include "clang/AST/TypeNodes.inc"
189 }
190
191 // If it wasn't sugared, we're done.
192 if (!IsSugar)
193 break;
194
195 // If the desugared type is a vector type, we don't want to expand
196 // it, it will turn into an attribute mess. People want their "vec4".
197 if (isa<VectorType>(Val: Underlying))
198 break;
199
200 // Don't desugar through the primary typedef of an anonymous type.
201 if (const TagType *UTT = Underlying->getAs<TagType>())
202 if (const TypedefType *QTT = dyn_cast<TypedefType>(Val&: QT))
203 if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
204 break;
205
206 // Record that we actually looked through an opaque type here.
207 ShouldAKA = true;
208 QT = Underlying;
209 }
210
211 // If we have a pointer-like type, desugar the pointee as well.
212 // FIXME: Handle other pointer-like types.
213 if (const PointerType *Ty = QT->getAs<PointerType>()) {
214 QT = Context.getPointerType(
215 T: desugarForDiagnostic(Context, QT: Ty->getPointeeType(), ShouldAKA));
216 } else if (const auto *Ty = QT->getAs<ObjCObjectPointerType>()) {
217 QT = Context.getObjCObjectPointerType(
218 OIT: desugarForDiagnostic(Context, QT: Ty->getPointeeType(), ShouldAKA));
219 } else if (const LValueReferenceType *Ty = QT->getAs<LValueReferenceType>()) {
220 QT = Context.getLValueReferenceType(
221 T: desugarForDiagnostic(Context, QT: Ty->getPointeeType(), ShouldAKA));
222 } else if (const RValueReferenceType *Ty = QT->getAs<RValueReferenceType>()) {
223 QT = Context.getRValueReferenceType(
224 T: desugarForDiagnostic(Context, QT: Ty->getPointeeType(), ShouldAKA));
225 } else if (const auto *Ty = QT->getAs<ObjCObjectType>()) {
226 if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {
227 QualType BaseType =
228 desugarForDiagnostic(Context, QT: Ty->getBaseType(), ShouldAKA);
229 QT = Context.getObjCObjectType(
230 Base: BaseType, typeArgs: Ty->getTypeArgsAsWritten(),
231 protocols: llvm::ArrayRef(Ty->qual_begin(), Ty->getNumProtocols()),
232 isKindOf: Ty->isKindOfTypeAsWritten());
233 }
234 }
235
236 return QC.apply(Context, QT);
237}
238
239/// Convert the given type to a string suitable for printing as part of
240/// a diagnostic.
241///
242/// There are four main criteria when determining whether we should have an
243/// a.k.a. clause when pretty-printing a type:
244///
245/// 1) Some types provide very minimal sugar that doesn't impede the
246/// user's understanding --- for example, elaborated type
247/// specifiers. If this is all the sugar we see, we don't want an
248/// a.k.a. clause.
249/// 2) Some types are technically sugared but are much more familiar
250/// when seen in their sugared form --- for example, va_list,
251/// vector types, and the magic Objective C types. We don't
252/// want to desugar these, even if we do produce an a.k.a. clause.
253/// 3) Some types may have already been desugared previously in this diagnostic.
254/// if this is the case, doing another "aka" would just be clutter.
255/// 4) Two different types within the same diagnostic have the same output
256/// string. In this case, force an a.k.a with the desugared type when
257/// doing so will provide additional information.
258///
259/// \param Context the context in which the type was allocated
260/// \param Ty the type to print
261/// \param QualTypeVals pointer values to QualTypes which are used in the
262/// diagnostic message
263static std::string
264ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty,
265 ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
266 ArrayRef<intptr_t> QualTypeVals) {
267 // FIXME: Playing with std::string is really slow.
268 bool ForceAKA = false;
269 QualType CanTy = Ty.getCanonicalType();
270 std::string S = Ty.getAsString(Policy: Context.getPrintingPolicy());
271 std::string CanS = CanTy.getAsString(Policy: Context.getPrintingPolicy());
272
273 for (const intptr_t &QualTypeVal : QualTypeVals) {
274 QualType CompareTy =
275 QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void *>(QualTypeVal));
276 if (CompareTy.isNull())
277 continue;
278 if (CompareTy == Ty)
279 continue; // Same types
280 QualType CompareCanTy = CompareTy.getCanonicalType();
281 if (CompareCanTy == CanTy)
282 continue; // Same canonical types
283 std::string CompareS = CompareTy.getAsString(Policy: Context.getPrintingPolicy());
284 bool ShouldAKA = false;
285 QualType CompareDesugar =
286 desugarForDiagnostic(Context, QT: CompareTy, ShouldAKA);
287 std::string CompareDesugarStr =
288 CompareDesugar.getAsString(Policy: Context.getPrintingPolicy());
289 if (CompareS != S && CompareDesugarStr != S)
290 continue; // The type string is different than the comparison string
291 // and the desugared comparison string.
292 std::string CompareCanS =
293 CompareCanTy.getAsString(Policy: Context.getPrintingPolicy());
294
295 if (CompareCanS == CanS)
296 continue; // No new info from canonical type
297
298 ForceAKA = true;
299 break;
300 }
301
302 // Check to see if we already desugared this type in this
303 // diagnostic. If so, don't do it again.
304 bool Repeated = false;
305 for (const auto &PrevArg : PrevArgs) {
306 // TODO: Handle ak_declcontext case.
307 if (PrevArg.first == DiagnosticsEngine::ak_qualtype) {
308 QualType PrevTy(
309 QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void *>(PrevArg.second)));
310 if (PrevTy == Ty) {
311 Repeated = true;
312 break;
313 }
314 }
315 }
316
317 // Consider producing an a.k.a. clause if removing all the direct
318 // sugar gives us something "significantly different".
319 if (!Repeated) {
320 bool ShouldAKA = false;
321 QualType DesugaredTy = desugarForDiagnostic(Context, QT: Ty, ShouldAKA);
322 if (ShouldAKA || ForceAKA) {
323 if (DesugaredTy == Ty) {
324 DesugaredTy = Ty.getCanonicalType();
325 }
326 std::string akaStr = DesugaredTy.getAsString(Policy: Context.getPrintingPolicy());
327 if (akaStr != S) {
328 S = "'" + S + "' (aka '" + akaStr + "')";
329 return S;
330 }
331 }
332
333 // Give some additional info on vector types. These are either not desugared
334 // or displaying complex __attribute__ expressions so add details of the
335 // type and element count.
336 if (const auto *VTy = Ty->getAs<VectorType>()) {
337 std::string DecoratedString;
338 llvm::raw_string_ostream OS(DecoratedString);
339 const char *Values = VTy->getNumElements() > 1 ? "values" : "value";
340 OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '"
341 << VTy->getElementType().getAsString(Policy: Context.getPrintingPolicy())
342 << "' " << Values << ")";
343 return DecoratedString;
344 }
345 }
346
347 S = "'" + S + "'";
348 return S;
349}
350
351static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
352 QualType ToType, bool PrintTree,
353 bool PrintFromType, bool ElideType,
354 bool ShowColors, raw_ostream &OS);
355
356void clang::FormatASTNodeDiagnosticArgument(
357 DiagnosticsEngine::ArgumentKind Kind,
358 intptr_t Val,
359 StringRef Modifier,
360 StringRef Argument,
361 ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs,
362 SmallVectorImpl<char> &Output,
363 void *Cookie,
364 ArrayRef<intptr_t> QualTypeVals) {
365 ASTContext &Context = *static_cast<ASTContext*>(Cookie);
366
367 size_t OldEnd = Output.size();
368 llvm::raw_svector_ostream OS(Output);
369 bool NeedQuotes = true;
370
371 switch (Kind) {
372 default: llvm_unreachable("unknown ArgumentKind");
373 case DiagnosticsEngine::ak_addrspace: {
374 assert(Modifier.empty() && Argument.empty() &&
375 "Invalid modifier for Qualifiers argument");
376
377 auto S = Qualifiers::getAddrSpaceAsString(AS: static_cast<LangAS>(Val));
378 if (S.empty()) {
379 OS << (Context.getLangOpts().OpenCL ? "default" : "generic");
380 OS << " address space";
381 } else {
382 OS << "address space";
383 OS << " '" << S << "'";
384 }
385 NeedQuotes = false;
386 break;
387 }
388 case DiagnosticsEngine::ak_qual: {
389 assert(Modifier.empty() && Argument.empty() &&
390 "Invalid modifier for Qualifiers argument");
391
392 Qualifiers Q(Qualifiers::fromOpaqueValue(opaque: Val));
393 auto S = Q.getAsString();
394 if (S.empty()) {
395 OS << "unqualified";
396 NeedQuotes = false;
397 } else {
398 OS << S;
399 }
400 break;
401 }
402 case DiagnosticsEngine::ak_qualtype_pair: {
403 TemplateDiffTypes &TDT = *reinterpret_cast<TemplateDiffTypes*>(Val);
404 QualType FromType =
405 QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void*>(TDT.FromType));
406 QualType ToType =
407 QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void*>(TDT.ToType));
408
409 if (FormatTemplateTypeDiff(Context, FromType, ToType, PrintTree: TDT.PrintTree,
410 PrintFromType: TDT.PrintFromType, ElideType: TDT.ElideType,
411 ShowColors: TDT.ShowColors, OS)) {
412 NeedQuotes = !TDT.PrintTree;
413 TDT.TemplateDiffUsed = true;
414 break;
415 }
416
417 // Don't fall-back during tree printing. The caller will handle
418 // this case.
419 if (TDT.PrintTree)
420 return;
421
422 // Attempting to do a template diff on non-templates. Set the variables
423 // and continue with regular type printing of the appropriate type.
424 Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType;
425 Modifier = StringRef();
426 Argument = StringRef();
427 // Fall through
428 [[fallthrough]];
429 }
430 case DiagnosticsEngine::ak_qualtype: {
431 assert(Modifier.empty() && Argument.empty() &&
432 "Invalid modifier for QualType argument");
433
434 QualType Ty(QualType::getFromOpaquePtr(Ptr: reinterpret_cast<void*>(Val)));
435 OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals);
436 NeedQuotes = false;
437 break;
438 }
439 case DiagnosticsEngine::ak_declarationname: {
440 if (Modifier == "objcclass" && Argument.empty())
441 OS << '+';
442 else if (Modifier == "objcinstance" && Argument.empty())
443 OS << '-';
444 else
445 assert(Modifier.empty() && Argument.empty() &&
446 "Invalid modifier for DeclarationName argument");
447
448 OS << DeclarationName::getFromOpaqueInteger(P: Val);
449 break;
450 }
451 case DiagnosticsEngine::ak_nameddecl: {
452 bool Qualified;
453 if (Modifier == "q" && Argument.empty())
454 Qualified = true;
455 else {
456 assert(Modifier.empty() && Argument.empty() &&
457 "Invalid modifier for NamedDecl* argument");
458 Qualified = false;
459 }
460 const NamedDecl *ND = reinterpret_cast<const NamedDecl*>(Val);
461 ND->getNameForDiagnostic(OS, Policy: Context.getPrintingPolicy(), Qualified);
462 break;
463 }
464 case DiagnosticsEngine::ak_nestednamespec: {
465 NestedNameSpecifier *NNS = reinterpret_cast<NestedNameSpecifier*>(Val);
466 NNS->print(OS, Policy: Context.getPrintingPolicy());
467 NeedQuotes = false;
468 break;
469 }
470 case DiagnosticsEngine::ak_declcontext: {
471 DeclContext *DC = reinterpret_cast<DeclContext *> (Val);
472 assert(DC && "Should never have a null declaration context");
473 NeedQuotes = false;
474
475 // FIXME: Get the strings for DeclContext from some localized place
476 if (DC->isTranslationUnit()) {
477 if (Context.getLangOpts().CPlusPlus)
478 OS << "the global namespace";
479 else
480 OS << "the global scope";
481 } else if (DC->isClosure()) {
482 OS << "block literal";
483 } else if (isLambdaCallOperator(DC)) {
484 OS << "lambda expression";
485 } else if (TypeDecl *Type = dyn_cast<TypeDecl>(Val: DC)) {
486 OS << ConvertTypeToDiagnosticString(Context,
487 Ty: Context.getTypeDeclType(Decl: Type),
488 PrevArgs, QualTypeVals);
489 } else {
490 assert(isa<NamedDecl>(DC) && "Expected a NamedDecl");
491 NamedDecl *ND = cast<NamedDecl>(Val: DC);
492 if (isa<NamespaceDecl>(Val: ND))
493 OS << "namespace ";
494 else if (isa<ObjCMethodDecl>(Val: ND))
495 OS << "method ";
496 else if (isa<FunctionDecl>(Val: ND))
497 OS << "function ";
498
499 OS << '\'';
500 ND->getNameForDiagnostic(OS, Policy: Context.getPrintingPolicy(), Qualified: true);
501 OS << '\'';
502 }
503 break;
504 }
505 case DiagnosticsEngine::ak_attr: {
506 const Attr *At = reinterpret_cast<Attr *>(Val);
507 assert(At && "Received null Attr object!");
508 OS << '\'' << At->getSpelling() << '\'';
509 NeedQuotes = false;
510 break;
511 }
512 }
513
514 if (NeedQuotes) {
515 Output.insert(I: Output.begin()+OldEnd, Elt: '\'');
516 Output.push_back(Elt: '\'');
517 }
518}
519
520/// TemplateDiff - A class that constructs a pretty string for a pair of
521/// QualTypes. For the pair of types, a diff tree will be created containing
522/// all the information about the templates and template arguments. Afterwards,
523/// the tree is transformed to a string according to the options passed in.
524namespace {
525class TemplateDiff {
526 /// Context - The ASTContext which is used for comparing template arguments.
527 ASTContext &Context;
528
529 /// Policy - Used during expression printing.
530 PrintingPolicy Policy;
531
532 /// ElideType - Option to elide identical types.
533 bool ElideType;
534
535 /// PrintTree - Format output string as a tree.
536 bool PrintTree;
537
538 /// ShowColor - Diagnostics support color, so bolding will be used.
539 bool ShowColor;
540
541 /// FromTemplateType - When single type printing is selected, this is the
542 /// type to be printed. When tree printing is selected, this type will
543 /// show up first in the tree.
544 QualType FromTemplateType;
545
546 /// ToTemplateType - The type that FromType is compared to. Only in tree
547 /// printing will this type be outputed.
548 QualType ToTemplateType;
549
550 /// OS - The stream used to construct the output strings.
551 raw_ostream &OS;
552
553 /// IsBold - Keeps track of the bold formatting for the output string.
554 bool IsBold;
555
556 /// DiffTree - A tree representation the differences between two types.
557 class DiffTree {
558 public:
559 /// DiffKind - The difference in a DiffNode. Fields of
560 /// TemplateArgumentInfo needed by each difference can be found in the
561 /// Set* and Get* functions.
562 enum DiffKind {
563 /// Incomplete or invalid node.
564 Invalid,
565 /// Another level of templates
566 Template,
567 /// Type difference, all type differences except those falling under
568 /// the Template difference.
569 Type,
570 /// Expression difference, this is only when both arguments are
571 /// expressions. If one argument is an expression and the other is
572 /// Integer or Declaration, then use that diff type instead.
573 Expression,
574 /// Template argument difference
575 TemplateTemplate,
576 /// Integer difference
577 Integer,
578 /// Declaration difference, nullptr arguments are included here
579 Declaration,
580 /// One argument being integer and the other being declaration
581 FromIntegerAndToDeclaration,
582 FromDeclarationAndToInteger
583 };
584
585 private:
586 /// TemplateArgumentInfo - All the information needed to pretty print
587 /// a template argument. See the Set* and Get* functions to see which
588 /// fields are used for each DiffKind.
589 struct TemplateArgumentInfo {
590 QualType ArgType;
591 Qualifiers Qual;
592 llvm::APSInt Val;
593 bool IsValidInt = false;
594 Expr *ArgExpr = nullptr;
595 TemplateDecl *TD = nullptr;
596 ValueDecl *VD = nullptr;
597 bool NeedAddressOf = false;
598 bool IsNullPtr = false;
599 bool IsDefault = false;
600 };
601
602 /// DiffNode - The root node stores the original type. Each child node
603 /// stores template arguments of their parents. For templated types, the
604 /// template decl is also stored.
605 struct DiffNode {
606 DiffKind Kind = Invalid;
607
608 /// NextNode - The index of the next sibling node or 0.
609 unsigned NextNode = 0;
610
611 /// ChildNode - The index of the first child node or 0.
612 unsigned ChildNode = 0;
613
614 /// ParentNode - The index of the parent node.
615 unsigned ParentNode = 0;
616
617 TemplateArgumentInfo FromArgInfo, ToArgInfo;
618
619 /// Same - Whether the two arguments evaluate to the same value.
620 bool Same = false;
621
622 DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {}
623 };
624
625 /// FlatTree - A flattened tree used to store the DiffNodes.
626 SmallVector<DiffNode, 16> FlatTree;
627
628 /// CurrentNode - The index of the current node being used.
629 unsigned CurrentNode;
630
631 /// NextFreeNode - The index of the next unused node. Used when creating
632 /// child nodes.
633 unsigned NextFreeNode;
634
635 /// ReadNode - The index of the current node being read.
636 unsigned ReadNode;
637
638 public:
639 DiffTree() : CurrentNode(0), NextFreeNode(1), ReadNode(0) {
640 FlatTree.push_back(Elt: DiffNode());
641 }
642
643 // Node writing functions, one for each valid DiffKind element.
644 void SetTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,
645 Qualifiers FromQual, Qualifiers ToQual,
646 bool FromDefault, bool ToDefault) {
647 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
648 FlatTree[CurrentNode].Kind = Template;
649 FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
650 FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
651 FlatTree[CurrentNode].FromArgInfo.Qual = FromQual;
652 FlatTree[CurrentNode].ToArgInfo.Qual = ToQual;
653 SetDefault(FromDefault, ToDefault);
654 }
655
656 void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault,
657 bool ToDefault) {
658 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
659 FlatTree[CurrentNode].Kind = Type;
660 FlatTree[CurrentNode].FromArgInfo.ArgType = FromType;
661 FlatTree[CurrentNode].ToArgInfo.ArgType = ToType;
662 SetDefault(FromDefault, ToDefault);
663 }
664
665 void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault,
666 bool ToDefault) {
667 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
668 FlatTree[CurrentNode].Kind = Expression;
669 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
670 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
671 SetDefault(FromDefault, ToDefault);
672 }
673
674 void SetTemplateTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,
675 bool FromDefault, bool ToDefault) {
676 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
677 FlatTree[CurrentNode].Kind = TemplateTemplate;
678 FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
679 FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
680 SetDefault(FromDefault, ToDefault);
681 }
682
683 void SetIntegerDiff(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
684 bool IsValidFromInt, bool IsValidToInt,
685 QualType FromIntType, QualType ToIntType,
686 Expr *FromExpr, Expr *ToExpr, bool FromDefault,
687 bool ToDefault) {
688 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
689 FlatTree[CurrentNode].Kind = Integer;
690 FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
691 FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
692 FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
693 FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
694 FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
695 FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
696 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
697 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
698 SetDefault(FromDefault, ToDefault);
699 }
700
701 void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
702 bool FromAddressOf, bool ToAddressOf,
703 bool FromNullPtr, bool ToNullPtr, Expr *FromExpr,
704 Expr *ToExpr, bool FromDefault, bool ToDefault) {
705 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
706 FlatTree[CurrentNode].Kind = Declaration;
707 FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
708 FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
709 FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
710 FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
711 FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
712 FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
713 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
714 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
715 SetDefault(FromDefault, ToDefault);
716 }
717
718 void SetFromDeclarationAndToIntegerDiff(
719 ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr,
720 Expr *FromExpr, const llvm::APSInt &ToInt, bool IsValidToInt,
721 QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) {
722 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
723 FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger;
724 FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
725 FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
726 FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
727 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
728 FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
729 FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
730 FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
731 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
732 SetDefault(FromDefault, ToDefault);
733 }
734
735 void SetFromIntegerAndToDeclarationDiff(
736 const llvm::APSInt &FromInt, bool IsValidFromInt, QualType FromIntType,
737 Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf,
738 bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) {
739 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
740 FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration;
741 FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
742 FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
743 FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
744 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
745 FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
746 FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
747 FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
748 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
749 SetDefault(FromDefault, ToDefault);
750 }
751
752 /// SetDefault - Sets FromDefault and ToDefault flags of the current node.
753 void SetDefault(bool FromDefault, bool ToDefault) {
754 assert((!FromDefault || !ToDefault) && "Both arguments cannot be default.");
755 FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault;
756 FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault;
757 }
758
759 /// SetSame - Sets the same flag of the current node.
760 void SetSame(bool Same) {
761 FlatTree[CurrentNode].Same = Same;
762 }
763
764 /// SetKind - Sets the current node's type.
765 void SetKind(DiffKind Kind) {
766 FlatTree[CurrentNode].Kind = Kind;
767 }
768
769 /// Up - Changes the node to the parent of the current node.
770 void Up() {
771 assert(FlatTree[CurrentNode].Kind != Invalid &&
772 "Cannot exit node before setting node information.");
773 CurrentNode = FlatTree[CurrentNode].ParentNode;
774 }
775
776 /// AddNode - Adds a child node to the current node, then sets that node
777 /// node as the current node.
778 void AddNode() {
779 assert(FlatTree[CurrentNode].Kind == Template &&
780 "Only Template nodes can have children nodes.");
781 FlatTree.push_back(Elt: DiffNode(CurrentNode));
782 DiffNode &Node = FlatTree[CurrentNode];
783 if (Node.ChildNode == 0) {
784 // If a child node doesn't exist, add one.
785 Node.ChildNode = NextFreeNode;
786 } else {
787 // If a child node exists, find the last child node and add a
788 // next node to it.
789 unsigned i;
790 for (i = Node.ChildNode; FlatTree[i].NextNode != 0;
791 i = FlatTree[i].NextNode) {
792 }
793 FlatTree[i].NextNode = NextFreeNode;
794 }
795 CurrentNode = NextFreeNode;
796 ++NextFreeNode;
797 }
798
799 // Node reading functions.
800 /// StartTraverse - Prepares the tree for recursive traversal.
801 void StartTraverse() {
802 ReadNode = 0;
803 CurrentNode = NextFreeNode;
804 NextFreeNode = 0;
805 }
806
807 /// Parent - Move the current read node to its parent.
808 void Parent() {
809 ReadNode = FlatTree[ReadNode].ParentNode;
810 }
811
812 void GetTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD,
813 Qualifiers &FromQual, Qualifiers &ToQual) {
814 assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind.");
815 FromTD = FlatTree[ReadNode].FromArgInfo.TD;
816 ToTD = FlatTree[ReadNode].ToArgInfo.TD;
817 FromQual = FlatTree[ReadNode].FromArgInfo.Qual;
818 ToQual = FlatTree[ReadNode].ToArgInfo.Qual;
819 }
820
821 void GetTypeDiff(QualType &FromType, QualType &ToType) {
822 assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind");
823 FromType = FlatTree[ReadNode].FromArgInfo.ArgType;
824 ToType = FlatTree[ReadNode].ToArgInfo.ArgType;
825 }
826
827 void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) {
828 assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind");
829 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
830 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
831 }
832
833 void GetTemplateTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {
834 assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind.");
835 FromTD = FlatTree[ReadNode].FromArgInfo.TD;
836 ToTD = FlatTree[ReadNode].ToArgInfo.TD;
837 }
838
839 void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
840 bool &IsValidFromInt, bool &IsValidToInt,
841 QualType &FromIntType, QualType &ToIntType,
842 Expr *&FromExpr, Expr *&ToExpr) {
843 assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind.");
844 FromInt = FlatTree[ReadNode].FromArgInfo.Val;
845 ToInt = FlatTree[ReadNode].ToArgInfo.Val;
846 IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
847 IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
848 FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
849 ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
850 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
851 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
852 }
853
854 void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
855 bool &FromAddressOf, bool &ToAddressOf,
856 bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr,
857 Expr *&ToExpr) {
858 assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind.");
859 FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
860 ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
861 FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
862 ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
863 FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
864 ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
865 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
866 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
867 }
868
869 void GetFromDeclarationAndToIntegerDiff(
870 ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr,
871 Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt,
872 QualType &ToIntType, Expr *&ToExpr) {
873 assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger &&
874 "Unexpected kind.");
875 FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
876 FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
877 FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
878 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
879 ToInt = FlatTree[ReadNode].ToArgInfo.Val;
880 IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
881 ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
882 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
883 }
884
885 void GetFromIntegerAndToDeclarationDiff(
886 llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType,
887 Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf,
888 bool &ToNullPtr, Expr *&ToExpr) {
889 assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration &&
890 "Unexpected kind.");
891 FromInt = FlatTree[ReadNode].FromArgInfo.Val;
892 IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
893 FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
894 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
895 ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
896 ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
897 ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
898 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
899 }
900
901 /// FromDefault - Return true if the from argument is the default.
902 bool FromDefault() {
903 return FlatTree[ReadNode].FromArgInfo.IsDefault;
904 }
905
906 /// ToDefault - Return true if the to argument is the default.
907 bool ToDefault() {
908 return FlatTree[ReadNode].ToArgInfo.IsDefault;
909 }
910
911 /// NodeIsSame - Returns true the arguments are the same.
912 bool NodeIsSame() {
913 return FlatTree[ReadNode].Same;
914 }
915
916 /// HasChildrend - Returns true if the node has children.
917 bool HasChildren() {
918 return FlatTree[ReadNode].ChildNode != 0;
919 }
920
921 /// MoveToChild - Moves from the current node to its child.
922 void MoveToChild() {
923 ReadNode = FlatTree[ReadNode].ChildNode;
924 }
925
926 /// AdvanceSibling - If there is a next sibling, advance to it and return
927 /// true. Otherwise, return false.
928 bool AdvanceSibling() {
929 if (FlatTree[ReadNode].NextNode == 0)
930 return false;
931
932 ReadNode = FlatTree[ReadNode].NextNode;
933 return true;
934 }
935
936 /// HasNextSibling - Return true if the node has a next sibling.
937 bool HasNextSibling() {
938 return FlatTree[ReadNode].NextNode != 0;
939 }
940
941 /// Empty - Returns true if the tree has no information.
942 bool Empty() {
943 return GetKind() == Invalid;
944 }
945
946 /// GetKind - Returns the current node's type.
947 DiffKind GetKind() {
948 return FlatTree[ReadNode].Kind;
949 }
950 };
951
952 DiffTree Tree;
953
954 /// TSTiterator - a pair of iterators that walks the
955 /// TemplateSpecializationType and the desugared TemplateSpecializationType.
956 /// The deseguared TemplateArgument should provide the canonical argument
957 /// for comparisons.
958 class TSTiterator {
959 typedef const TemplateArgument& reference;
960 typedef const TemplateArgument* pointer;
961
962 /// InternalIterator - an iterator that is used to enter a
963 /// TemplateSpecializationType and read TemplateArguments inside template
964 /// parameter packs in order with the rest of the TemplateArguments.
965 struct InternalIterator {
966 /// TST - the template specialization whose arguments this iterator
967 /// traverse over.
968 const TemplateSpecializationType *TST;
969
970 /// Index - the index of the template argument in TST.
971 unsigned Index;
972
973 /// CurrentTA - if CurrentTA is not the same as EndTA, then CurrentTA
974 /// points to a TemplateArgument within a parameter pack.
975 TemplateArgument::pack_iterator CurrentTA;
976
977 /// EndTA - the end iterator of a parameter pack
978 TemplateArgument::pack_iterator EndTA;
979
980 /// InternalIterator - Constructs an iterator and sets it to the first
981 /// template argument.
982 InternalIterator(const TemplateSpecializationType *TST)
983 : TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) {
984 if (!TST) return;
985
986 if (isEnd()) return;
987
988 // Set to first template argument. If not a parameter pack, done.
989 TemplateArgument TA = TST->template_arguments()[0];
990 if (TA.getKind() != TemplateArgument::Pack) return;
991
992 // Start looking into the parameter pack.
993 CurrentTA = TA.pack_begin();
994 EndTA = TA.pack_end();
995
996 // Found a valid template argument.
997 if (CurrentTA != EndTA) return;
998
999 // Parameter pack is empty, use the increment to get to a valid
1000 // template argument.
1001 ++(*this);
1002 }
1003
1004 /// Return true if the iterator is non-singular.
1005 bool isValid() const { return TST; }
1006
1007 /// isEnd - Returns true if the iterator is one past the end.
1008 bool isEnd() const {
1009 assert(TST && "InternalIterator is invalid with a null TST.");
1010 return Index >= TST->template_arguments().size();
1011 }
1012
1013 /// &operator++ - Increment the iterator to the next template argument.
1014 InternalIterator &operator++() {
1015 assert(TST && "InternalIterator is invalid with a null TST.");
1016 if (isEnd()) {
1017 return *this;
1018 }
1019
1020 // If in a parameter pack, advance in the parameter pack.
1021 if (CurrentTA != EndTA) {
1022 ++CurrentTA;
1023 if (CurrentTA != EndTA)
1024 return *this;
1025 }
1026
1027 // Loop until a template argument is found, or the end is reached.
1028 while (true) {
1029 // Advance to the next template argument. Break if reached the end.
1030 if (++Index == TST->template_arguments().size())
1031 break;
1032
1033 // If the TemplateArgument is not a parameter pack, done.
1034 TemplateArgument TA = TST->template_arguments()[Index];
1035 if (TA.getKind() != TemplateArgument::Pack)
1036 break;
1037
1038 // Handle parameter packs.
1039 CurrentTA = TA.pack_begin();
1040 EndTA = TA.pack_end();
1041
1042 // If the parameter pack is empty, try to advance again.
1043 if (CurrentTA != EndTA)
1044 break;
1045 }
1046 return *this;
1047 }
1048
1049 /// operator* - Returns the appropriate TemplateArgument.
1050 reference operator*() const {
1051 assert(TST && "InternalIterator is invalid with a null TST.");
1052 assert(!isEnd() && "Index exceeds number of arguments.");
1053 if (CurrentTA == EndTA)
1054 return TST->template_arguments()[Index];
1055 else
1056 return *CurrentTA;
1057 }
1058
1059 /// operator-> - Allow access to the underlying TemplateArgument.
1060 pointer operator->() const {
1061 assert(TST && "InternalIterator is invalid with a null TST.");
1062 return &operator*();
1063 }
1064 };
1065
1066 InternalIterator SugaredIterator;
1067 InternalIterator DesugaredIterator;
1068
1069 public:
1070 TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
1071 : SugaredIterator(TST),
1072 DesugaredIterator(
1073 (TST->isSugared() && !TST->isTypeAlias())
1074 ? GetTemplateSpecializationType(Context, Ty: TST->desugar())
1075 : nullptr) {}
1076
1077 /// &operator++ - Increment the iterator to the next template argument.
1078 TSTiterator &operator++() {
1079 ++SugaredIterator;
1080 if (DesugaredIterator.isValid())
1081 ++DesugaredIterator;
1082 return *this;
1083 }
1084
1085 /// operator* - Returns the appropriate TemplateArgument.
1086 reference operator*() const {
1087 return *SugaredIterator;
1088 }
1089
1090 /// operator-> - Allow access to the underlying TemplateArgument.
1091 pointer operator->() const {
1092 return &operator*();
1093 }
1094
1095 /// isEnd - Returns true if no more TemplateArguments are available.
1096 bool isEnd() const {
1097 return SugaredIterator.isEnd();
1098 }
1099
1100 /// hasDesugaredTA - Returns true if there is another TemplateArgument
1101 /// available.
1102 bool hasDesugaredTA() const {
1103 return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();
1104 }
1105
1106 /// getDesugaredTA - Returns the desugared TemplateArgument.
1107 reference getDesugaredTA() const {
1108 assert(DesugaredIterator.isValid() &&
1109 "Desugared TemplateArgument should not be used.");
1110 return *DesugaredIterator;
1111 }
1112 };
1113
1114 // These functions build up the template diff tree, including functions to
1115 // retrieve and compare template arguments.
1116
1117 static const TemplateSpecializationType *GetTemplateSpecializationType(
1118 ASTContext &Context, QualType Ty) {
1119 if (const TemplateSpecializationType *TST =
1120 Ty->getAs<TemplateSpecializationType>())
1121 return TST;
1122
1123 if (const auto* SubstType = Ty->getAs<SubstTemplateTypeParmType>())
1124 Ty = SubstType->getReplacementType();
1125
1126 const RecordType *RT = Ty->getAs<RecordType>();
1127
1128 if (!RT)
1129 return nullptr;
1130
1131 const ClassTemplateSpecializationDecl *CTSD =
1132 dyn_cast<ClassTemplateSpecializationDecl>(Val: RT->getDecl());
1133
1134 if (!CTSD)
1135 return nullptr;
1136
1137 Ty = Context.getTemplateSpecializationType(
1138 T: TemplateName(CTSD->getSpecializedTemplate()),
1139 Args: CTSD->getTemplateArgs().asArray(),
1140 Canon: Ty.getLocalUnqualifiedType().getCanonicalType());
1141
1142 return Ty->getAs<TemplateSpecializationType>();
1143 }
1144
1145 /// Returns true if the DiffType is Type and false for Template.
1146 static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType,
1147 QualType ToType,
1148 const TemplateSpecializationType *&FromArgTST,
1149 const TemplateSpecializationType *&ToArgTST) {
1150 if (FromType.isNull() || ToType.isNull())
1151 return true;
1152
1153 if (Context.hasSameType(T1: FromType, T2: ToType))
1154 return true;
1155
1156 FromArgTST = GetTemplateSpecializationType(Context, Ty: FromType);
1157 ToArgTST = GetTemplateSpecializationType(Context, Ty: ToType);
1158
1159 if (!FromArgTST || !ToArgTST)
1160 return true;
1161
1162 if (!hasSameTemplate(FromTST&: FromArgTST, ToTST&: ToArgTST))
1163 return true;
1164
1165 return false;
1166 }
1167
1168 /// DiffTypes - Fills a DiffNode with information about a type difference.
1169 void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) {
1170 QualType FromType = GetType(Iter: FromIter);
1171 QualType ToType = GetType(Iter: ToIter);
1172
1173 bool FromDefault = FromIter.isEnd() && !FromType.isNull();
1174 bool ToDefault = ToIter.isEnd() && !ToType.isNull();
1175
1176 const TemplateSpecializationType *FromArgTST = nullptr;
1177 const TemplateSpecializationType *ToArgTST = nullptr;
1178 if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) {
1179 Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault);
1180 Tree.SetSame(!FromType.isNull() && !ToType.isNull() &&
1181 Context.hasSameType(T1: FromType, T2: ToType));
1182 } else {
1183 assert(FromArgTST && ToArgTST &&
1184 "Both template specializations need to be valid.");
1185 Qualifiers FromQual = FromType.getQualifiers(),
1186 ToQual = ToType.getQualifiers();
1187 FromQual -= QualType(FromArgTST, 0).getQualifiers();
1188 ToQual -= QualType(ToArgTST, 0).getQualifiers();
1189 Tree.SetTemplateDiff(FromTD: FromArgTST->getTemplateName().getAsTemplateDecl(),
1190 ToTD: ToArgTST->getTemplateName().getAsTemplateDecl(),
1191 FromQual, ToQual, FromDefault, ToDefault);
1192 DiffTemplate(FromTST: FromArgTST, ToTST: ToArgTST);
1193 }
1194 }
1195
1196 /// DiffTemplateTemplates - Fills a DiffNode with information about a
1197 /// template template difference.
1198 void DiffTemplateTemplates(const TSTiterator &FromIter,
1199 const TSTiterator &ToIter) {
1200 TemplateDecl *FromDecl = GetTemplateDecl(Iter: FromIter);
1201 TemplateDecl *ToDecl = GetTemplateDecl(Iter: ToIter);
1202 Tree.SetTemplateTemplateDiff(FromTD: FromDecl, ToTD: ToDecl, FromDefault: FromIter.isEnd() && FromDecl,
1203 ToDefault: ToIter.isEnd() && ToDecl);
1204 Tree.SetSame(FromDecl && ToDecl &&
1205 FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());
1206 }
1207
1208 /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes
1209 static void InitializeNonTypeDiffVariables(ASTContext &Context,
1210 const TSTiterator &Iter,
1211 NonTypeTemplateParmDecl *Default,
1212 llvm::APSInt &Value, bool &HasInt,
1213 QualType &IntType, bool &IsNullPtr,
1214 Expr *&E, ValueDecl *&VD,
1215 bool &NeedAddressOf) {
1216 if (!Iter.isEnd()) {
1217 switch (Iter->getKind()) {
1218 case TemplateArgument::StructuralValue:
1219 // FIXME: Diffing of structural values is not implemented.
1220 // There is no possible fallback in this case, this will show up
1221 // as '(no argument)'.
1222 return;
1223 case TemplateArgument::Integral:
1224 Value = Iter->getAsIntegral();
1225 HasInt = true;
1226 IntType = Iter->getIntegralType();
1227 return;
1228 case TemplateArgument::Declaration: {
1229 VD = Iter->getAsDecl();
1230 QualType ArgType = Iter->getParamTypeForDecl();
1231 QualType VDType = VD->getType();
1232 if (ArgType->isPointerType() &&
1233 Context.hasSameType(T1: ArgType->getPointeeType(), T2: VDType))
1234 NeedAddressOf = true;
1235 return;
1236 }
1237 case TemplateArgument::NullPtr:
1238 IsNullPtr = true;
1239 return;
1240 case TemplateArgument::Expression:
1241 E = Iter->getAsExpr();
1242 break;
1243 case TemplateArgument::Null:
1244 case TemplateArgument::Type:
1245 case TemplateArgument::Template:
1246 case TemplateArgument::TemplateExpansion:
1247 llvm_unreachable("TemplateArgument kind is not expected for NTTP");
1248 case TemplateArgument::Pack:
1249 llvm_unreachable("TemplateArgument kind should be handled elsewhere");
1250 }
1251 } else if (!Default->isParameterPack()) {
1252 E = Default->getDefaultArgument().getArgument().getAsExpr();
1253 }
1254
1255 if (!Iter.hasDesugaredTA())
1256 return;
1257
1258 const TemplateArgument &TA = Iter.getDesugaredTA();
1259 switch (TA.getKind()) {
1260 case TemplateArgument::StructuralValue:
1261 // FIXME: Diffing of structural values is not implemented.
1262 // Just fall back to the expression.
1263 return;
1264 case TemplateArgument::Integral:
1265 Value = TA.getAsIntegral();
1266 HasInt = true;
1267 IntType = TA.getIntegralType();
1268 return;
1269 case TemplateArgument::Declaration: {
1270 VD = TA.getAsDecl();
1271 QualType ArgType = TA.getParamTypeForDecl();
1272 QualType VDType = VD->getType();
1273 if (ArgType->isPointerType() &&
1274 Context.hasSameType(T1: ArgType->getPointeeType(), T2: VDType))
1275 NeedAddressOf = true;
1276 return;
1277 }
1278 case TemplateArgument::NullPtr:
1279 IsNullPtr = true;
1280 return;
1281 case TemplateArgument::Expression:
1282 // TODO: Sometimes, the desugared template argument Expr differs from
1283 // the sugared template argument Expr. It may be useful in the future
1284 // but for now, it is just discarded.
1285 if (!E)
1286 E = TA.getAsExpr();
1287 return;
1288 case TemplateArgument::Null:
1289 case TemplateArgument::Type:
1290 case TemplateArgument::Template:
1291 case TemplateArgument::TemplateExpansion:
1292 llvm_unreachable("TemplateArgument kind is not expected for NTTP");
1293 case TemplateArgument::Pack:
1294 llvm_unreachable("TemplateArgument kind should be handled elsewhere");
1295 }
1296 llvm_unreachable("Unexpected TemplateArgument kind");
1297 }
1298
1299 /// DiffNonTypes - Handles any template parameters not handled by DiffTypes
1300 /// of DiffTemplatesTemplates, such as integer and declaration parameters.
1301 void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
1302 NonTypeTemplateParmDecl *FromDefaultNonTypeDecl,
1303 NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) {
1304 Expr *FromExpr = nullptr, *ToExpr = nullptr;
1305 llvm::APSInt FromInt, ToInt;
1306 QualType FromIntType, ToIntType;
1307 ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
1308 bool HasFromInt = false, HasToInt = false, FromNullPtr = false,
1309 ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;
1310 InitializeNonTypeDiffVariables(
1311 Context, Iter: FromIter, Default: FromDefaultNonTypeDecl, Value&: FromInt, HasInt&: HasFromInt,
1312 IntType&: FromIntType, IsNullPtr&: FromNullPtr, E&: FromExpr, VD&: FromValueDecl, NeedAddressOf&: NeedFromAddressOf);
1313 InitializeNonTypeDiffVariables(Context, Iter: ToIter, Default: ToDefaultNonTypeDecl, Value&: ToInt,
1314 HasInt&: HasToInt, IntType&: ToIntType, IsNullPtr&: ToNullPtr, E&: ToExpr,
1315 VD&: ToValueDecl, NeedAddressOf&: NeedToAddressOf);
1316
1317 bool FromDefault = FromIter.isEnd() &&
1318 (FromExpr || FromValueDecl || HasFromInt || FromNullPtr);
1319 bool ToDefault = ToIter.isEnd() &&
1320 (ToExpr || ToValueDecl || HasToInt || ToNullPtr);
1321
1322 bool FromDeclaration = FromValueDecl || FromNullPtr;
1323 bool ToDeclaration = ToValueDecl || ToNullPtr;
1324
1325 if (FromDeclaration && HasToInt) {
1326 Tree.SetFromDeclarationAndToIntegerDiff(
1327 FromValueDecl, FromAddressOf: NeedFromAddressOf, FromNullPtr, FromExpr, ToInt,
1328 IsValidToInt: HasToInt, ToIntType, ToExpr, FromDefault, ToDefault);
1329 Tree.SetSame(false);
1330 return;
1331
1332 }
1333
1334 if (HasFromInt && ToDeclaration) {
1335 Tree.SetFromIntegerAndToDeclarationDiff(
1336 FromInt, IsValidFromInt: HasFromInt, FromIntType, FromExpr, ToValueDecl,
1337 ToAddressOf: NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault);
1338 Tree.SetSame(false);
1339 return;
1340 }
1341
1342 if (HasFromInt || HasToInt) {
1343 Tree.SetIntegerDiff(FromInt, ToInt, IsValidFromInt: HasFromInt, IsValidToInt: HasToInt, FromIntType,
1344 ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);
1345 if (HasFromInt && HasToInt) {
1346 Tree.SetSame(Context.hasSameType(T1: FromIntType, T2: ToIntType) &&
1347 FromInt == ToInt);
1348 }
1349 return;
1350 }
1351
1352 if (FromDeclaration || ToDeclaration) {
1353 Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf: NeedFromAddressOf,
1354 ToAddressOf: NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
1355 ToExpr, FromDefault, ToDefault);
1356 bool BothNull = FromNullPtr && ToNullPtr;
1357 bool SameValueDecl =
1358 FromValueDecl && ToValueDecl &&
1359 NeedFromAddressOf == NeedToAddressOf &&
1360 FromValueDecl->getCanonicalDecl() == ToValueDecl->getCanonicalDecl();
1361 Tree.SetSame(BothNull || SameValueDecl);
1362 return;
1363 }
1364
1365 assert((FromExpr || ToExpr) && "Both template arguments cannot be empty.");
1366 Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault);
1367 Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
1368 }
1369
1370 /// DiffTemplate - recursively visits template arguments and stores the
1371 /// argument info into a tree.
1372 void DiffTemplate(const TemplateSpecializationType *FromTST,
1373 const TemplateSpecializationType *ToTST) {
1374 // Begin descent into diffing template tree.
1375 TemplateParameterList *ParamsFrom =
1376 FromTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
1377 TemplateParameterList *ParamsTo =
1378 ToTST->getTemplateName().getAsTemplateDecl()->getTemplateParameters();
1379 unsigned TotalArgs = 0;
1380 for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST);
1381 !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {
1382 Tree.AddNode();
1383
1384 // Get the parameter at index TotalArgs. If index is larger
1385 // than the total number of parameters, then there is an
1386 // argument pack, so re-use the last parameter.
1387 unsigned FromParamIndex = std::min(a: TotalArgs, b: ParamsFrom->size() - 1);
1388 unsigned ToParamIndex = std::min(a: TotalArgs, b: ParamsTo->size() - 1);
1389 NamedDecl *FromParamND = ParamsFrom->getParam(Idx: FromParamIndex);
1390 NamedDecl *ToParamND = ParamsTo->getParam(Idx: ToParamIndex);
1391
1392 assert(FromParamND->getKind() == ToParamND->getKind() &&
1393 "Parameter Decl are not the same kind.");
1394
1395 if (isa<TemplateTypeParmDecl>(Val: FromParamND)) {
1396 DiffTypes(FromIter, ToIter);
1397 } else if (isa<TemplateTemplateParmDecl>(Val: FromParamND)) {
1398 DiffTemplateTemplates(FromIter, ToIter);
1399 } else if (isa<NonTypeTemplateParmDecl>(Val: FromParamND)) {
1400 NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =
1401 cast<NonTypeTemplateParmDecl>(Val: FromParamND);
1402 NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =
1403 cast<NonTypeTemplateParmDecl>(Val: ToParamND);
1404 DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,
1405 ToDefaultNonTypeDecl);
1406 } else {
1407 llvm_unreachable("Unexpected Decl type.");
1408 }
1409
1410 ++FromIter;
1411 ++ToIter;
1412 Tree.Up();
1413 }
1414 }
1415
1416 /// makeTemplateList - Dump every template alias into the vector.
1417 static void makeTemplateList(
1418 SmallVectorImpl<const TemplateSpecializationType *> &TemplateList,
1419 const TemplateSpecializationType *TST) {
1420 while (TST) {
1421 TemplateList.push_back(Elt: TST);
1422 if (!TST->isTypeAlias())
1423 return;
1424 TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
1425 }
1426 }
1427
1428 /// hasSameBaseTemplate - Returns true when the base templates are the same,
1429 /// even if the template arguments are not.
1430 static bool hasSameBaseTemplate(const TemplateSpecializationType *FromTST,
1431 const TemplateSpecializationType *ToTST) {
1432 return FromTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl() ==
1433 ToTST->getTemplateName().getAsTemplateDecl()->getCanonicalDecl();
1434 }
1435
1436 /// hasSameTemplate - Returns true if both types are specialized from the
1437 /// same template declaration. If they come from different template aliases,
1438 /// do a parallel ascension search to determine the highest template alias in
1439 /// common and set the arguments to them.
1440 static bool hasSameTemplate(const TemplateSpecializationType *&FromTST,
1441 const TemplateSpecializationType *&ToTST) {
1442 // Check the top templates if they are the same.
1443 if (hasSameBaseTemplate(FromTST, ToTST))
1444 return true;
1445
1446 // Create vectors of template aliases.
1447 SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,
1448 ToTemplateList;
1449
1450 makeTemplateList(TemplateList&: FromTemplateList, TST: FromTST);
1451 makeTemplateList(TemplateList&: ToTemplateList, TST: ToTST);
1452
1453 SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator
1454 FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),
1455 ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();
1456
1457 // Check if the lowest template types are the same. If not, return.
1458 if (!hasSameBaseTemplate(FromTST: *FromIter, ToTST: *ToIter))
1459 return false;
1460
1461 // Begin searching up the template aliases. The bottom most template
1462 // matches so move up until one pair does not match. Use the template
1463 // right before that one.
1464 for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {
1465 if (!hasSameBaseTemplate(FromTST: *FromIter, ToTST: *ToIter))
1466 break;
1467 }
1468
1469 FromTST = FromIter[-1];
1470 ToTST = ToIter[-1];
1471
1472 return true;
1473 }
1474
1475 /// GetType - Retrieves the template type arguments, including default
1476 /// arguments.
1477 static QualType GetType(const TSTiterator &Iter) {
1478 if (!Iter.isEnd())
1479 return Iter->getAsType();
1480 if (Iter.hasDesugaredTA())
1481 return Iter.getDesugaredTA().getAsType();
1482 return QualType();
1483 }
1484
1485 /// GetTemplateDecl - Retrieves the template template arguments, including
1486 /// default arguments.
1487 static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) {
1488 if (!Iter.isEnd())
1489 return Iter->getAsTemplate().getAsTemplateDecl();
1490 if (Iter.hasDesugaredTA())
1491 return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl();
1492 return nullptr;
1493 }
1494
1495 /// IsEqualExpr - Returns true if the expressions are the same in regards to
1496 /// template arguments. These expressions are dependent, so profile them
1497 /// instead of trying to evaluate them.
1498 static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {
1499 if (FromExpr == ToExpr)
1500 return true;
1501
1502 if (!FromExpr || !ToExpr)
1503 return false;
1504
1505 llvm::FoldingSetNodeID FromID, ToID;
1506 FromExpr->Profile(ID&: FromID, Context, Canonical: true);
1507 ToExpr->Profile(ID&: ToID, Context, Canonical: true);
1508 return FromID == ToID;
1509 }
1510
1511 // These functions converts the tree representation of the template
1512 // differences into the internal character vector.
1513
1514 /// TreeToString - Converts the Tree object into a character stream which
1515 /// will later be turned into the output string.
1516 void TreeToString(int Indent = 1) {
1517 if (PrintTree) {
1518 OS << '\n';
1519 OS.indent(NumSpaces: 2 * Indent);
1520 ++Indent;
1521 }
1522
1523 // Handle cases where the difference is not templates with different
1524 // arguments.
1525 switch (Tree.GetKind()) {
1526 case DiffTree::Invalid:
1527 llvm_unreachable("Template diffing failed with bad DiffNode");
1528 case DiffTree::Type: {
1529 QualType FromType, ToType;
1530 Tree.GetTypeDiff(FromType, ToType);
1531 PrintTypeNames(FromType, ToType, FromDefault: Tree.FromDefault(), ToDefault: Tree.ToDefault(),
1532 Same: Tree.NodeIsSame());
1533 return;
1534 }
1535 case DiffTree::Expression: {
1536 Expr *FromExpr, *ToExpr;
1537 Tree.GetExpressionDiff(FromExpr, ToExpr);
1538 PrintExpr(FromExpr, ToExpr, FromDefault: Tree.FromDefault(), ToDefault: Tree.ToDefault(),
1539 Same: Tree.NodeIsSame());
1540 return;
1541 }
1542 case DiffTree::TemplateTemplate: {
1543 TemplateDecl *FromTD, *ToTD;
1544 Tree.GetTemplateTemplateDiff(FromTD, ToTD);
1545 PrintTemplateTemplate(FromTD, ToTD, FromDefault: Tree.FromDefault(),
1546 ToDefault: Tree.ToDefault(), Same: Tree.NodeIsSame());
1547 return;
1548 }
1549 case DiffTree::Integer: {
1550 llvm::APSInt FromInt, ToInt;
1551 Expr *FromExpr, *ToExpr;
1552 bool IsValidFromInt, IsValidToInt;
1553 QualType FromIntType, ToIntType;
1554 Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,
1555 FromIntType, ToIntType, FromExpr, ToExpr);
1556 PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,
1557 ToIntType, FromExpr, ToExpr, FromDefault: Tree.FromDefault(),
1558 ToDefault: Tree.ToDefault(), Same: Tree.NodeIsSame());
1559 return;
1560 }
1561 case DiffTree::Declaration: {
1562 ValueDecl *FromValueDecl, *ToValueDecl;
1563 bool FromAddressOf, ToAddressOf;
1564 bool FromNullPtr, ToNullPtr;
1565 Expr *FromExpr, *ToExpr;
1566 Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf,
1567 ToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
1568 ToExpr);
1569 PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
1570 FromNullPtr, ToNullPtr, FromExpr, ToExpr,
1571 FromDefault: Tree.FromDefault(), ToDefault: Tree.ToDefault(), Same: Tree.NodeIsSame());
1572 return;
1573 }
1574 case DiffTree::FromDeclarationAndToInteger: {
1575 ValueDecl *FromValueDecl;
1576 bool FromAddressOf;
1577 bool FromNullPtr;
1578 Expr *FromExpr;
1579 llvm::APSInt ToInt;
1580 bool IsValidToInt;
1581 QualType ToIntType;
1582 Expr *ToExpr;
1583 Tree.GetFromDeclarationAndToIntegerDiff(
1584 FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt,
1585 IsValidToInt, ToIntType, ToExpr);
1586 assert((FromValueDecl || FromNullPtr) && IsValidToInt);
1587 PrintValueDeclAndInteger(VD: FromValueDecl, NeedAddressOf: FromAddressOf, IsNullPtr: FromNullPtr,
1588 VDExpr: FromExpr, DefaultDecl: Tree.FromDefault(), Val: ToInt, IntType: ToIntType,
1589 IntExpr: ToExpr, DefaultInt: Tree.ToDefault());
1590 return;
1591 }
1592 case DiffTree::FromIntegerAndToDeclaration: {
1593 llvm::APSInt FromInt;
1594 bool IsValidFromInt;
1595 QualType FromIntType;
1596 Expr *FromExpr;
1597 ValueDecl *ToValueDecl;
1598 bool ToAddressOf;
1599 bool ToNullPtr;
1600 Expr *ToExpr;
1601 Tree.GetFromIntegerAndToDeclarationDiff(
1602 FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl,
1603 ToAddressOf, ToNullPtr, ToExpr);
1604 assert(IsValidFromInt && (ToValueDecl || ToNullPtr));
1605 PrintIntegerAndValueDecl(Val: FromInt, IntType: FromIntType, IntExpr: FromExpr,
1606 DefaultInt: Tree.FromDefault(), VD: ToValueDecl, NeedAddressOf: ToAddressOf,
1607 IsNullPtr: ToNullPtr, VDExpr: ToExpr, DefaultDecl: Tree.ToDefault());
1608 return;
1609 }
1610 case DiffTree::Template: {
1611 // Node is root of template. Recurse on children.
1612 TemplateDecl *FromTD, *ToTD;
1613 Qualifiers FromQual, ToQual;
1614 Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual);
1615
1616 PrintQualifiers(FromQual, ToQual);
1617
1618 if (!Tree.HasChildren()) {
1619 // If we're dealing with a template specialization with zero
1620 // arguments, there are no children; special-case this.
1621 OS << FromTD->getDeclName() << "<>";
1622 return;
1623 }
1624
1625 OS << FromTD->getDeclName() << '<';
1626 Tree.MoveToChild();
1627 unsigned NumElideArgs = 0;
1628 bool AllArgsElided = true;
1629 do {
1630 if (ElideType) {
1631 if (Tree.NodeIsSame()) {
1632 ++NumElideArgs;
1633 continue;
1634 }
1635 AllArgsElided = false;
1636 if (NumElideArgs > 0) {
1637 PrintElideArgs(NumElideArgs, Indent);
1638 NumElideArgs = 0;
1639 OS << ", ";
1640 }
1641 }
1642 TreeToString(Indent);
1643 if (Tree.HasNextSibling())
1644 OS << ", ";
1645 } while (Tree.AdvanceSibling());
1646 if (NumElideArgs > 0) {
1647 if (AllArgsElided)
1648 OS << "...";
1649 else
1650 PrintElideArgs(NumElideArgs, Indent);
1651 }
1652
1653 Tree.Parent();
1654 OS << ">";
1655 return;
1656 }
1657 }
1658 }
1659
1660 // To signal to the text printer that a certain text needs to be bolded,
1661 // a special character is injected into the character stream which the
1662 // text printer will later strip out.
1663
1664 /// Bold - Start bolding text.
1665 void Bold() {
1666 assert(!IsBold && "Attempting to bold text that is already bold.");
1667 IsBold = true;
1668 if (ShowColor)
1669 OS << ToggleHighlight;
1670 }
1671
1672 /// Unbold - Stop bolding text.
1673 void Unbold() {
1674 assert(IsBold && "Attempting to remove bold from unbold text.");
1675 IsBold = false;
1676 if (ShowColor)
1677 OS << ToggleHighlight;
1678 }
1679
1680 // Functions to print out the arguments and highlighting the difference.
1681
1682 /// PrintTypeNames - prints the typenames, bolding differences. Will detect
1683 /// typenames that are the same and attempt to disambiguate them by using
1684 /// canonical typenames.
1685 void PrintTypeNames(QualType FromType, QualType ToType,
1686 bool FromDefault, bool ToDefault, bool Same) {
1687 assert((!FromType.isNull() || !ToType.isNull()) &&
1688 "Only one template argument may be missing.");
1689
1690 if (Same) {
1691 OS << FromType.getAsString(Policy);
1692 return;
1693 }
1694
1695 if (!FromType.isNull() && !ToType.isNull() &&
1696 FromType.getLocalUnqualifiedType() ==
1697 ToType.getLocalUnqualifiedType()) {
1698 Qualifiers FromQual = FromType.getLocalQualifiers(),
1699 ToQual = ToType.getLocalQualifiers();
1700 PrintQualifiers(FromQual, ToQual);
1701 FromType.getLocalUnqualifiedType().print(OS, Policy);
1702 return;
1703 }
1704
1705 std::string FromTypeStr = FromType.isNull() ? "(no argument)"
1706 : FromType.getAsString(Policy);
1707 std::string ToTypeStr = ToType.isNull() ? "(no argument)"
1708 : ToType.getAsString(Policy);
1709 // Print without ElaboratedType sugar if it is better.
1710 // TODO: merge this with other aka printing above.
1711 if (FromTypeStr == ToTypeStr) {
1712 const auto *FromElTy = dyn_cast<ElaboratedType>(Val&: FromType),
1713 *ToElTy = dyn_cast<ElaboratedType>(Val&: ToType);
1714 if (FromElTy || ToElTy) {
1715 std::string FromNamedTypeStr =
1716 FromElTy ? FromElTy->getNamedType().getAsString(Policy)
1717 : FromTypeStr;
1718 std::string ToNamedTypeStr =
1719 ToElTy ? ToElTy->getNamedType().getAsString(Policy) : ToTypeStr;
1720 if (FromNamedTypeStr != ToNamedTypeStr) {
1721 FromTypeStr = FromNamedTypeStr;
1722 ToTypeStr = ToNamedTypeStr;
1723 goto PrintTypes;
1724 }
1725 }
1726 // Switch to canonical typename if it is better.
1727 std::string FromCanTypeStr =
1728 FromType.getCanonicalType().getAsString(Policy);
1729 std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy);
1730 if (FromCanTypeStr != ToCanTypeStr) {
1731 FromTypeStr = FromCanTypeStr;
1732 ToTypeStr = ToCanTypeStr;
1733 }
1734 }
1735
1736 PrintTypes:
1737 if (PrintTree) OS << '[';
1738 OS << (FromDefault ? "(default) " : "");
1739 Bold();
1740 OS << FromTypeStr;
1741 Unbold();
1742 if (PrintTree) {
1743 OS << " != " << (ToDefault ? "(default) " : "");
1744 Bold();
1745 OS << ToTypeStr;
1746 Unbold();
1747 OS << "]";
1748 }
1749 }
1750
1751 /// PrintExpr - Prints out the expr template arguments, highlighting argument
1752 /// differences.
1753 void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault,
1754 bool ToDefault, bool Same) {
1755 assert((FromExpr || ToExpr) &&
1756 "Only one template argument may be missing.");
1757 if (Same) {
1758 PrintExpr(E: FromExpr);
1759 } else if (!PrintTree) {
1760 OS << (FromDefault ? "(default) " : "");
1761 Bold();
1762 PrintExpr(E: FromExpr);
1763 Unbold();
1764 } else {
1765 OS << (FromDefault ? "[(default) " : "[");
1766 Bold();
1767 PrintExpr(E: FromExpr);
1768 Unbold();
1769 OS << " != " << (ToDefault ? "(default) " : "");
1770 Bold();
1771 PrintExpr(E: ToExpr);
1772 Unbold();
1773 OS << ']';
1774 }
1775 }
1776
1777 /// PrintExpr - Actual formatting and printing of expressions.
1778 void PrintExpr(const Expr *E) {
1779 if (E) {
1780 E->printPretty(OS, Helper: nullptr, Policy);
1781 return;
1782 }
1783 OS << "(no argument)";
1784 }
1785
1786 /// PrintTemplateTemplate - Handles printing of template template arguments,
1787 /// highlighting argument differences.
1788 void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,
1789 bool FromDefault, bool ToDefault, bool Same) {
1790 assert((FromTD || ToTD) && "Only one template argument may be missing.");
1791
1792 std::string FromName =
1793 std::string(FromTD ? FromTD->getName() : "(no argument)");
1794 std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");
1795 if (FromTD && ToTD && FromName == ToName) {
1796 FromName = FromTD->getQualifiedNameAsString();
1797 ToName = ToTD->getQualifiedNameAsString();
1798 }
1799
1800 if (Same) {
1801 OS << "template " << FromTD->getDeclName();
1802 } else if (!PrintTree) {
1803 OS << (FromDefault ? "(default) template " : "template ");
1804 Bold();
1805 OS << FromName;
1806 Unbold();
1807 } else {
1808 OS << (FromDefault ? "[(default) template " : "[template ");
1809 Bold();
1810 OS << FromName;
1811 Unbold();
1812 OS << " != " << (ToDefault ? "(default) template " : "template ");
1813 Bold();
1814 OS << ToName;
1815 Unbold();
1816 OS << ']';
1817 }
1818 }
1819
1820 /// PrintAPSInt - Handles printing of integral arguments, highlighting
1821 /// argument differences.
1822 void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
1823 bool IsValidFromInt, bool IsValidToInt, QualType FromIntType,
1824 QualType ToIntType, Expr *FromExpr, Expr *ToExpr,
1825 bool FromDefault, bool ToDefault, bool Same) {
1826 assert((IsValidFromInt || IsValidToInt) &&
1827 "Only one integral argument may be missing.");
1828
1829 if (Same) {
1830 if (FromIntType->isBooleanType()) {
1831 OS << ((FromInt == 0) ? "false" : "true");
1832 } else {
1833 OS << toString(I: FromInt, Radix: 10);
1834 }
1835 return;
1836 }
1837
1838 bool PrintType = IsValidFromInt && IsValidToInt &&
1839 !Context.hasSameType(T1: FromIntType, T2: ToIntType);
1840
1841 if (!PrintTree) {
1842 OS << (FromDefault ? "(default) " : "");
1843 PrintAPSInt(Val: FromInt, E: FromExpr, Valid: IsValidFromInt, IntType: FromIntType, PrintType);
1844 } else {
1845 OS << (FromDefault ? "[(default) " : "[");
1846 PrintAPSInt(Val: FromInt, E: FromExpr, Valid: IsValidFromInt, IntType: FromIntType, PrintType);
1847 OS << " != " << (ToDefault ? "(default) " : "");
1848 PrintAPSInt(Val: ToInt, E: ToExpr, Valid: IsValidToInt, IntType: ToIntType, PrintType);
1849 OS << ']';
1850 }
1851 }
1852
1853 /// PrintAPSInt - If valid, print the APSInt. If the expression is
1854 /// gives more information, print it too.
1855 void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid,
1856 QualType IntType, bool PrintType) {
1857 Bold();
1858 if (Valid) {
1859 if (HasExtraInfo(E)) {
1860 PrintExpr(E);
1861 Unbold();
1862 OS << " aka ";
1863 Bold();
1864 }
1865 if (PrintType) {
1866 Unbold();
1867 OS << "(";
1868 Bold();
1869 IntType.print(OS, Policy: Context.getPrintingPolicy());
1870 Unbold();
1871 OS << ") ";
1872 Bold();
1873 }
1874 if (IntType->isBooleanType()) {
1875 OS << ((Val == 0) ? "false" : "true");
1876 } else {
1877 OS << toString(I: Val, Radix: 10);
1878 }
1879 } else if (E) {
1880 PrintExpr(E);
1881 } else {
1882 OS << "(no argument)";
1883 }
1884 Unbold();
1885 }
1886
1887 /// HasExtraInfo - Returns true if E is not an integer literal, the
1888 /// negation of an integer literal, or a boolean literal.
1889 bool HasExtraInfo(Expr *E) {
1890 if (!E) return false;
1891
1892 E = E->IgnoreImpCasts();
1893
1894 if (isa<IntegerLiteral>(Val: E)) return false;
1895
1896 if (UnaryOperator *UO = dyn_cast<UnaryOperator>(Val: E))
1897 if (UO->getOpcode() == UO_Minus)
1898 if (isa<IntegerLiteral>(Val: UO->getSubExpr()))
1899 return false;
1900
1901 if (isa<CXXBoolLiteralExpr>(Val: E))
1902 return false;
1903
1904 return true;
1905 }
1906
1907 void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) {
1908 if (VD) {
1909 if (AddressOf)
1910 OS << "&";
1911 else if (auto *TPO = dyn_cast<TemplateParamObjectDecl>(Val: VD)) {
1912 // FIXME: Diffing the APValue would be neat.
1913 // FIXME: Suppress this and use the full name of the declaration if the
1914 // parameter is a pointer or reference.
1915 TPO->getType().getUnqualifiedType().print(OS, Policy);
1916 TPO->printAsInit(OS, Policy);
1917 return;
1918 }
1919 VD->printName(OS, Policy);
1920 return;
1921 }
1922
1923 if (NullPtr) {
1924 if (E && !isa<CXXNullPtrLiteralExpr>(Val: E)) {
1925 PrintExpr(E);
1926 if (IsBold) {
1927 Unbold();
1928 OS << " aka ";
1929 Bold();
1930 } else {
1931 OS << " aka ";
1932 }
1933 }
1934
1935 OS << "nullptr";
1936 return;
1937 }
1938
1939 if (E) {
1940 PrintExpr(E);
1941 return;
1942 }
1943
1944 OS << "(no argument)";
1945 }
1946
1947 /// PrintDecl - Handles printing of Decl arguments, highlighting
1948 /// argument differences.
1949 void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
1950 bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,
1951 bool ToNullPtr, Expr *FromExpr, Expr *ToExpr,
1952 bool FromDefault, bool ToDefault, bool Same) {
1953 assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&
1954 "Only one Decl argument may be NULL");
1955
1956 if (Same) {
1957 PrintValueDecl(VD: FromValueDecl, AddressOf: FromAddressOf, E: FromExpr, NullPtr: FromNullPtr);
1958 } else if (!PrintTree) {
1959 OS << (FromDefault ? "(default) " : "");
1960 Bold();
1961 PrintValueDecl(VD: FromValueDecl, AddressOf: FromAddressOf, E: FromExpr, NullPtr: FromNullPtr);
1962 Unbold();
1963 } else {
1964 OS << (FromDefault ? "[(default) " : "[");
1965 Bold();
1966 PrintValueDecl(VD: FromValueDecl, AddressOf: FromAddressOf, E: FromExpr, NullPtr: FromNullPtr);
1967 Unbold();
1968 OS << " != " << (ToDefault ? "(default) " : "");
1969 Bold();
1970 PrintValueDecl(VD: ToValueDecl, AddressOf: ToAddressOf, E: ToExpr, NullPtr: ToNullPtr);
1971 Unbold();
1972 OS << ']';
1973 }
1974 }
1975
1976 /// PrintValueDeclAndInteger - Uses the print functions for ValueDecl and
1977 /// APSInt to print a mixed difference.
1978 void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf,
1979 bool IsNullPtr, Expr *VDExpr, bool DefaultDecl,
1980 const llvm::APSInt &Val, QualType IntType,
1981 Expr *IntExpr, bool DefaultInt) {
1982 if (!PrintTree) {
1983 OS << (DefaultDecl ? "(default) " : "");
1984 Bold();
1985 PrintValueDecl(VD, AddressOf: NeedAddressOf, E: VDExpr, NullPtr: IsNullPtr);
1986 Unbold();
1987 } else {
1988 OS << (DefaultDecl ? "[(default) " : "[");
1989 Bold();
1990 PrintValueDecl(VD, AddressOf: NeedAddressOf, E: VDExpr, NullPtr: IsNullPtr);
1991 Unbold();
1992 OS << " != " << (DefaultInt ? "(default) " : "");
1993 PrintAPSInt(Val, E: IntExpr, Valid: true /*Valid*/, IntType, PrintType: false /*PrintType*/);
1994 OS << ']';
1995 }
1996 }
1997
1998 /// PrintIntegerAndValueDecl - Uses the print functions for APSInt and
1999 /// ValueDecl to print a mixed difference.
2000 void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType,
2001 Expr *IntExpr, bool DefaultInt, ValueDecl *VD,
2002 bool NeedAddressOf, bool IsNullPtr,
2003 Expr *VDExpr, bool DefaultDecl) {
2004 if (!PrintTree) {
2005 OS << (DefaultInt ? "(default) " : "");
2006 PrintAPSInt(Val, E: IntExpr, Valid: true /*Valid*/, IntType, PrintType: false /*PrintType*/);
2007 } else {
2008 OS << (DefaultInt ? "[(default) " : "[");
2009 PrintAPSInt(Val, E: IntExpr, Valid: true /*Valid*/, IntType, PrintType: false /*PrintType*/);
2010 OS << " != " << (DefaultDecl ? "(default) " : "");
2011 Bold();
2012 PrintValueDecl(VD, AddressOf: NeedAddressOf, E: VDExpr, NullPtr: IsNullPtr);
2013 Unbold();
2014 OS << ']';
2015 }
2016 }
2017
2018 // Prints the appropriate placeholder for elided template arguments.
2019 void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
2020 if (PrintTree) {
2021 OS << '\n';
2022 for (unsigned i = 0; i < Indent; ++i)
2023 OS << " ";
2024 }
2025 if (NumElideArgs == 0) return;
2026 if (NumElideArgs == 1)
2027 OS << "[...]";
2028 else
2029 OS << "[" << NumElideArgs << " * ...]";
2030 }
2031
2032 // Prints and highlights differences in Qualifiers.
2033 void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {
2034 // Both types have no qualifiers
2035 if (FromQual.empty() && ToQual.empty())
2036 return;
2037
2038 // Both types have same qualifiers
2039 if (FromQual == ToQual) {
2040 PrintQualifier(Q: FromQual, /*ApplyBold*/false);
2041 return;
2042 }
2043
2044 // Find common qualifiers and strip them from FromQual and ToQual.
2045 Qualifiers CommonQual = Qualifiers::removeCommonQualifiers(L&: FromQual,
2046 R&: ToQual);
2047
2048 // The qualifiers are printed before the template name.
2049 // Inline printing:
2050 // The common qualifiers are printed. Then, qualifiers only in this type
2051 // are printed and highlighted. Finally, qualifiers only in the other
2052 // type are printed and highlighted inside parentheses after "missing".
2053 // Tree printing:
2054 // Qualifiers are printed next to each other, inside brackets, and
2055 // separated by "!=". The printing order is:
2056 // common qualifiers, highlighted from qualifiers, "!=",
2057 // common qualifiers, highlighted to qualifiers
2058 if (PrintTree) {
2059 OS << "[";
2060 if (CommonQual.empty() && FromQual.empty()) {
2061 Bold();
2062 OS << "(no qualifiers) ";
2063 Unbold();
2064 } else {
2065 PrintQualifier(Q: CommonQual, /*ApplyBold*/false);
2066 PrintQualifier(Q: FromQual, /*ApplyBold*/true);
2067 }
2068 OS << "!= ";
2069 if (CommonQual.empty() && ToQual.empty()) {
2070 Bold();
2071 OS << "(no qualifiers)";
2072 Unbold();
2073 } else {
2074 PrintQualifier(Q: CommonQual, /*ApplyBold*/false,
2075 /*appendSpaceIfNonEmpty*/AppendSpaceIfNonEmpty: !ToQual.empty());
2076 PrintQualifier(Q: ToQual, /*ApplyBold*/true,
2077 /*appendSpaceIfNonEmpty*/AppendSpaceIfNonEmpty: false);
2078 }
2079 OS << "] ";
2080 } else {
2081 PrintQualifier(Q: CommonQual, /*ApplyBold*/false);
2082 PrintQualifier(Q: FromQual, /*ApplyBold*/true);
2083 }
2084 }
2085
2086 void PrintQualifier(Qualifiers Q, bool ApplyBold,
2087 bool AppendSpaceIfNonEmpty = true) {
2088 if (Q.empty()) return;
2089 if (ApplyBold) Bold();
2090 Q.print(OS, Policy, appendSpaceIfNonEmpty: AppendSpaceIfNonEmpty);
2091 if (ApplyBold) Unbold();
2092 }
2093
2094public:
2095
2096 TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType,
2097 QualType ToType, bool PrintTree, bool PrintFromType,
2098 bool ElideType, bool ShowColor)
2099 : Context(Context),
2100 Policy(Context.getLangOpts()),
2101 ElideType(ElideType),
2102 PrintTree(PrintTree),
2103 ShowColor(ShowColor),
2104 // When printing a single type, the FromType is the one printed.
2105 FromTemplateType(PrintFromType ? FromType : ToType),
2106 ToTemplateType(PrintFromType ? ToType : FromType),
2107 OS(OS),
2108 IsBold(false) {
2109 }
2110
2111 /// DiffTemplate - Start the template type diffing.
2112 void DiffTemplate() {
2113 Qualifiers FromQual = FromTemplateType.getQualifiers(),
2114 ToQual = ToTemplateType.getQualifiers();
2115
2116 const TemplateSpecializationType *FromOrigTST =
2117 GetTemplateSpecializationType(Context, Ty: FromTemplateType);
2118 const TemplateSpecializationType *ToOrigTST =
2119 GetTemplateSpecializationType(Context, Ty: ToTemplateType);
2120
2121 // Only checking templates.
2122 if (!FromOrigTST || !ToOrigTST)
2123 return;
2124
2125 // Different base templates.
2126 if (!hasSameTemplate(FromTST&: FromOrigTST, ToTST&: ToOrigTST)) {
2127 return;
2128 }
2129
2130 FromQual -= QualType(FromOrigTST, 0).getQualifiers();
2131 ToQual -= QualType(ToOrigTST, 0).getQualifiers();
2132
2133 // Same base template, but different arguments.
2134 Tree.SetTemplateDiff(FromTD: FromOrigTST->getTemplateName().getAsTemplateDecl(),
2135 ToTD: ToOrigTST->getTemplateName().getAsTemplateDecl(),
2136 FromQual, ToQual, FromDefault: false /*FromDefault*/,
2137 ToDefault: false /*ToDefault*/);
2138
2139 DiffTemplate(FromTST: FromOrigTST, ToTST: ToOrigTST);
2140 }
2141
2142 /// Emit - When the two types given are templated types with the same
2143 /// base template, a string representation of the type difference will be
2144 /// emitted to the stream and return true. Otherwise, return false.
2145 bool Emit() {
2146 Tree.StartTraverse();
2147 if (Tree.Empty())
2148 return false;
2149
2150 TreeToString();
2151 assert(!IsBold && "Bold is applied to end of string.");
2152 return true;
2153 }
2154}; // end class TemplateDiff
2155} // end anonymous namespace
2156
2157/// FormatTemplateTypeDiff - A helper static function to start the template
2158/// diff and return the properly formatted string. Returns true if the diff
2159/// is successful.
2160static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType,
2161 QualType ToType, bool PrintTree,
2162 bool PrintFromType, bool ElideType,
2163 bool ShowColors, raw_ostream &OS) {
2164 if (PrintTree)
2165 PrintFromType = true;
2166 TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType,
2167 ElideType, ShowColors);
2168 TD.DiffTemplate();
2169 return TD.Emit();
2170}
2171