clang: lib/AST/ASTDiagnostic.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
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
30
31
33 bool &ShouldAKA) {
35
36 while (true) {
38
39
40 if (const UsingType *UT = dyn_cast(Ty)) {
41 QT = UT->desugar();
42 continue;
43 }
44
45 if (const ParenType *PT = dyn_cast(Ty)) {
46 QT = PT->desugar();
47 continue;
48 }
49
50 if (const MacroQualifiedType *MDT = dyn_cast(Ty)) {
51 QT = MDT->desugar();
52 continue;
53 }
54
55 if (const SubstTemplateTypeParmType *ST =
56 dyn_cast(Ty)) {
57 QT = ST->desugar();
58 continue;
59 }
60
61 if (const AttributedType *AT = dyn_cast(Ty)) {
62 QT = AT->desugar();
63 continue;
64 }
65
66 if (const AdjustedType *AT = dyn_cast(Ty)) {
67 QT = AT->desugar();
68 continue;
69 }
70
71 if (const AutoType *AT = dyn_cast(Ty)) {
72 if (!AT->isSugared())
73 break;
74 QT = AT->desugar();
75 continue;
76 }
77
78
79
80 if (const FunctionType *FT = dyn_cast(Ty)) {
81 bool DesugarReturn = false;
82 QualType SugarRT = FT->getReturnType();
84 if (auto nullability = AttributedType::stripOuterNullability(SugarRT)) {
85 RT = Context.getAttributedType(*nullability, RT, RT);
86 }
87
88 bool DesugarArgument = false;
91 if (FPT) {
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
111
112 if (const TemplateSpecializationType *TST =
113 dyn_cast(Ty)) {
114 if (!TST->isTypeAlias()) {
115 bool DesugarArgument = false;
117 for (const TemplateArgument &Arg : TST->template_arguments()) {
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 {}, QT);
130 }
131 break;
132 }
133 }
134
135 if (const auto *AT = dyn_cast(Ty)) {
138 if (const auto *CAT = dyn_cast(AT))
139 QT = Context.getConstantArrayType(
140 ElementTy, CAT->getSize(), CAT->getSizeExpr(),
141 CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());
142 else if (const auto *VAT = dyn_cast(AT))
143 QT = Context.getVariableArrayType(ElementTy, VAT->getSizeExpr(),
144 VAT->getSizeModifier(),
145 VAT->getIndexTypeCVRQualifiers());
146 else if (const auto *DSAT = dyn_cast(AT))
147 QT = Context.getDependentSizedArrayType(
148 ElementTy, DSAT->getSizeExpr(), DSAT->getSizeModifier(),
149 DSAT->getIndexTypeCVRQualifiers());
150 else if (const auto *IAT = dyn_cast(AT))
151 QT = Context.getIncompleteArrayType(ElementTy, IAT->getSizeModifier(),
152 IAT->getIndexTypeCVRQualifiers());
153 else
154 llvm_unreachable("Unhandled array type");
155 break;
156 }
157
158
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
166 if (QualType(Ty, 0) == Context.getBuiltinVaListType() ||
167 QualType(Ty, 0) == Context.getBuiltinMSVaListType())
168 break;
169
170
172 bool IsSugar = false;
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
188 if (!IsSugar)
189 break;
190
191
192
194 break;
195
196
197 if (const TagType *UTT = Underlying->getAs())
198 if (const TypedefType *QTT = dyn_cast(QT))
199 if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
200 break;
201
202
203 ShouldAKA = true;
204 QT = Underlying;
205 }
206
207
208
210 QT = Context.getPointerType(
213 QT = Context.getObjCObjectPointerType(
216 QT = Context.getLValueReferenceType(
219 QT = Context.getRValueReferenceType(
222 if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {
225 QT = Context.getObjCObjectType(
226 BaseType, Ty->getTypeArgsAsWritten(),
227 ArrayRef(Ty->qual_begin(), Ty->getNumProtocols()),
228 Ty->isKindOfTypeAsWritten());
229 }
230 }
231
232 return QC.apply(Context, QT);
233}
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259static std::string
263
264 bool ForceAKA = false;
266 std::string S = Ty.getAsString(Context.getPrintingPolicy());
267 std::string CanS = CanTy.getAsString(Context.getPrintingPolicy());
268
269 for (const intptr_t &QualTypeVal : QualTypeVals) {
272 if (CompareTy.isNull())
273 continue;
274 if (CompareTy == Ty)
275 continue;
277 if (CompareCanTy == CanTy)
278 continue;
279 std::string CompareS = CompareTy.getAsString(Context.getPrintingPolicy());
280 bool ShouldAKA = false;
283 std::string CompareDesugarStr =
284 CompareDesugar.getAsString(Context.getPrintingPolicy());
285 if (CompareS != S && CompareDesugarStr != S)
286 continue;
287
288 std::string CompareCanS =
289 CompareCanTy.getAsString(Context.getPrintingPolicy());
290
291 if (CompareCanS == CanS)
292 continue;
293
294 ForceAKA = true;
295 break;
296 }
297
298
299
300 bool Repeated = false;
301 for (const auto &PrevArg : PrevArgs) {
302
306 if (PrevTy == Ty) {
307 Repeated = true;
308 break;
309 }
310 }
311 }
312
313
314
315 if (!Repeated) {
316 bool ShouldAKA = false;
318 if (ShouldAKA || ForceAKA) {
319 if (DesugaredTy == Ty) {
321 }
322 std::string akaStr = DesugaredTy.getAsString(Context.getPrintingPolicy());
323 if (akaStr != S) {
324 S = "'" + S + "' (aka '" + akaStr + "')";
325 return S;
326 }
327 }
328
329
330
331
333 std::string DecoratedString;
334 llvm::raw_string_ostream OS(DecoratedString);
335 const char *Values = VTy->getNumElements() > 1 ? "values" : "value";
336 OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '"
337 << VTy->getElementType().getAsString(Context.getPrintingPolicy())
338 << "' " << Values << ")";
339 return DecoratedString;
340 }
341 }
342
343 S = "'" + S + "'";
344 return S;
345}
346
348 QualType ToType, bool PrintTree,
349 bool PrintFromType, bool ElideType,
350 bool ShowColors, raw_ostream &OS);
351
355 StringRef Modifier,
356 StringRef Argument,
359 void *Cookie,
362
363 size_t OldEnd = Output.size();
364 llvm::raw_svector_ostream OS(Output);
365 bool NeedQuotes = true;
366
367 switch (Kind) {
368 default: llvm_unreachable("unknown ArgumentKind");
370 assert(Modifier.empty() && Argument.empty() &&
371 "Invalid modifier for Qualifiers argument");
372
374 if (S.empty()) {
375 OS << (Context.getLangOpts().OpenCL ? "default" : "generic");
376 OS << " address space";
377 } else {
378 OS << "address space";
379 OS << " '" << S << "'";
380 }
381 NeedQuotes = false;
382 break;
383 }
385 assert(Modifier.empty() && Argument.empty() &&
386 "Invalid modifier for Qualifiers argument");
387
390 if (S.empty()) {
391 OS << "unqualified";
392 NeedQuotes = false;
393 } else {
394 OS << S;
395 }
396 break;
397 }
404
410 break;
411 }
412
413
414
416 return;
417
418
419
421 Modifier = StringRef();
422 Argument = StringRef();
423
424 [[fallthrough]];
425 }
427 assert(Modifier.empty() && Argument.empty() &&
428 "Invalid modifier for QualType argument");
429
432 NeedQuotes = false;
433 break;
434 }
436 if (Modifier == "objcclass" && Argument.empty())
437 OS << '+';
438 else if (Modifier == "objcinstance" && Argument.empty())
439 OS << '-';
440 else
441 assert(Modifier.empty() && Argument.empty() &&
442 "Invalid modifier for DeclarationName argument");
443
445 break;
446 }
449 if (Modifier == "q" && Argument.empty())
451 else {
452 assert(Modifier.empty() && Argument.empty() &&
453 "Invalid modifier for NamedDecl* argument");
455 }
458 break;
459 }
462 .print(OS, Context.getPrintingPolicy(),
463 false,
464 false);
465 break;
468 assert(DC && "Should never have a null declaration context");
469 NeedQuotes = false;
470
471
473 if (Context.getLangOpts().CPlusPlus)
474 OS << "the global namespace";
475 else
476 OS << "the global scope";
478 OS << "block literal";
480 OS << "lambda expression";
481 } else if (TypeDecl *Type = dyn_cast(DC)) {
483 Context, Context.getTypeDeclType(Type), PrevArgs, QualTypeVals);
484 } else {
485 assert(isa(DC) && "Expected a NamedDecl");
488 OS << "namespace ";
490 OS << "method ";
492 OS << "function ";
493
494 OS << '\'';
496 OS << '\'';
497 }
498 break;
499 }
501 const Attr *At = reinterpret_cast<Attr *>(Val);
502 assert(At && "Received null Attr object!");
503
504 OS << '\'';
508 } else {
510 }
511 OS << '\'';
512 NeedQuotes = false;
513 break;
514 }
516 const Expr *E = reinterpret_cast<Expr *>(Val);
517 assert(E && "Received null Expr!");
518 E->printPretty(OS, nullptr, Context.getPrintingPolicy());
519 break;
520 }
523 assert(AT && "Received null AttributeCommonInfo object!");
524
525 OS << '\'';
528 } else {
530 }
531 OS << '\'';
532 NeedQuotes = false;
533 break;
534 }
535 }
536
537 if (NeedQuotes) {
538 Output.insert(Output.begin()+OldEnd, '\'');
539 Output.push_back('\'');
540 }
541}
542
543
544
545
546
547namespace {
548class TemplateDiff {
549
551
552
554
555
556 bool ElideType;
557
558
559 bool PrintTree;
560
561
562 bool ShowColor;
563
564
565
566
568
569
570
572
573
574 raw_ostream &OS;
575
576
577 bool IsBold;
578
579
580 class DiffTree {
581 public:
582
583
584
585 enum DiffKind {
586
588
590
591
593
594
595
597
598 TemplateTemplate,
599
601
603
604 FromIntegerAndToDeclaration,
605 FromDeclarationAndToInteger
606 };
607
608 private:
609
610
611
612 struct TemplateArgumentInfo {
613 QualType ArgType;
614 Qualifiers Qual;
615 llvm::APSInt Val;
616 bool IsValidInt = false;
617 Expr *ArgExpr = nullptr;
618 TemplateDecl *TD = nullptr;
619 ValueDecl *VD = nullptr;
620 bool NeedAddressOf = false;
621 bool IsNullPtr = false;
622 bool IsDefault = false;
623 };
624
625
626
627
628 struct DiffNode {
630
631
632 unsigned NextNode = 0;
633
634
635 unsigned ChildNode = 0;
636
637
638 unsigned ParentNode = 0;
639
640 TemplateArgumentInfo FromArgInfo, ToArgInfo;
641
642
643 bool Same = false;
644
645 DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {}
646 };
647
648
649 SmallVector<DiffNode, 16> FlatTree;
650
651
652 unsigned CurrentNode;
653
654
655
656 unsigned NextFreeNode;
657
658
659 unsigned ReadNode;
660
661 public:
662 DiffTree() : CurrentNode(0), NextFreeNode(1), ReadNode(0) {
663 FlatTree.push_back(DiffNode());
664 }
665
666
667 void SetTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,
668 Qualifiers FromQual, Qualifiers ToQual,
669 bool FromDefault, bool ToDefault) {
670 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
671 FlatTree[CurrentNode].Kind = Template;
672 FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
673 FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
674 FlatTree[CurrentNode].FromArgInfo.Qual = FromQual;
675 FlatTree[CurrentNode].ToArgInfo.Qual = ToQual;
676 SetDefault(FromDefault, ToDefault);
677 }
678
679 void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault,
680 bool ToDefault) {
681 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
682 FlatTree[CurrentNode].Kind = Type;
683 FlatTree[CurrentNode].FromArgInfo.ArgType = FromType;
684 FlatTree[CurrentNode].ToArgInfo.ArgType = ToType;
685 SetDefault(FromDefault, ToDefault);
686 }
687
688 void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault,
689 bool ToDefault) {
690 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
691 FlatTree[CurrentNode].Kind = Expression;
692 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
693 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
694 SetDefault(FromDefault, ToDefault);
695 }
696
697 void SetTemplateTemplateDiff(TemplateDecl *FromTD, TemplateDecl *ToTD,
698 bool FromDefault, bool ToDefault) {
699 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
700 FlatTree[CurrentNode].Kind = TemplateTemplate;
701 FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
702 FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
703 SetDefault(FromDefault, ToDefault);
704 }
705
706 void SetIntegerDiff(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
707 bool IsValidFromInt, bool IsValidToInt,
708 QualType FromIntType, QualType ToIntType,
709 Expr *FromExpr, Expr *ToExpr, bool FromDefault,
710 bool ToDefault) {
711 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
712 FlatTree[CurrentNode].Kind = Integer;
713 FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
714 FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
715 FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
716 FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
717 FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
718 FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
719 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
720 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
721 SetDefault(FromDefault, ToDefault);
722 }
723
724 void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
725 bool FromAddressOf, bool ToAddressOf,
726 bool FromNullPtr, bool ToNullPtr, Expr *FromExpr,
727 Expr *ToExpr, bool FromDefault, bool ToDefault) {
728 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
729 FlatTree[CurrentNode].Kind = Declaration;
730 FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
731 FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
732 FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
733 FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
734 FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
735 FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
736 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
737 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
738 SetDefault(FromDefault, ToDefault);
739 }
740
741 void SetFromDeclarationAndToIntegerDiff(
742 ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr,
743 Expr *FromExpr, const llvm::APSInt &ToInt, bool IsValidToInt,
744 QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) {
745 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
746 FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger;
747 FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
748 FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
749 FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
750 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
751 FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
752 FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
753 FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
754 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
755 SetDefault(FromDefault, ToDefault);
756 }
757
758 void SetFromIntegerAndToDeclarationDiff(
759 const llvm::APSInt &FromInt, bool IsValidFromInt, QualType FromIntType,
760 Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf,
761 bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) {
762 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
763 FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration;
764 FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
765 FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
766 FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
767 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
768 FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
769 FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
770 FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
771 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
772 SetDefault(FromDefault, ToDefault);
773 }
774
775
776 void SetDefault(bool FromDefault, bool ToDefault) {
777 assert((!FromDefault || !ToDefault) && "Both arguments cannot be default.");
778 FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault;
779 FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault;
780 }
781
782
783 void SetSame(bool Same) {
784 FlatTree[CurrentNode].Same = Same;
785 }
786
787
788 void SetKind(DiffKind Kind) {
789 FlatTree[CurrentNode].Kind = Kind;
790 }
791
792
793 void Up() {
794 assert(FlatTree[CurrentNode].Kind != Invalid &&
795 "Cannot exit node before setting node information.");
796 CurrentNode = FlatTree[CurrentNode].ParentNode;
797 }
798
799
800
801 void AddNode() {
802 assert(FlatTree[CurrentNode].Kind == Template &&
803 "Only Template nodes can have children nodes.");
804 FlatTree.push_back(DiffNode(CurrentNode));
805 DiffNode &Node = FlatTree[CurrentNode];
806 if (Node.ChildNode == 0) {
807
808 Node.ChildNode = NextFreeNode;
809 } else {
810
811
812 unsigned i;
813 for (i = Node.ChildNode; FlatTree[i].NextNode != 0;
814 i = FlatTree[i].NextNode) {
815 }
816 FlatTree[i].NextNode = NextFreeNode;
817 }
818 CurrentNode = NextFreeNode;
819 ++NextFreeNode;
820 }
821
822
823
824 void StartTraverse() {
825 ReadNode = 0;
826 CurrentNode = NextFreeNode;
827 NextFreeNode = 0;
828 }
829
830
831 void Parent() {
832 ReadNode = FlatTree[ReadNode].ParentNode;
833 }
834
835 void GetTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD,
836 Qualifiers &FromQual, Qualifiers &ToQual) {
837 assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind.");
838 FromTD = FlatTree[ReadNode].FromArgInfo.TD;
839 ToTD = FlatTree[ReadNode].ToArgInfo.TD;
840 FromQual = FlatTree[ReadNode].FromArgInfo.Qual;
841 ToQual = FlatTree[ReadNode].ToArgInfo.Qual;
842 }
843
844 void GetTypeDiff(QualType &FromType, QualType &ToType) {
845 assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind");
846 FromType = FlatTree[ReadNode].FromArgInfo.ArgType;
847 ToType = FlatTree[ReadNode].ToArgInfo.ArgType;
848 }
849
850 void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) {
851 assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind");
852 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
853 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
854 }
855
856 void GetTemplateTemplateDiff(TemplateDecl *&FromTD, TemplateDecl *&ToTD) {
857 assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind.");
858 FromTD = FlatTree[ReadNode].FromArgInfo.TD;
859 ToTD = FlatTree[ReadNode].ToArgInfo.TD;
860 }
861
862 void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
863 bool &IsValidFromInt, bool &IsValidToInt,
864 QualType &FromIntType, QualType &ToIntType,
865 Expr *&FromExpr, Expr *&ToExpr) {
866 assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind.");
867 FromInt = FlatTree[ReadNode].FromArgInfo.Val;
868 ToInt = FlatTree[ReadNode].ToArgInfo.Val;
869 IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
870 IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
871 FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
872 ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
873 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
874 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
875 }
876
877 void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
878 bool &FromAddressOf, bool &ToAddressOf,
879 bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr,
880 Expr *&ToExpr) {
881 assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind.");
882 FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
883 ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
884 FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
885 ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
886 FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
887 ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
888 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
889 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
890 }
891
892 void GetFromDeclarationAndToIntegerDiff(
893 ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr,
894 Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt,
895 QualType &ToIntType, Expr *&ToExpr) {
896 assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger &&
897 "Unexpected kind.");
898 FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
899 FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
900 FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
901 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
902 ToInt = FlatTree[ReadNode].ToArgInfo.Val;
903 IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
904 ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
905 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
906 }
907
908 void GetFromIntegerAndToDeclarationDiff(
909 llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType,
910 Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf,
911 bool &ToNullPtr, Expr *&ToExpr) {
912 assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration &&
913 "Unexpected kind.");
914 FromInt = FlatTree[ReadNode].FromArgInfo.Val;
915 IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
916 FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
917 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
918 ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
919 ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
920 ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
921 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
922 }
923
924
925 bool FromDefault() {
926 return FlatTree[ReadNode].FromArgInfo.IsDefault;
927 }
928
929
930 bool ToDefault() {
931 return FlatTree[ReadNode].ToArgInfo.IsDefault;
932 }
933
934
935 bool NodeIsSame() {
936 return FlatTree[ReadNode].Same;
937 }
938
939
940 bool HasChildren() {
941 return FlatTree[ReadNode].ChildNode != 0;
942 }
943
944
945 void MoveToChild() {
946 ReadNode = FlatTree[ReadNode].ChildNode;
947 }
948
949
950
951 bool AdvanceSibling() {
952 if (FlatTree[ReadNode].NextNode == 0)
953 return false;
954
955 ReadNode = FlatTree[ReadNode].NextNode;
956 return true;
957 }
958
959
960 bool HasNextSibling() {
961 return FlatTree[ReadNode].NextNode != 0;
962 }
963
964
966 return GetKind() == Invalid;
967 }
968
969
970 DiffKind GetKind() {
971 return FlatTree[ReadNode].Kind;
972 }
973 };
974
975 DiffTree Tree;
976
977
978
979
980
981 class TSTiterator {
982 typedef const TemplateArgument& reference;
983 typedef const TemplateArgument* pointer;
984
985
986
987
988 struct InternalIterator {
989
990
991 const TemplateSpecializationType *TST;
992
993
994 unsigned Index;
995
996
997
999
1000
1002
1003
1004
1005 InternalIterator(const TemplateSpecializationType *TST)
1006 : TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) {
1007 if (!TST) return;
1008
1009 if (isEnd()) return;
1010
1011
1012 TemplateArgument TA = TST->template_arguments()[0];
1014
1015
1018
1019
1020 if (CurrentTA != EndTA) return;
1021
1022
1023
1024 ++(*this);
1025 }
1026
1027
1028 bool isValid() const { return TST; }
1029
1030
1031 bool isEnd() const {
1032 assert(TST && "InternalIterator is invalid with a null TST.");
1033 return Index >= TST->template_arguments().size();
1034 }
1035
1036
1037 InternalIterator &operator++() {
1038 assert(TST && "InternalIterator is invalid with a null TST.");
1039 if (isEnd()) {
1040 return *this;
1041 }
1042
1043
1044 if (CurrentTA != EndTA) {
1045 ++CurrentTA;
1046 if (CurrentTA != EndTA)
1047 return *this;
1048 }
1049
1050
1051 while (true) {
1052
1053 if (++Index == TST->template_arguments().size())
1054 break;
1055
1056
1057 TemplateArgument TA = TST->template_arguments()[Index];
1059 break;
1060
1061
1064
1065
1066 if (CurrentTA != EndTA)
1067 break;
1068 }
1069 return *this;
1070 }
1071
1072
1074 assert(TST && "InternalIterator is invalid with a null TST.");
1075 assert(!isEnd() && "Index exceeds number of arguments.");
1076 if (CurrentTA == EndTA)
1077 return TST->template_arguments()[Index];
1078 else
1079 return *CurrentTA;
1080 }
1081
1082
1083 pointer operator->() const {
1084 assert(TST && "InternalIterator is invalid with a null TST.");
1086 }
1087 };
1088
1089 InternalIterator SugaredIterator;
1090 InternalIterator DesugaredIterator;
1091
1092 public:
1093 TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST)
1094 : SugaredIterator(TST),
1095 DesugaredIterator(
1096 (TST->isSugared() && !TST->isTypeAlias())
1097 ? GetTemplateSpecializationType(Context, TST->desugar())
1099
1100
1101 TSTiterator &operator++() {
1102 ++SugaredIterator;
1103 if (DesugaredIterator.isValid())
1104 ++DesugaredIterator;
1105 return *this;
1106 }
1107
1108
1110 return *SugaredIterator;
1111 }
1112
1113
1114 pointer operator->() const {
1116 }
1117
1118
1119 bool isEnd() const {
1120 return SugaredIterator.isEnd();
1121 }
1122
1123
1124
1125 bool hasDesugaredTA() const {
1126 return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();
1127 }
1128
1129
1130 reference getDesugaredTA() const {
1131 assert(DesugaredIterator.isValid() &&
1132 "Desugared TemplateArgument should not be used.");
1133 return *DesugaredIterator;
1134 }
1135 };
1136
1137
1138
1139
1140 static const TemplateSpecializationType *
1141 GetTemplateSpecializationType(ASTContext &Context, QualType Ty) {
1142 if (const TemplateSpecializationType *TST =
1143 Ty->getAs())
1144 return TST;
1145
1146 if (const auto* SubstType = Ty->getAs())
1147 Ty = SubstType->getReplacementType();
1148
1149 const auto *RT = Ty->getAs();
1150 if (!RT)
1151 return nullptr;
1152
1153 const auto *CTSD = dyn_cast(RT->getDecl());
1154 if (!CTSD)
1155 return nullptr;
1156
1157 Ty = Context.getTemplateSpecializationType(
1158 ElaboratedTypeKeyword::None,
1159 TemplateName(CTSD->getSpecializedTemplate()),
1160 CTSD->getTemplateArgs().asArray(), {},
1162
1163 return Ty->getAs();
1164 }
1165
1166
1167 static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType,
1168 QualType ToType,
1169 const TemplateSpecializationType *&FromArgTST,
1170 const TemplateSpecializationType *&ToArgTST) {
1172 return true;
1173
1174 if (Context.hasSameType(FromType, ToType))
1175 return true;
1176
1177 FromArgTST = GetTemplateSpecializationType(Context, FromType);
1178 ToArgTST = GetTemplateSpecializationType(Context, ToType);
1179
1180 if (!FromArgTST || !ToArgTST)
1181 return true;
1182
1183 if (!hasSameTemplate(Context, FromArgTST, ToArgTST))
1184 return true;
1185
1186 return false;
1187 }
1188
1189
1190 void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) {
1191 QualType FromType = GetType(FromIter);
1192 QualType ToType = GetType(ToIter);
1193
1194 bool FromDefault = FromIter.isEnd() && !FromType.isNull();
1195 bool ToDefault = ToIter.isEnd() && !ToType.isNull();
1196
1197 const TemplateSpecializationType *FromArgTST = nullptr;
1198 const TemplateSpecializationType *ToArgTST = nullptr;
1199 if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) {
1200 Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault);
1201 Tree.SetSame(!FromType.isNull() && !ToType.isNull() &&
1202 Context.hasSameType(FromType, ToType));
1203 } else {
1204 assert(FromArgTST && ToArgTST &&
1205 "Both template specializations need to be valid.");
1208 FromQual -= QualType(FromArgTST, 0).getQualifiers();
1209 ToQual -= QualType(ToArgTST, 0).getQualifiers();
1210 Tree.SetTemplateDiff(FromArgTST->getTemplateName().getAsTemplateDecl(),
1211 ToArgTST->getTemplateName().getAsTemplateDecl(),
1212 FromQual, ToQual, FromDefault, ToDefault);
1213 DiffTemplate(FromArgTST, ToArgTST);
1214 }
1215 }
1216
1217
1218
1219 void DiffTemplateTemplates(const TSTiterator &FromIter,
1220 const TSTiterator &ToIter) {
1221 TemplateDecl *FromDecl = GetTemplateDecl(FromIter);
1222 TemplateDecl *ToDecl = GetTemplateDecl(ToIter);
1223 Tree.SetTemplateTemplateDiff(FromDecl, ToDecl, FromIter.isEnd() && FromDecl,
1224 ToIter.isEnd() && ToDecl);
1225 Tree.SetSame(FromDecl && ToDecl &&
1227 }
1228
1229
1230 static void InitializeNonTypeDiffVariables(ASTContext &Context,
1231 const TSTiterator &Iter,
1232 NonTypeTemplateParmDecl *Default,
1233 llvm::APSInt &Value, bool &HasInt,
1234 QualType &IntType, bool &IsNullPtr,
1235 Expr *&E, ValueDecl *&VD,
1236 bool &NeedAddressOf) {
1237 if (!Iter.isEnd()) {
1238 switch (Iter->getKind()) {
1240
1241
1242
1243 return;
1245 Value = Iter->getAsIntegral();
1246 HasInt = true;
1247 IntType = Iter->getIntegralType();
1248 return;
1250 VD = Iter->getAsDecl();
1251 QualType ArgType = Iter->getParamTypeForDecl();
1252 QualType VDType = VD->getType();
1254 Context.hasSameType(ArgType->getPointeeType(), VDType))
1255 NeedAddressOf = true;
1256 return;
1257 }
1259 IsNullPtr = true;
1260 return;
1262 E = Iter->getAsExpr();
1263 break;
1268 llvm_unreachable("TemplateArgument kind is not expected for NTTP");
1270 llvm_unreachable("TemplateArgument kind should be handled elsewhere");
1271 }
1272 } else if (->isParameterPack()) {
1273 E = Default->getDefaultArgument().getArgument().getAsExpr();
1274 }
1275
1276 if (!Iter.hasDesugaredTA())
1277 return;
1278
1279 const TemplateArgument &TA = Iter.getDesugaredTA();
1282
1283
1284 return;
1287 HasInt = true;
1289 return;
1293 QualType VDType = VD->getType();
1295 Context.hasSameType(ArgType->getPointeeType(), VDType))
1296 NeedAddressOf = true;
1297 return;
1298 }
1300 IsNullPtr = true;
1301 return;
1303
1304
1305
1306 if (!E)
1308 return;
1313 llvm_unreachable("TemplateArgument kind is not expected for NTTP");
1315 llvm_unreachable("TemplateArgument kind should be handled elsewhere");
1316 }
1317 llvm_unreachable("Unexpected TemplateArgument kind");
1318 }
1319
1320
1321
1322 void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
1323 NonTypeTemplateParmDecl *FromDefaultNonTypeDecl,
1324 NonTypeTemplateParmDecl *ToDefaultNonTypeDecl) {
1325 Expr *FromExpr = nullptr, *ToExpr = nullptr;
1326 llvm::APSInt FromInt, ToInt;
1327 QualType FromIntType, ToIntType;
1328 ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
1329 bool HasFromInt = false, HasToInt = false, FromNullPtr = false,
1330 ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;
1331 InitializeNonTypeDiffVariables(
1332 Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt,
1333 FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf);
1334 InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt,
1335 HasToInt, ToIntType, ToNullPtr, ToExpr,
1336 ToValueDecl, NeedToAddressOf);
1337
1338 bool FromDefault = FromIter.isEnd() &&
1339 (FromExpr || FromValueDecl || HasFromInt || FromNullPtr);
1340 bool ToDefault = ToIter.isEnd() &&
1341 (ToExpr || ToValueDecl || HasToInt || ToNullPtr);
1342
1343 bool FromDeclaration = FromValueDecl || FromNullPtr;
1344 bool ToDeclaration = ToValueDecl || ToNullPtr;
1345
1346 if (FromDeclaration && HasToInt) {
1347 Tree.SetFromDeclarationAndToIntegerDiff(
1348 FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt,
1349 HasToInt, ToIntType, ToExpr, FromDefault, ToDefault);
1350 Tree.SetSame(false);
1351 return;
1352
1353 }
1354
1355 if (HasFromInt && ToDeclaration) {
1356 Tree.SetFromIntegerAndToDeclarationDiff(
1357 FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl,
1358 NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault);
1359 Tree.SetSame(false);
1360 return;
1361 }
1362
1363 if (HasFromInt || HasToInt) {
1364 Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,
1365 ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);
1366 if (HasFromInt && HasToInt) {
1367 Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) &&
1368 FromInt == ToInt);
1369 }
1370 return;
1371 }
1372
1373 if (FromDeclaration || ToDeclaration) {
1374 Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf,
1375 NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
1376 ToExpr, FromDefault, ToDefault);
1377 bool BothNull = FromNullPtr && ToNullPtr;
1378 bool SameValueDecl =
1379 FromValueDecl && ToValueDecl &&
1380 NeedFromAddressOf == NeedToAddressOf &&
1382 Tree.SetSame(BothNull || SameValueDecl);
1383 return;
1384 }
1385
1386 assert((FromExpr || ToExpr) && "Both template arguments cannot be empty.");
1387 Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault);
1388 Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
1389 }
1390
1391
1392
1393 void DiffTemplate(const TemplateSpecializationType *FromTST,
1394 const TemplateSpecializationType *ToTST) {
1395
1396
1397
1398 TemplateParameterList *ParamsFrom =
1399 FromTST->getTemplateName()
1400 .getAsTemplateDecl(true)
1401 ->getTemplateParameters();
1402 TemplateParameterList *ParamsTo =
1403 ToTST->getTemplateName()
1404 .getAsTemplateDecl(true)
1405 ->getTemplateParameters();
1406 unsigned TotalArgs = 0;
1407 for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST);
1408 !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {
1409 Tree.AddNode();
1410
1411
1412
1413
1414 unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);
1415 unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1);
1416 NamedDecl *FromParamND = ParamsFrom->getParam(FromParamIndex);
1417 NamedDecl *ToParamND = ParamsTo->getParam(ToParamIndex);
1418
1419 assert(FromParamND->getKind() == ToParamND->getKind() &&
1420 "Parameter Decl are not the same kind.");
1421
1423 DiffTypes(FromIter, ToIter);
1425 DiffTemplateTemplates(FromIter, ToIter);
1427 NonTypeTemplateParmDecl *FromDefaultNonTypeDecl =
1429 NonTypeTemplateParmDecl *ToDefaultNonTypeDecl =
1431 DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,
1432 ToDefaultNonTypeDecl);
1433 } else {
1434 llvm_unreachable("Unexpected Decl type.");
1435 }
1436
1437 ++FromIter;
1438 ++ToIter;
1439 Tree.Up();
1440 }
1441 }
1442
1443
1444 static void makeTemplateList(
1445 SmallVectorImpl<const TemplateSpecializationType *> &TemplateList,
1446 const TemplateSpecializationType *TST) {
1447 while (TST) {
1448 TemplateList.push_back(TST);
1449 if (!TST->isTypeAlias())
1450 return;
1451 TST = TST->getAliasedType()->getAs();
1452 }
1453 }
1454
1455
1456
1457 static bool hasSameBaseTemplate(ASTContext &Context,
1458 const TemplateSpecializationType *FromTST,
1459 const TemplateSpecializationType *ToTST) {
1460 return Context.getCanonicalTemplateName(FromTST->getTemplateName(),
1461 true) ==
1462 Context.getCanonicalTemplateName(ToTST->getTemplateName(),
1463 true);
1464 }
1465
1466
1467
1468
1469
1470 static bool hasSameTemplate(ASTContext &Context,
1471 const TemplateSpecializationType *&FromTST,
1472 const TemplateSpecializationType *&ToTST) {
1473
1474 if (hasSameBaseTemplate(Context, FromTST, ToTST))
1475 return true;
1476
1477
1478 SmallVector<const TemplateSpecializationType*, 1> FromTemplateList,
1479 ToTemplateList;
1480
1481 makeTemplateList(FromTemplateList, FromTST);
1482 makeTemplateList(ToTemplateList, ToTST);
1483
1484 SmallVectorImpl<const TemplateSpecializationType *>::reverse_iterator
1485 FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),
1486 ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();
1487
1488
1489 if (!hasSameBaseTemplate(Context, *FromIter, *ToIter))
1490 return false;
1491
1492
1493
1494
1495 for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {
1496 if (!hasSameBaseTemplate(Context, *FromIter, *ToIter))
1497 break;
1498 }
1499
1500 FromTST = FromIter[-1];
1501 ToTST = ToIter[-1];
1502
1503 return true;
1504 }
1505
1506
1507
1508 static QualType GetType(const TSTiterator &Iter) {
1509 if (!Iter.isEnd())
1510 return Iter->getAsType();
1511 if (Iter.hasDesugaredTA())
1512 return Iter.getDesugaredTA().getAsType();
1513 return QualType();
1514 }
1515
1516
1517
1518 static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) {
1519 if (!Iter.isEnd())
1520 return Iter->getAsTemplate().getAsTemplateDecl();
1521 if (Iter.hasDesugaredTA())
1522 return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl();
1523 return nullptr;
1524 }
1525
1526
1527
1528
1529 static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {
1530 if (FromExpr == ToExpr)
1531 return true;
1532
1533 if (!FromExpr || !ToExpr)
1534 return false;
1535
1536 llvm::FoldingSetNodeID FromID, ToID;
1537 FromExpr->Profile(FromID, Context, true);
1538 ToExpr->Profile(ToID, Context, true);
1539 return FromID == ToID;
1540 }
1541
1542
1543
1544
1545
1546
1547 void TreeToString(int Indent = 1) {
1548 if (PrintTree) {
1549 OS << '\n';
1550 OS.indent(2 * Indent);
1552 }
1553
1554
1555
1556 switch (Tree.GetKind()) {
1557 case DiffTree::Invalid:
1558 llvm_unreachable("Template diffing failed with bad DiffNode");
1559 case DiffTree::Type: {
1560 QualType FromType, ToType;
1561 Tree.GetTypeDiff(FromType, ToType);
1562 PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),
1563 Tree.NodeIsSame());
1564 return;
1565 }
1566 case DiffTree::Expression: {
1567 Expr *FromExpr, *ToExpr;
1568 Tree.GetExpressionDiff(FromExpr, ToExpr);
1569 PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
1570 Tree.NodeIsSame());
1571 return;
1572 }
1573 case DiffTree::TemplateTemplate: {
1574 TemplateDecl *FromTD, *ToTD;
1575 Tree.GetTemplateTemplateDiff(FromTD, ToTD);
1576 PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),
1577 Tree.ToDefault(), Tree.NodeIsSame());
1578 return;
1579 }
1580 case DiffTree::Integer: {
1581 llvm::APSInt FromInt, ToInt;
1582 Expr *FromExpr, *ToExpr;
1583 bool IsValidFromInt, IsValidToInt;
1584 QualType FromIntType, ToIntType;
1585 Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,
1586 FromIntType, ToIntType, FromExpr, ToExpr);
1587 PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,
1588 ToIntType, FromExpr, ToExpr, Tree.FromDefault(),
1589 Tree.ToDefault(), Tree.NodeIsSame());
1590 return;
1591 }
1592 case DiffTree::Declaration: {
1593 ValueDecl *FromValueDecl, *ToValueDecl;
1594 bool FromAddressOf, ToAddressOf;
1595 bool FromNullPtr, ToNullPtr;
1596 Expr *FromExpr, *ToExpr;
1597 Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf,
1598 ToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
1599 ToExpr);
1600 PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
1601 FromNullPtr, ToNullPtr, FromExpr, ToExpr,
1602 Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
1603 return;
1604 }
1605 case DiffTree::FromDeclarationAndToInteger: {
1606 ValueDecl *FromValueDecl;
1607 bool FromAddressOf;
1608 bool FromNullPtr;
1609 Expr *FromExpr;
1610 llvm::APSInt ToInt;
1611 bool IsValidToInt;
1612 QualType ToIntType;
1613 Expr *ToExpr;
1614 Tree.GetFromDeclarationAndToIntegerDiff(
1615 FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt,
1616 IsValidToInt, ToIntType, ToExpr);
1617 assert((FromValueDecl || FromNullPtr) && IsValidToInt);
1618 PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr,
1619 FromExpr, Tree.FromDefault(), ToInt, ToIntType,
1620 ToExpr, Tree.ToDefault());
1621 return;
1622 }
1623 case DiffTree::FromIntegerAndToDeclaration: {
1624 llvm::APSInt FromInt;
1625 bool IsValidFromInt;
1626 QualType FromIntType;
1627 Expr *FromExpr;
1628 ValueDecl *ToValueDecl;
1629 bool ToAddressOf;
1630 bool ToNullPtr;
1631 Expr *ToExpr;
1632 Tree.GetFromIntegerAndToDeclarationDiff(
1633 FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl,
1634 ToAddressOf, ToNullPtr, ToExpr);
1635 assert(IsValidFromInt && (ToValueDecl || ToNullPtr));
1636 PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr,
1637 Tree.FromDefault(), ToValueDecl, ToAddressOf,
1638 ToNullPtr, ToExpr, Tree.ToDefault());
1639 return;
1640 }
1641 case DiffTree::Template: {
1642
1643 TemplateDecl *FromTD, *ToTD;
1644 Qualifiers FromQual, ToQual;
1645 Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual);
1646
1647 PrintQualifiers(FromQual, ToQual);
1648
1649 if (!Tree.HasChildren()) {
1650
1651
1653 return;
1654 }
1655
1657 Tree.MoveToChild();
1658 unsigned NumElideArgs = 0;
1659 bool AllArgsElided = true;
1660 do {
1661 if (ElideType) {
1662 if (Tree.NodeIsSame()) {
1663 ++NumElideArgs;
1664 continue;
1665 }
1666 AllArgsElided = false;
1667 if (NumElideArgs > 0) {
1668 PrintElideArgs(NumElideArgs, Indent);
1669 NumElideArgs = 0;
1670 OS << ", ";
1671 }
1672 }
1673 TreeToString(Indent);
1674 if (Tree.HasNextSibling())
1675 OS << ", ";
1676 } while (Tree.AdvanceSibling());
1677 if (NumElideArgs > 0) {
1678 if (AllArgsElided)
1679 OS << "...";
1680 else
1681 PrintElideArgs(NumElideArgs, Indent);
1682 }
1683
1684 Tree.Parent();
1685 OS << ">";
1686 return;
1687 }
1688 }
1689 }
1690
1691
1692
1693
1694
1695
1696 void Bold() {
1697 assert(!IsBold && "Attempting to bold text that is already bold.");
1698 IsBold = true;
1699 if (ShowColor)
1701 }
1702
1703
1704 void Unbold() {
1705 assert(IsBold && "Attempting to remove bold from unbold text.");
1706 IsBold = false;
1707 if (ShowColor)
1709 }
1710
1711
1712
1713
1714
1715
1716 void PrintTypeNames(QualType FromType, QualType ToType,
1717 bool FromDefault, bool ToDefault, bool Same) {
1718 assert((!FromType.isNull() || !ToType.isNull()) &&
1719 "Only one template argument may be missing.");
1720
1721 if (Same) {
1723 return;
1724 }
1725
1726 if (!FromType.isNull() && !ToType.isNull() &&
1731 PrintQualifiers(FromQual, ToQual);
1733 return;
1734 }
1735
1736 std::string FromTypeStr = FromType.isNull() ? "(no argument)"
1738 std::string ToTypeStr =
1740
1741 if (FromTypeStr == ToTypeStr) {
1742
1743 std::string FromCanTypeStr =
1746 if (FromCanTypeStr != ToCanTypeStr) {
1747 FromTypeStr = FromCanTypeStr;
1748 ToTypeStr = ToCanTypeStr;
1749 }
1750 }
1751
1752 if (PrintTree)
1753 OS << '[';
1754 OS << (FromDefault ? "(default) " : "");
1756 OS << FromTypeStr;
1757 Unbold();
1758 if (PrintTree) {
1759 OS << " != " << (ToDefault ? "(default) " : "");
1761 OS << ToTypeStr;
1762 Unbold();
1763 OS << "]";
1764 }
1765 }
1766
1767
1768
1769 void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault,
1770 bool ToDefault, bool Same) {
1771 assert((FromExpr || ToExpr) &&
1772 "Only one template argument may be missing.");
1773 if (Same) {
1774 PrintExpr(FromExpr);
1775 } else if (!PrintTree) {
1776 OS << (FromDefault ? "(default) " : "");
1778 PrintExpr(FromExpr);
1779 Unbold();
1780 } else {
1781 OS << (FromDefault ? "[(default) " : "[");
1783 PrintExpr(FromExpr);
1784 Unbold();
1785 OS << " != " << (ToDefault ? "(default) " : "");
1787 PrintExpr(ToExpr);
1788 Unbold();
1789 OS << ']';
1790 }
1791 }
1792
1793
1794 void PrintExpr(const Expr *E) {
1795 if (E) {
1797 return;
1798 }
1799 OS << "(no argument)";
1800 }
1801
1802
1803
1804 void PrintTemplateTemplate(TemplateDecl *FromTD, TemplateDecl *ToTD,
1805 bool FromDefault, bool ToDefault, bool Same) {
1806 assert((FromTD || ToTD) && "Only one template argument may be missing.");
1807
1808 std::string FromName =
1809 std::string(FromTD ? FromTD->getName() : "(no argument)");
1810 std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");
1811 if (FromTD && ToTD && FromName == ToName) {
1814 }
1815
1816 if (Same) {
1817 OS << "template " << FromTD->getDeclName();
1818 } else if (!PrintTree) {
1819 OS << (FromDefault ? "(default) template " : "template ");
1821 OS << FromName;
1822 Unbold();
1823 } else {
1824 OS << (FromDefault ? "[(default) template " : "[template ");
1826 OS << FromName;
1827 Unbold();
1828 OS << " != " << (ToDefault ? "(default) template " : "template ");
1830 OS << ToName;
1831 Unbold();
1832 OS << ']';
1833 }
1834 }
1835
1836
1837
1838 void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
1839 bool IsValidFromInt, bool IsValidToInt, QualType FromIntType,
1840 QualType ToIntType, Expr *FromExpr, Expr *ToExpr,
1841 bool FromDefault, bool ToDefault, bool Same) {
1842 assert((IsValidFromInt || IsValidToInt) &&
1843 "Only one integral argument may be missing.");
1844
1845 if (Same) {
1847 OS << ((FromInt == 0) ? "false" : "true");
1848 } else {
1849 OS << toString(FromInt, 10);
1850 }
1851 return;
1852 }
1853
1854 bool PrintType = IsValidFromInt && IsValidToInt &&
1855 !Context.hasSameType(FromIntType, ToIntType);
1856
1857 if (!PrintTree) {
1858 OS << (FromDefault ? "(default) " : "");
1859 PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
1860 } else {
1861 OS << (FromDefault ? "[(default) " : "[");
1862 PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
1863 OS << " != " << (ToDefault ? "(default) " : "");
1864 PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType);
1865 OS << ']';
1866 }
1867 }
1868
1869
1870
1871 void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid,
1872 QualType IntType, bool PrintType) {
1875 if (HasExtraInfo(E)) {
1876 PrintExpr(E);
1877 Unbold();
1878 OS << " aka ";
1880 }
1881 if (PrintType) {
1882 Unbold();
1883 OS << "(";
1885 IntType.print(OS, Context.getPrintingPolicy());
1886 Unbold();
1887 OS << ") ";
1889 }
1891 OS << ((Val == 0) ? "false" : "true");
1892 } else {
1894 }
1895 } else if (E) {
1896 PrintExpr(E);
1897 } else {
1898 OS << "(no argument)";
1899 }
1900 Unbold();
1901 }
1902
1903
1904
1905 bool HasExtraInfo(Expr *E) {
1906 if (!E) return false;
1907
1909
1910 auto CheckIntegerLiteral = [](Expr *E) {
1911 if (auto *TemplateExpr = dyn_cast(E))
1912 E = TemplateExpr->getReplacement();
1914 };
1915
1916 if (CheckIntegerLiteral(E)) return false;
1917
1918 if (UnaryOperator *UO = dyn_cast(E))
1919 if (UO->getOpcode() == UO_Minus)
1920 if (CheckIntegerLiteral(UO->getSubExpr()))
1921 return false;
1922
1924 return false;
1925
1926 return true;
1927 }
1928
1929 void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) {
1930 if (VD) {
1931 if (AddressOf)
1932 OS << "&";
1933 else if (auto *TPO = dyn_cast(VD)) {
1934
1935
1936
1937 TPO->getType().getUnqualifiedType().print(OS, Policy);
1938 TPO->printAsInit(OS, Policy);
1939 return;
1940 }
1942 return;
1943 }
1944
1945 if (NullPtr) {
1947 PrintExpr(E);
1948 if (IsBold) {
1949 Unbold();
1950 OS << " aka ";
1952 } else {
1953 OS << " aka ";
1954 }
1955 }
1956
1957 OS << "nullptr";
1958 return;
1959 }
1960
1961 if (E) {
1962 PrintExpr(E);
1963 return;
1964 }
1965
1966 OS << "(no argument)";
1967 }
1968
1969
1970
1971 void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
1972 bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,
1973 bool ToNullPtr, Expr *FromExpr, Expr *ToExpr,
1974 bool FromDefault, bool ToDefault, bool Same) {
1975 assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&
1976 "Only one Decl argument may be NULL");
1977
1978 if (Same) {
1979 PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
1980 } else if (!PrintTree) {
1981 OS << (FromDefault ? "(default) " : "");
1983 PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
1984 Unbold();
1985 } else {
1986 OS << (FromDefault ? "[(default) " : "[");
1988 PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
1989 Unbold();
1990 OS << " != " << (ToDefault ? "(default) " : "");
1992 PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr);
1993 Unbold();
1994 OS << ']';
1995 }
1996 }
1997
1998
1999
2000 void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf,
2001 bool IsNullPtr, Expr *VDExpr, bool DefaultDecl,
2002 const llvm::APSInt &Val, QualType IntType,
2003 Expr *IntExpr, bool DefaultInt) {
2004 if (!PrintTree) {
2005 OS << (DefaultDecl ? "(default) " : "");
2007 PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
2008 Unbold();
2009 } else {
2010 OS << (DefaultDecl ? "[(default) " : "[");
2012 PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
2013 Unbold();
2014 OS << " != " << (DefaultInt ? "(default) " : "");
2015 PrintAPSInt(Val, IntExpr, true , IntType, false );
2016 OS << ']';
2017 }
2018 }
2019
2020
2021
2022 void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType,
2023 Expr *IntExpr, bool DefaultInt, ValueDecl *VD,
2024 bool NeedAddressOf, bool IsNullPtr,
2025 Expr *VDExpr, bool DefaultDecl) {
2026 if (!PrintTree) {
2027 OS << (DefaultInt ? "(default) " : "");
2028 PrintAPSInt(Val, IntExpr, true , IntType, false );
2029 } else {
2030 OS << (DefaultInt ? "[(default) " : "[");
2031 PrintAPSInt(Val, IntExpr, true , IntType, false );
2032 OS << " != " << (DefaultDecl ? "(default) " : "");
2034 PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
2035 Unbold();
2036 OS << ']';
2037 }
2038 }
2039
2040
2041 void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
2042 if (PrintTree) {
2043 OS << '\n';
2044 for (unsigned i = 0; i < Indent; ++i)
2045 OS << " ";
2046 }
2047 if (NumElideArgs == 0) return;
2048 if (NumElideArgs == 1)
2049 OS << "[...]";
2050 else
2051 OS << "[" << NumElideArgs << " * ...]";
2052 }
2053
2054
2055 void PrintQualifiers(Qualifiers FromQual, Qualifiers ToQual) {
2056
2057 if (FromQual.empty() && ToQual.empty())
2058 return;
2059
2060
2061 if (FromQual == ToQual) {
2062 PrintQualifier(FromQual, false);
2063 return;
2064 }
2065
2066
2068 ToQual);
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080 if (PrintTree) {
2081 OS << "[";
2082 if (CommonQual.empty() && FromQual.empty()) {
2084 OS << "(no qualifiers) ";
2085 Unbold();
2086 } else {
2087 PrintQualifier(CommonQual, false);
2088 PrintQualifier(FromQual, true);
2089 }
2090 OS << "!= ";
2091 if (CommonQual.empty() && ToQual.empty()) {
2093 OS << "(no qualifiers)";
2094 Unbold();
2095 } else {
2096 PrintQualifier(CommonQual, false,
2097 !ToQual.empty());
2098 PrintQualifier(ToQual, true,
2099 false);
2100 }
2101 OS << "] ";
2102 } else {
2103 PrintQualifier(CommonQual, false);
2104 PrintQualifier(FromQual, true);
2105 }
2106 }
2107
2108 void PrintQualifier(Qualifiers Q, bool ApplyBold,
2109 bool AppendSpaceIfNonEmpty = true) {
2110 if (Q.empty()) return;
2111 if (ApplyBold) Bold();
2112 Q.print(OS, Policy, AppendSpaceIfNonEmpty);
2113 if (ApplyBold) Unbold();
2114 }
2115
2116public:
2117
2118 TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType,
2119 QualType ToType, bool PrintTree, bool PrintFromType,
2120 bool ElideType, bool ShowColor)
2121 : Context(Context),
2122 Policy(Context.getLangOpts()),
2123 ElideType(ElideType),
2124 PrintTree(PrintTree),
2125 ShowColor(ShowColor),
2126
2127 FromTemplateType(PrintFromType ? FromType : ToType),
2128 ToTemplateType(PrintFromType ? ToType : FromType),
2129 OS(OS),
2131 }
2132
2133
2134 void DiffTemplate() {
2135 Qualifiers FromQual = FromTemplateType.getQualifiers(),
2136 ToQual = ToTemplateType.getQualifiers();
2137
2138 const TemplateSpecializationType *FromOrigTST =
2139 GetTemplateSpecializationType(Context, FromTemplateType);
2140 const TemplateSpecializationType *ToOrigTST =
2141 GetTemplateSpecializationType(Context, ToTemplateType);
2142
2143
2144 if (!FromOrigTST || !ToOrigTST)
2145 return;
2146
2147
2148 if (!hasSameTemplate(Context, FromOrigTST, ToOrigTST)) {
2149 return;
2150 }
2151
2152 FromQual -= QualType(FromOrigTST, 0).getQualifiers();
2153 ToQual -= QualType(ToOrigTST, 0).getQualifiers();
2154
2155
2156 Tree.SetTemplateDiff(
2157 FromOrigTST->getTemplateName().getAsTemplateDecl(
2158 true),
2159 ToOrigTST->getTemplateName().getAsTemplateDecl(true),
2160 FromQual, ToQual, false , false );
2161
2162 DiffTemplate(FromOrigTST, ToOrigTST);
2163 }
2164
2165
2166
2167
2168 bool Emit() {
2169 Tree.StartTraverse();
2170 if (Tree.Empty())
2171 return false;
2172
2173 TreeToString();
2174 assert(!IsBold && "Bold is applied to end of string.");
2175 return true;
2176 }
2177};
2178}
2179
2180
2181
2182
2184 QualType ToType, bool PrintTree,
2185 bool PrintFromType, bool ElideType,
2186 bool ShowColors, raw_ostream &OS) {
2187 if (PrintTree)
2188 PrintFromType = true;
2189 TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType,
2190 ElideType, ShowColors);
2191 TD.DiffTemplate();
2192 return TD.Emit();
2193}
2194
2196 auto IsSingleCodeUnitCP = [](unsigned Value, QualType T) {
2197 if (T->isChar8Type()) {
2198 assert(Value <= 0xFF && "not a valid UTF-8 code unit");
2199 return Value <= 0x7F;
2200 }
2201 if (T->isChar16Type()) {
2202 assert(Value <= 0xFFFF && "not a valid UTF-16 code unit");
2203 return llvm::IsSingleCodeUnitUTF16Codepoint(Value);
2204 }
2205 assert(T->isChar32Type());
2206 return llvm::IsSingleCodeUnitUTF32Codepoint(Value);
2207 };
2209 if (!IsSingleCodeUnitCP(Value, T)) {
2210 llvm::raw_svector_ostream OS(Str);
2211 OS << "<" << llvm::format_hex(Value, 1, true) << ">";
2212 return std::string(Str.begin(), Str.end());
2213 }
2214
2215 char Buffer[UNI_MAX_UTF8_BYTES_PER_CODE_POINT];
2216 char *Ptr = Buffer;
2217 [[maybe_unused]] bool Converted = llvm::ConvertCodePointToUTF8(Value, Ptr);
2218 assert(Converted && "trying to encode invalid code unit");
2220 return std::string(Str.begin(), Str.end());
2221}
Defines the clang::ASTContext interface.
static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, QualType ToType, bool PrintTree, bool PrintFromType, bool ElideType, bool ShowColors, raw_ostream &OS)
FormatTemplateTypeDiff - A helper static function to start the template diff and return the properly ...
Definition ASTDiagnostic.cpp:2183
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.
Definition ASTDiagnostic.cpp:260
This file provides some common utility functions for processing Lambda related AST Constructs.
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
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 ...
Represents a type which was implicitly adjusted by the semantic engine for arbitrary reasons.
Attr - This represents one attribute.
const char * getSpelling() const
std::string getNormalizedFullName() const
Gets the normalized full name, which consists of both scope and name and with surrounding underscores...
const IdentifierInfo * getScopeName() const
const IdentifierInfo * getAttrName() const
bool isStandardAttributeSyntax() const
The attribute is spelled [[]] in either C or C++ mode, including standard attributes spelled with a k...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool isTranslationUnit() const
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
static DeclarationName getFromOpaqueInteger(uintptr_t P)
Get a declaration name from an opaque integer returned by getAsOpaqueInteger.
@ ak_nameddecl
NamedDecl *.
@ ak_declcontext
DeclContext *.
@ ak_addrspace
address space
@ ak_qualtype_pair
pair<QualType, QualType>
@ ak_attr_info
AttributeCommonInfo *.
@ ak_declarationname
DeclarationName.
@ ak_nestednamespec
NestedNameSpecifier *.
This represents one expression.
Expr * IgnoreImpCasts() LLVM_READONLY
Skip past any implicit casts which might surround this expression until reaching a fixed point.
Represents a prototype with parameter type info, e.g.
ExtProtoInfo getExtProtoInfo() const
ArrayRef< QualType > param_types() const
FunctionType - C99 6.7.5.3 - Function Declarators.
StringRef getName() const
Return the actual identifier string.
An lvalue reference type, per C++11 [dcl.ref].
Sugar type that represents a type that was qualified by a qualifier written as a macro invocation.
This represents a decl that may have a name.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
std::string getQualifiedNameAsString() const
virtual void getNameForDiagnostic(raw_ostream &OS, const PrintingPolicy &Policy, bool Qualified) const
Appends a human-readable name for this declaration into the given stream.
virtual void printName(raw_ostream &OS, const PrintingPolicy &Policy) const
Pretty-print the unqualified name of this declaration.
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.
Sugar for parentheses used when specifying types.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
QualType getLocalUnqualifiedType() const
Return this type with all of the instance-specific qualifiers removed, but without removing any quali...
bool isNull() const
Return true if this QualType doesn't point to a type yet.
static QualType getFromOpaquePtr(const void *Ptr)
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
QualType getCanonicalType() const
static std::string getAsString(SplitQualType split, const PrintingPolicy &Policy)
Qualifiers getLocalQualifiers() const
Retrieve the set of qualifiers local to this particular QualType instance, not including any qualifie...
A qualifier set is used to build a set of qualifiers.
const Type * strip(QualType type)
Collect any qualifiers on the given type and return an unqualified type.
QualType apply(const ASTContext &Context, QualType QT) const
Apply the collected qualifiers to the given type.
The collection of all-type qualifiers we support.
static Qualifiers removeCommonQualifiers(Qualifiers &L, Qualifiers &R)
Returns the common set of qualifiers while removing them from the given sets.
void print(raw_ostream &OS, const PrintingPolicy &Policy, bool appendSpaceIfNonEmpty=false) const
std::string getAsString() const
static Qualifiers fromOpaqueValue(uint64_t opaque)
static std::string getAddrSpaceAsString(LangAS AS)
An rvalue reference type, per C++11 [dcl.ref].
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical, bool ProfileLambdaExpr=false) const
Produce a unique representation of the given statement.
Represents a template argument.
QualType getParamTypeForDecl() const
Expr * getAsExpr() const
Retrieve the template argument as an expression.
pack_iterator pack_end() const
Iterator referencing one past the last argument of a template argument pack.
const TemplateArgument * pack_iterator
Iterator that traverses the elements of a template argument pack.
pack_iterator pack_begin() const
Iterator referencing the first argument of a template argument pack.
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
QualType getIntegralType() const
Retrieve the type of the integral value.
ValueDecl * getAsDecl() const
Retrieve the declaration for a declaration non-type template argument.
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
@ Template
The template argument is a template name that was provided for a template template parameter.
@ StructuralValue
The template argument is a non-type template argument that can't be represented by the special-case D...
@ Pack
The template argument is actually a parameter pack.
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
@ Type
The template argument is a type.
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
ArgKind getKind() const
Return the kind of stored template argument.
NamedDecl * getParam(unsigned Idx)
Represents a declaration of a type.
The base class of the type hierarchy.
bool isBooleanType() const
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
TypeClass getTypeClass() const
const T * getAs() const
Member-template getAs'.
Represents a GCC generic vector type.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
QualType desugarForDiagnostic(ASTContext &Context, QualType QT, bool &ShouldAKA)
Returns a desugared version of the QualType, and marks ShouldAKA as true whenever we remove significa...
Definition ASTDiagnostic.cpp:32
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
@ TemplateName
The identifier is a template name. FIXME: Add an annotation for that.
std::string FormatUTFCodeUnitAsCodepoint(unsigned Value, QualType T)
Definition ASTDiagnostic.cpp:2195
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)
bool isLambdaCallOperator(const CXXMethodDecl *MD)
const FunctionProtoType * T
@ Template
We are parsing a template declaration.
void EscapeStringForDiagnostic(StringRef Str, SmallVectorImpl< char > &OutStr)
EscapeStringForDiagnostic - Append Str to the diagnostic buffer, escaping non-printable characters an...
LangAS
Defines the address space values used by the address space qualifier of QualType.
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.
Definition ASTDiagnostic.cpp:352
U cast(CodeGen::Address addr)
__INTPTR_TYPE__ intptr_t
A signed integer type with the property that any valid pointer to void can be converted to this type,...
Describes how types, statements, expressions, and declarations should be printed.
unsigned TemplateDiffUsed