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