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