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