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