clang 22.0.0git
ASTDiagnostic.cpp
Go to the documentation of this file.
1//===--- ASTDiagnostic.cpp - Diagnostic Printing Hooks for AST Nodes ------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements a diagnostic formatting hook for AST elements.
10//
11//===----------------------------------------------------------------------===//
12
15#include "clang/AST/ASTLambda.h"
16#include "clang/AST/Attr.h"
17#include "clang/AST/DeclObjC.h"
19#include "clang/AST/ExprCXX.h"
21#include "clang/AST/Type.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/ConvertUTF.h"
24#include "llvm/Support/Format.h"
25#include "llvm/Support/raw_ostream.h"
26
27using namespace clang;
28
29// Returns a desugared version of the QualType, and marks ShouldAKA as true
30// whenever we remove significant sugar from the type. Make sure ShouldAKA
31// is initialized before passing it in.
33 bool &ShouldAKA) {
35
36 while (true) {
37 const Type *Ty = QC.strip(QT);
38
39 // ... or a using type ...
40 if (const UsingType *UT = dyn_cast<UsingType>(Ty)) {
41 QT = UT->desugar();
42 continue;
43 }
44 // ... or a paren type ...
45 if (const ParenType *PT = dyn_cast<ParenType>(Ty)) {
46 QT = PT->desugar();
47 continue;
48 }
49 // ... or a macro defined type ...
50 if (const MacroQualifiedType *MDT = dyn_cast<MacroQualifiedType>(Ty)) {
51 QT = MDT->desugar();
52 continue;
53 }
54 // ...or a substituted template type parameter ...
55 if (const SubstTemplateTypeParmType *ST =
56 dyn_cast<SubstTemplateTypeParmType>(Ty)) {
57 QT = ST->desugar();
58 continue;
59 }
60 // ...or an attributed type...
61 if (const AttributedType *AT = dyn_cast<AttributedType>(Ty)) {
62 QT = AT->desugar();
63 continue;
64 }
65 // ...or an adjusted type...
66 if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) {
67 QT = AT->desugar();
68 continue;
69 }
70 // ... or an auto type.
71 if (const AutoType *AT = dyn_cast<AutoType>(Ty)) {
72 if (!AT->isSugared())
73 break;
74 QT = AT->desugar();
75 continue;
76 }
77
78 // Desugar FunctionType if return type or any parameter type should be
79 // desugared. Preserve nullability attribute on desugared types.
80 if (const FunctionType *FT = dyn_cast<FunctionType>(Ty)) {
81 bool DesugarReturn = false;
82 QualType SugarRT = FT->getReturnType();
83 QualType RT = desugarForDiagnostic(Context, SugarRT, DesugarReturn);
84 if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {
85 RT = Context.getAttributedType(*nullability, RT, RT);
86 }
87
88 bool DesugarArgument = false;
90 const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT);
91 if (FPT) {
92 for (QualType SugarPT : FPT->param_types()) {
93 QualType PT = desugarForDiagnostic(Context, SugarPT, DesugarArgument);
94 if (auto nullability =
95 AttributedType::stripOuterNullability(SugarPT)) {
96 PT = Context.getAttributedType(*nullability, PT, PT);
97 }
98 Args.push_back(PT);
99 }
100 }
101
102 if (DesugarReturn || DesugarArgument) {
103 ShouldAKA = true;
104 QT = FPT ? Context.getFunctionType(RT, Args, FPT->getExtProtoInfo())
105 : Context.getFunctionNoProtoType(RT, FT->getExtInfo());
106 break;
107 }
108 }
109
110 // Desugar template specializations if any template argument should be
111 // desugared.
112 if (const TemplateSpecializationType *TST =
113 dyn_cast<TemplateSpecializationType>(Ty)) {
114 if (!TST->isTypeAlias()) {
115 bool DesugarArgument = false;
117 for (const TemplateArgument &Arg : TST->template_arguments()) {
118 if (Arg.getKind() == TemplateArgument::Type)
119 Args.push_back(desugarForDiagnostic(Context, Arg.getAsType(),
120 DesugarArgument));
121 else
122 Args.push_back(Arg);
123 }
124
125 if (DesugarArgument) {
126 ShouldAKA = true;
127 QT = Context.getTemplateSpecializationType(
128 TST->getKeyword(), TST->getTemplateName(), Args,
129 /*CanonicalArgs=*/{}, QT);
130 }
131 break;
132 }
133 }
134
135 if (const auto *AT = dyn_cast<ArrayType>(Ty)) {
136 QualType ElementTy =
137 desugarForDiagnostic(Context, AT->getElementType(), ShouldAKA);
138 if (const auto *CAT = dyn_cast<ConstantArrayType>(AT))
139 QT = Context.getConstantArrayType(
140 ElementTy, CAT->getSize(), CAT->getSizeExpr(),
141 CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());
142 else if (const auto *VAT = dyn_cast<VariableArrayType>(AT))
143 QT = Context.getVariableArrayType(ElementTy, VAT->getSizeExpr(),
144 VAT->getSizeModifier(),
145 VAT->getIndexTypeCVRQualifiers());
146 else if (const auto *DSAT = dyn_cast<DependentSizedArrayType>(AT))
147 QT = Context.getDependentSizedArrayType(
148 ElementTy, DSAT->getSizeExpr(), DSAT->getSizeModifier(),
149 DSAT->getIndexTypeCVRQualifiers());
150 else if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT))
151 QT = Context.getIncompleteArrayType(ElementTy, IAT->getSizeModifier(),
152 IAT->getIndexTypeCVRQualifiers());
153 else
154 llvm_unreachable("Unhandled array type");
155 break;
156 }
157
158 // Don't desugar magic Objective-C types.
159 if (QualType(Ty,0) == Context.getObjCIdType() ||
160 QualType(Ty,0) == Context.getObjCClassType() ||
161 QualType(Ty,0) == Context.getObjCSelType() ||
162 QualType(Ty,0) == Context.getObjCProtoType())
163 break;
164
165 // Don't desugar va_list.
166 if (QualType(Ty, 0) == Context.getBuiltinVaListType() ||
167 QualType(Ty, 0) == Context.getBuiltinMSVaListType())
168 break;
169
170 // Otherwise, do a single-step desugar.
171 QualType Underlying;
172 bool IsSugar = false;
173 switch (Ty->getTypeClass()) {
174#define ABSTRACT_TYPE(Class, Base)
175#define TYPE(Class, Base) \
176case Type::Class: { \
177const Class##Type *CTy = cast<Class##Type>(Ty); \
178if (CTy->isSugared()) { \
179IsSugar = true; \
180Underlying = CTy->desugar(); \
181} \
182break; \
183}
184#include "clang/AST/TypeNodes.inc"
185 }
186
187 // If it wasn't sugared, we're done.
188 if (!IsSugar)
189 break;
190
191 // If the desugared type is a vector type, we don't want to expand
192 // it, it will turn into an attribute mess. People want their "vec4".
193 if (isa<VectorType>(Underlying))
194 break;
195
196 // Don't desugar through the primary typedef of an anonymous type.
197 if (const TagType *UTT = Underlying->getAs<TagType>())
198 if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))
199 if (UTT->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);
458 ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), Qualified);
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
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.
650 SmallVector<DiffNode, 16> FlatTree;
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.
992 const TemplateSpecializationType *TST;
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 =
1144 Ty->getAs<TemplateSpecializationType>())
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
1155 const ClassTemplateSpecializationDecl *CTSD =
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 &&
1230 FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl());
1231 }
1232
1233 /// InitializeNonTypeDiffVariables - Helper function for DiffNonTypes
1234 static void InitializeNonTypeDiffVariables(ASTContext &Context,
1235 const TSTiterator &Iter,
1236 NonTypeTemplateParmDecl *Default,
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)
1405 ->getTemplateParameters();
1406 TemplateParameterList *ParamsTo =
1407 ToTST->getTemplateName()
1408 .getAsTemplateDecl(/*IgnoreDeduced=*/true)
1409 ->getTemplateParameters();
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 =
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(
1449 SmallVectorImpl<const TemplateSpecializationType *> &TemplateList,
1450 const TemplateSpecializationType *TST) {
1451 while (TST) {
1452 TemplateList.push_back(TST);
1453 if (!TST->isTypeAlias())
1454 return;
1455 TST = TST->getAliasedType()->getAs<TemplateSpecializationType>();
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) ==
1466 Context.getCanonicalTemplateName(ToTST->getTemplateName(),
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.
1482 SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,
1483 ToTemplateList;
1484
1485 makeTemplateList(FromTemplateList, FromTST);
1486 makeTemplateList(ToTemplateList, ToTST);
1487
1488 SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator
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
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.
This file provides some common utility functions for processing Lambda related AST Constructs.
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
Definition CharUnits.h:225
Defines the C++ template declaration subclasses.
Defines the clang::Expr interface and subclasses for C++ expressions.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:188
Represents a type which was implicitly adjusted by the semantic engine for arbitrary reasons.
Definition TypeBase.h:3489
Attr - This represents one attribute.
Definition Attr.h:44
const char * getSpelling() const
std::string getNormalizedFullName() const
Gets the normalized full name, which consists of both scope and name and with surrounding underscores...
const IdentifierInfo * getScopeName() const
const IdentifierInfo * getAttrName() const
bool isStandardAttributeSyntax() const
The attribute is spelled [[]] in either C or C++ mode, including standard attributes spelled with a k...
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:5264
ExtProtoInfo getExtProtoInfo() const
Definition TypeBase.h:5553
ArrayRef< QualType > param_types() const
Definition TypeBase.h:5704
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4460
StringRef getName() const
Return the actual identifier string.
An lvalue reference type, per C++11 [dcl.ref].
Definition TypeBase.h:3615
Sugar type that represents a type that was qualified by a qualifier written as a macro invocation.
Definition TypeBase.h:6143
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)
Represents a pointer to an Objective C object.
Definition TypeBase.h:7903
Sugar for parentheses used when specifying types.
Definition TypeBase.h:3302
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
A (possibly-)qualified type.
Definition TypeBase.h:937
QualType getLocalUnqualifiedType() const
Return this type with all of the instance-specific qualifiers removed, but without removing any quali...
Definition TypeBase.h:1225
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
static QualType getFromOpaquePtr(const void *Ptr)
Definition TypeBase.h:986
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8325
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
QualType getCanonicalType() const
Definition TypeBase.h:8337
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:8317
A qualifier set is used to build a set of qualifiers.
Definition TypeBase.h:8225
const Type * strip(QualType type)
Collect any qualifiers on the given type and return an unqualified type.
Definition TypeBase.h:8232
QualType apply(const ASTContext &Context, QualType QT) const
Apply the collected qualifiers to the given type.
Definition Type.cpp:4666
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:3633
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.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
Represents a template argument.
QualType getParamTypeForDecl() const
Expr * getAsExpr() const
Retrieve the template argument as an expression.
pack_iterator pack_end() const
Iterator referencing one past the last argument of a template argument pack.
const TemplateArgument * pack_iterator
Iterator that traverses the elements of a template argument pack.
pack_iterator pack_begin() const
Iterator referencing the first argument of a template argument pack.
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
QualType getIntegralType() const
Retrieve the type of the integral value.
ValueDecl * getAsDecl() const
Retrieve the declaration for a declaration non-type template argument.
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
@ Template
The template argument is a template name that was provided for a template template parameter.
@ StructuralValue
The template argument is a non-type template argument that can't be represented by the special-case D...
@ Pack
The template argument is actually a parameter pack.
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
@ Type
The template argument is a type.
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
ArgKind getKind() const
Return the kind of stored template argument.
NamedDecl * getParam(unsigned Idx)
Represents a declaration of a type.
Definition Decl.h:3510
The base class of the type hierarchy.
Definition TypeBase.h:1833
bool isBooleanType() const
Definition TypeBase.h:9008
bool isPointerType() const
Definition TypeBase.h:8522
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
TypeClass getTypeClass() const
Definition TypeBase.h:2385
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9101
QualType getType() const
Definition Decl.h:722
Represents a GCC generic vector type.
Definition TypeBase.h:4173
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
QualType desugarForDiagnostic(ASTContext &Context, QualType QT, bool &ShouldAKA)
Returns a desugared version of the QualType, and marks ShouldAKA as true whenever we remove significa...
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
Definition Parser.h:61
std::string FormatUTFCodeUnitAsCodepoint(unsigned Value, QualType T)
nullptr
This class represents a compute construct, representing a 'Kind' of β€˜parallel’, 'serial',...
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
Definition JsonSupport.h:21
bool isLambdaCallOperator(const CXXMethodDecl *MD)
Definition ASTLambda.h:28
const FunctionProtoType * T
@ Template
We are parsing a template declaration.
Definition Parser.h:81
void EscapeStringForDiagnostic(StringRef Str, SmallVectorImpl< char > &OutStr)
EscapeStringForDiagnostic - Append Str to the diagnostic buffer, escaping non-printable characters an...
LangAS
Defines the address space values used by the address space qualifier of QualType.
const char ToggleHighlight
Special character that the diagnostic printer will use to toggle the bold attribute.
void FormatASTNodeDiagnosticArgument(DiagnosticsEngine::ArgumentKind Kind, intptr_t Val, StringRef Modifier, StringRef Argument, ArrayRef< DiagnosticsEngine::ArgumentValue > PrevArgs, SmallVectorImpl< char > &Output, void *Cookie, ArrayRef< intptr_t > QualTypeVals)
DiagnosticsEngine argument formatting function for diagnostics that involve AST nodes.
U cast(CodeGen::Address addr)
Definition Address.h:327
__INTPTR_TYPE__ intptr_t
A signed integer type with the property that any valid pointer to void can be converted to this type,...
#define false
Definition stdbool.h:26
Describes how types, statements, expressions, and declarations should be printed.