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/raw_ostream.h"
24
25using namespace clang;
26
27
28
29
31 bool &ShouldAKA) {
33
34 while (true) {
36
37
38 if (const ElaboratedType *ET = dyn_cast(Ty)) {
39 QT = ET->desugar();
40 continue;
41 }
42
43 if (const UsingType *UT = dyn_cast(Ty)) {
44 QT = UT->desugar();
45 continue;
46 }
47
48 if (const ParenType *PT = dyn_cast(Ty)) {
49 QT = PT->desugar();
50 continue;
51 }
52
53 if (const MacroQualifiedType *MDT = dyn_cast(Ty)) {
54 QT = MDT->desugar();
55 continue;
56 }
57
59 dyn_cast(Ty)) {
60 QT = ST->desugar();
61 continue;
62 }
63
64 if (const AttributedType *AT = dyn_cast(Ty)) {
65 QT = AT->desugar();
66 continue;
67 }
68
69 if (const AdjustedType *AT = dyn_cast(Ty)) {
70 QT = AT->desugar();
71 continue;
72 }
73
74 if (const AutoType *AT = dyn_cast(Ty)) {
75 if (!AT->isSugared())
76 break;
77 QT = AT->desugar();
78 continue;
79 }
80
81
82
83 if (const FunctionType *FT = dyn_cast(Ty)) {
84 bool DesugarReturn = false;
85 QualType SugarRT = FT->getReturnType();
89 }
90
91 bool DesugarArgument = false;
94 if (FPT) {
97 if (auto nullability =
100 }
101 Args.push_back(PT);
102 }
103 }
104
105 if (DesugarReturn || DesugarArgument) {
106 ShouldAKA = true;
109 break;
110 }
111 }
112
113
114
116 dyn_cast(Ty)) {
117 if (!TST->isTypeAlias()) {
118 bool DesugarArgument = false;
120 for (const TemplateArgument &Arg : TST->template_arguments()) {
123 DesugarArgument));
124 else
125 Args.push_back(Arg);
126 }
127
128 if (DesugarArgument) {
129 ShouldAKA = true;
131 TST->getTemplateName(), Args, QT);
132 }
133 break;
134 }
135 }
136
137 if (const auto *AT = dyn_cast(Ty)) {
140 if (const auto *CAT = dyn_cast(AT))
142 ElementTy, CAT->getSize(), CAT->getSizeExpr(),
143 CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers());
144 else if (const auto *VAT = dyn_cast(AT))
146 ElementTy, VAT->getSizeExpr(), VAT->getSizeModifier(),
147 VAT->getIndexTypeCVRQualifiers(), VAT->getBracketsRange());
148 else if (const auto *DSAT = dyn_cast(AT))
150 ElementTy, DSAT->getSizeExpr(), DSAT->getSizeModifier(),
151 DSAT->getIndexTypeCVRQualifiers(), DSAT->getBracketsRange());
152 else if (const auto *IAT = dyn_cast(AT))
154 IAT->getIndexTypeCVRQualifiers());
155 else
156 llvm_unreachable("Unhandled array type");
157 break;
158 }
159
160
165 break;
166
167
170 break;
171
172
174 bool IsSugar = false;
176#define ABSTRACT_TYPE(Class, Base)
177#define TYPE(Class, Base) \
178case Type::Class: { \
179const Class##Type *CTy = cast<Class##Type>(Ty); \
180if (CTy->isSugared()) { \
181IsSugar = true; \
182Underlying = CTy->desugar(); \
183} \
184break; \
185}
186#include "clang/AST/TypeNodes.inc"
187 }
188
189
190 if (!IsSugar)
191 break;
192
193
194
195 if (isa(Underlying))
196 break;
197
198
200 if (const TypedefType *QTT = dyn_cast(QT))
201 if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
202 break;
203
204
205 ShouldAKA = true;
206 QT = Underlying;
207 }
208
209
210
224 if (Ty->getBaseType().getTypePtr() != Ty && !ShouldAKA) {
228 BaseType, Ty->getTypeArgsAsWritten(),
229 llvm::ArrayRef(Ty->qual_begin(), Ty->getNumProtocols()),
230 Ty->isKindOfTypeAsWritten());
231 }
232 }
233
234 return QC.apply(Context, QT);
235}
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261static std::string
265
266 bool ForceAKA = false;
270
271 for (const intptr_t &QualTypeVal : QualTypeVals) {
274 if (CompareTy.isNull())
275 continue;
276 if (CompareTy == Ty)
277 continue;
279 if (CompareCanTy == CanTy)
280 continue;
282 bool ShouldAKA = false;
285 std::string CompareDesugarStr =
287 if (CompareS != S && CompareDesugarStr != S)
288 continue;
289
290 std::string CompareCanS =
292
293 if (CompareCanS == CanS)
294 continue;
295
296 ForceAKA = true;
297 break;
298 }
299
300
301
302 bool Repeated = false;
303 for (const auto &PrevArg : PrevArgs) {
304
308 if (PrevTy == Ty) {
309 Repeated = true;
310 break;
311 }
312 }
313 }
314
315
316
317 if (!Repeated) {
318 bool ShouldAKA = false;
320 if (ShouldAKA || ForceAKA) {
321 if (DesugaredTy == Ty) {
323 }
325 if (akaStr != S) {
326 S = "'" + S + "' (aka '" + akaStr + "')";
327 return S;
328 }
329 }
330
331
332
333
335 std::string DecoratedString;
336 llvm::raw_string_ostream OS(DecoratedString);
337 const char *Values = VTy->getNumElements() > 1 ? "values" : "value";
338 OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '"
339 << VTy->getElementType().getAsString(Context.getPrintingPolicy())
340 << "' " << Values << ")";
341 return DecoratedString;
342 }
343 }
344
345 S = "'" + S + "'";
346 return S;
347}
348
350 QualType ToType, bool PrintTree,
351 bool PrintFromType, bool ElideType,
353
357 StringRef Modifier,
358 StringRef Argument,
361 void *Cookie,
364
365 size_t OldEnd = Output.size();
366 llvm::raw_svector_ostream OS(Output);
367 bool NeedQuotes = true;
368
369 switch (Kind) {
370 default: llvm_unreachable("unknown ArgumentKind");
372 assert(Modifier.empty() && Argument.empty() &&
373 "Invalid modifier for Qualifiers argument");
374
376 if (S.empty()) {
377 OS << (Context.getLangOpts().OpenCL ? "default" : "generic");
378 OS << " address space";
379 } else {
380 OS << "address space";
381 OS << " '" << S << "'";
382 }
383 NeedQuotes = false;
384 break;
385 }
387 assert(Modifier.empty() && Argument.empty() &&
388 "Invalid modifier for Qualifiers argument");
389
392 if (S.empty()) {
393 OS << "unqualified";
394 NeedQuotes = false;
395 } else {
396 OS << S;
397 }
398 break;
399 }
406
412 break;
413 }
414
415
416
418 return;
419
420
421
423 Modifier = StringRef();
424 Argument = StringRef();
425
426 [[fallthrough]];
427 }
429 assert(Modifier.empty() && Argument.empty() &&
430 "Invalid modifier for QualType argument");
431
434 NeedQuotes = false;
435 break;
436 }
438 if (Modifier == "objcclass" && Argument.empty())
439 OS << '+';
440 else if (Modifier == "objcinstance" && Argument.empty())
441 OS << '-';
442 else
443 assert(Modifier.empty() && Argument.empty() &&
444 "Invalid modifier for DeclarationName argument");
445
447 break;
448 }
451 if (Modifier == "q" && Argument.empty())
453 else {
454 assert(Modifier.empty() && Argument.empty() &&
455 "Invalid modifier for NamedDecl* argument");
457 }
460 break;
461 }
465 NeedQuotes = false;
466 break;
467 }
470 assert(DC && "Should never have a null declaration context");
471 NeedQuotes = false;
472
473
476 OS << "the global namespace";
477 else
478 OS << "the global scope";
480 OS << "block literal";
482 OS << "lambda expression";
483 } else if (TypeDecl *Type = dyn_cast(DC)) {
486 PrevArgs, QualTypeVals);
487 } else {
488 assert(isa(DC) && "Expected a NamedDecl");
489 NamedDecl *ND = cast(DC);
490 if (isa(ND))
491 OS << "namespace ";
492 else if (isa(ND))
493 OS << "method ";
494 else if (isa(ND))
495 OS << "function ";
496
497 OS << '\'';
499 OS << '\'';
500 }
501 break;
502 }
504 const Attr *At = reinterpret_cast<Attr *>(Val);
505 assert(At && "Received null Attr object!");
507 NeedQuotes = false;
508 break;
509 }
510 }
511
512 if (NeedQuotes) {
513 Output.insert(Output.begin()+OldEnd, '\'');
514 Output.push_back('\'');
515 }
516}
517
518
519
520
521
522namespace {
523class TemplateDiff {
524
526
527
529
530
531 bool ElideType;
532
533
534 bool PrintTree;
535
536
537 bool ShowColor;
538
539
540
541
543
544
545
547
548
549 raw_ostream &OS;
550
551
552 bool IsBold;
553
554
555 class DiffTree {
556 public:
557
558
559
560 enum DiffKind {
561
562 Invalid,
563
564 Template,
565
566
568
569
570
572
573 TemplateTemplate,
574
576
577 Declaration,
578
579 FromIntegerAndToDeclaration,
580 FromDeclarationAndToInteger
581 };
582
583 private:
584
585
586
587 struct TemplateArgumentInfo {
590 llvm::APSInt Val;
591 bool IsValidInt = false;
592 Expr *ArgExpr = nullptr;
595 bool NeedAddressOf = false;
596 bool IsNullPtr = false;
597 bool IsDefault = false;
598 };
599
600
601
602
603 struct DiffNode {
605
606
607 unsigned NextNode = 0;
608
609
610 unsigned ChildNode = 0;
611
612
613 unsigned ParentNode = 0;
614
615 TemplateArgumentInfo FromArgInfo, ToArgInfo;
616
617
618 bool Same = false;
619
620 DiffNode(unsigned ParentNode = 0) : ParentNode(ParentNode) {}
621 };
622
623
625
626
627 unsigned CurrentNode;
628
629
630
631 unsigned NextFreeNode;
632
633
634 unsigned ReadNode;
635
636 public:
637 DiffTree() : CurrentNode(0), NextFreeNode(1), ReadNode(0) {
638 FlatTree.push_back(DiffNode());
639 }
640
641
644 bool FromDefault, bool ToDefault) {
645 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
646 FlatTree[CurrentNode].Kind = Template;
647 FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
648 FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
649 FlatTree[CurrentNode].FromArgInfo.Qual = FromQual;
650 FlatTree[CurrentNode].ToArgInfo.Qual = ToQual;
651 SetDefault(FromDefault, ToDefault);
652 }
653
654 void SetTypeDiff(QualType FromType, QualType ToType, bool FromDefault,
655 bool ToDefault) {
656 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
657 FlatTree[CurrentNode].Kind = Type;
658 FlatTree[CurrentNode].FromArgInfo.ArgType = FromType;
659 FlatTree[CurrentNode].ToArgInfo.ArgType = ToType;
660 SetDefault(FromDefault, ToDefault);
661 }
662
663 void SetExpressionDiff(Expr *FromExpr, Expr *ToExpr, bool FromDefault,
664 bool ToDefault) {
665 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
666 FlatTree[CurrentNode].Kind = Expression;
667 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
668 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
669 SetDefault(FromDefault, ToDefault);
670 }
671
673 bool FromDefault, bool ToDefault) {
674 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
675 FlatTree[CurrentNode].Kind = TemplateTemplate;
676 FlatTree[CurrentNode].FromArgInfo.TD = FromTD;
677 FlatTree[CurrentNode].ToArgInfo.TD = ToTD;
678 SetDefault(FromDefault, ToDefault);
679 }
680
681 void SetIntegerDiff(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
682 bool IsValidFromInt, bool IsValidToInt,
684 Expr *FromExpr, Expr *ToExpr, bool FromDefault,
685 bool ToDefault) {
686 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
687 FlatTree[CurrentNode].Kind = Integer;
688 FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
689 FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
690 FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
691 FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
692 FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
693 FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
694 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
695 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
696 SetDefault(FromDefault, ToDefault);
697 }
698
699 void SetDeclarationDiff(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
700 bool FromAddressOf, bool ToAddressOf,
701 bool FromNullPtr, bool ToNullPtr, Expr *FromExpr,
702 Expr *ToExpr, bool FromDefault, bool ToDefault) {
703 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
704 FlatTree[CurrentNode].Kind = Declaration;
705 FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
706 FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
707 FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
708 FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
709 FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
710 FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
711 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
712 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
713 SetDefault(FromDefault, ToDefault);
714 }
715
716 void SetFromDeclarationAndToIntegerDiff(
717 ValueDecl *FromValueDecl, bool FromAddressOf, bool FromNullPtr,
718 Expr *FromExpr, const llvm::APSInt &ToInt, bool IsValidToInt,
719 QualType ToIntType, Expr *ToExpr, bool FromDefault, bool ToDefault) {
720 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
721 FlatTree[CurrentNode].Kind = FromDeclarationAndToInteger;
722 FlatTree[CurrentNode].FromArgInfo.VD = FromValueDecl;
723 FlatTree[CurrentNode].FromArgInfo.NeedAddressOf = FromAddressOf;
724 FlatTree[CurrentNode].FromArgInfo.IsNullPtr = FromNullPtr;
725 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
726 FlatTree[CurrentNode].ToArgInfo.Val = ToInt;
727 FlatTree[CurrentNode].ToArgInfo.IsValidInt = IsValidToInt;
728 FlatTree[CurrentNode].ToArgInfo.ArgType = ToIntType;
729 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
730 SetDefault(FromDefault, ToDefault);
731 }
732
733 void SetFromIntegerAndToDeclarationDiff(
734 const llvm::APSInt &FromInt, bool IsValidFromInt, QualType FromIntType,
735 Expr *FromExpr, ValueDecl *ToValueDecl, bool ToAddressOf,
736 bool ToNullPtr, Expr *ToExpr, bool FromDefault, bool ToDefault) {
737 assert(FlatTree[CurrentNode].Kind == Invalid && "Node is not empty.");
738 FlatTree[CurrentNode].Kind = FromIntegerAndToDeclaration;
739 FlatTree[CurrentNode].FromArgInfo.Val = FromInt;
740 FlatTree[CurrentNode].FromArgInfo.IsValidInt = IsValidFromInt;
741 FlatTree[CurrentNode].FromArgInfo.ArgType = FromIntType;
742 FlatTree[CurrentNode].FromArgInfo.ArgExpr = FromExpr;
743 FlatTree[CurrentNode].ToArgInfo.VD = ToValueDecl;
744 FlatTree[CurrentNode].ToArgInfo.NeedAddressOf = ToAddressOf;
745 FlatTree[CurrentNode].ToArgInfo.IsNullPtr = ToNullPtr;
746 FlatTree[CurrentNode].ToArgInfo.ArgExpr = ToExpr;
747 SetDefault(FromDefault, ToDefault);
748 }
749
750
751 void SetDefault(bool FromDefault, bool ToDefault) {
752 assert((!FromDefault || !ToDefault) && "Both arguments cannot be default.");
753 FlatTree[CurrentNode].FromArgInfo.IsDefault = FromDefault;
754 FlatTree[CurrentNode].ToArgInfo.IsDefault = ToDefault;
755 }
756
757
758 void SetSame(bool Same) {
759 FlatTree[CurrentNode].Same = Same;
760 }
761
762
763 void SetKind(DiffKind Kind) {
764 FlatTree[CurrentNode].Kind = Kind;
765 }
766
767
768 void Up() {
769 assert(FlatTree[CurrentNode].Kind != Invalid &&
770 "Cannot exit node before setting node information.");
771 CurrentNode = FlatTree[CurrentNode].ParentNode;
772 }
773
774
775
776 void AddNode() {
777 assert(FlatTree[CurrentNode].Kind == Template &&
778 "Only Template nodes can have children nodes.");
779 FlatTree.push_back(DiffNode(CurrentNode));
780 DiffNode &Node = FlatTree[CurrentNode];
781 if (Node.ChildNode == 0) {
782
783 Node.ChildNode = NextFreeNode;
784 } else {
785
786
787 unsigned i;
788 for (i = Node.ChildNode; FlatTree[i].NextNode != 0;
789 i = FlatTree[i].NextNode) {
790 }
791 FlatTree[i].NextNode = NextFreeNode;
792 }
793 CurrentNode = NextFreeNode;
794 ++NextFreeNode;
795 }
796
797
798
799 void StartTraverse() {
800 ReadNode = 0;
801 CurrentNode = NextFreeNode;
802 NextFreeNode = 0;
803 }
804
805
807 ReadNode = FlatTree[ReadNode].ParentNode;
808 }
809
812 assert(FlatTree[ReadNode].Kind == Template && "Unexpected kind.");
813 FromTD = FlatTree[ReadNode].FromArgInfo.TD;
814 ToTD = FlatTree[ReadNode].ToArgInfo.TD;
815 FromQual = FlatTree[ReadNode].FromArgInfo.Qual;
816 ToQual = FlatTree[ReadNode].ToArgInfo.Qual;
817 }
818
820 assert(FlatTree[ReadNode].Kind == Type && "Unexpected kind");
821 FromType = FlatTree[ReadNode].FromArgInfo.ArgType;
822 ToType = FlatTree[ReadNode].ToArgInfo.ArgType;
823 }
824
825 void GetExpressionDiff(Expr *&FromExpr, Expr *&ToExpr) {
826 assert(FlatTree[ReadNode].Kind == Expression && "Unexpected kind");
827 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
828 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
829 }
830
832 assert(FlatTree[ReadNode].Kind == TemplateTemplate && "Unexpected kind.");
833 FromTD = FlatTree[ReadNode].FromArgInfo.TD;
834 ToTD = FlatTree[ReadNode].ToArgInfo.TD;
835 }
836
837 void GetIntegerDiff(llvm::APSInt &FromInt, llvm::APSInt &ToInt,
838 bool &IsValidFromInt, bool &IsValidToInt,
840 Expr *&FromExpr, Expr *&ToExpr) {
841 assert(FlatTree[ReadNode].Kind == Integer && "Unexpected kind.");
842 FromInt = FlatTree[ReadNode].FromArgInfo.Val;
843 ToInt = FlatTree[ReadNode].ToArgInfo.Val;
844 IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
845 IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
846 FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
847 ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
848 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
849 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
850 }
851
852 void GetDeclarationDiff(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
853 bool &FromAddressOf, bool &ToAddressOf,
854 bool &FromNullPtr, bool &ToNullPtr, Expr *&FromExpr,
855 Expr *&ToExpr) {
856 assert(FlatTree[ReadNode].Kind == Declaration && "Unexpected kind.");
857 FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
858 ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
859 FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
860 ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
861 FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
862 ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
863 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
864 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
865 }
866
867 void GetFromDeclarationAndToIntegerDiff(
868 ValueDecl *&FromValueDecl, bool &FromAddressOf, bool &FromNullPtr,
869 Expr *&FromExpr, llvm::APSInt &ToInt, bool &IsValidToInt,
871 assert(FlatTree[ReadNode].Kind == FromDeclarationAndToInteger &&
872 "Unexpected kind.");
873 FromValueDecl = FlatTree[ReadNode].FromArgInfo.VD;
874 FromAddressOf = FlatTree[ReadNode].FromArgInfo.NeedAddressOf;
875 FromNullPtr = FlatTree[ReadNode].FromArgInfo.IsNullPtr;
876 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
877 ToInt = FlatTree[ReadNode].ToArgInfo.Val;
878 IsValidToInt = FlatTree[ReadNode].ToArgInfo.IsValidInt;
879 ToIntType = FlatTree[ReadNode].ToArgInfo.ArgType;
880 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
881 }
882
883 void GetFromIntegerAndToDeclarationDiff(
884 llvm::APSInt &FromInt, bool &IsValidFromInt, QualType &FromIntType,
885 Expr *&FromExpr, ValueDecl *&ToValueDecl, bool &ToAddressOf,
886 bool &ToNullPtr, Expr *&ToExpr) {
887 assert(FlatTree[ReadNode].Kind == FromIntegerAndToDeclaration &&
888 "Unexpected kind.");
889 FromInt = FlatTree[ReadNode].FromArgInfo.Val;
890 IsValidFromInt = FlatTree[ReadNode].FromArgInfo.IsValidInt;
891 FromIntType = FlatTree[ReadNode].FromArgInfo.ArgType;
892 FromExpr = FlatTree[ReadNode].FromArgInfo.ArgExpr;
893 ToValueDecl = FlatTree[ReadNode].ToArgInfo.VD;
894 ToAddressOf = FlatTree[ReadNode].ToArgInfo.NeedAddressOf;
895 ToNullPtr = FlatTree[ReadNode].ToArgInfo.IsNullPtr;
896 ToExpr = FlatTree[ReadNode].ToArgInfo.ArgExpr;
897 }
898
899
900 bool FromDefault() {
901 return FlatTree[ReadNode].FromArgInfo.IsDefault;
902 }
903
904
905 bool ToDefault() {
906 return FlatTree[ReadNode].ToArgInfo.IsDefault;
907 }
908
909
910 bool NodeIsSame() {
911 return FlatTree[ReadNode].Same;
912 }
913
914
915 bool HasChildren() {
916 return FlatTree[ReadNode].ChildNode != 0;
917 }
918
919
920 void MoveToChild() {
921 ReadNode = FlatTree[ReadNode].ChildNode;
922 }
923
924
925
926 bool AdvanceSibling() {
927 if (FlatTree[ReadNode].NextNode == 0)
928 return false;
929
930 ReadNode = FlatTree[ReadNode].NextNode;
931 return true;
932 }
933
934
935 bool HasNextSibling() {
936 return FlatTree[ReadNode].NextNode != 0;
937 }
938
939
941 return GetKind() == Invalid;
942 }
943
944
945 DiffKind GetKind() {
946 return FlatTree[ReadNode].Kind;
947 }
948 };
949
950 DiffTree Tree;
951
952
953
954
955
956 class TSTiterator {
959
960
961
962
963 struct InternalIterator {
964
965
967
968
969 unsigned Index;
970
971
972
974
975
977
978
979
981 : TST(TST), Index(0), CurrentTA(nullptr), EndTA(nullptr) {
982 if (!TST) return;
983
984 if (isEnd()) return;
985
986
989
990
993
994
995 if (CurrentTA != EndTA) return;
996
997
998
999 ++(*this);
1000 }
1001
1002
1003 bool isValid() const { return TST; }
1004
1005
1006 bool isEnd() const {
1007 assert(TST && "InternalIterator is invalid with a null TST.");
1009 }
1010
1011
1012 InternalIterator &operator++() {
1013 assert(TST && "InternalIterator is invalid with a null TST.");
1014 if (isEnd()) {
1015 return *this;
1016 }
1017
1018
1019 if (CurrentTA != EndTA) {
1020 ++CurrentTA;
1021 if (CurrentTA != EndTA)
1022 return *this;
1023 }
1024
1025
1026 while (true) {
1027
1029 break;
1030
1031
1034 break;
1035
1036
1039
1040
1041 if (CurrentTA != EndTA)
1042 break;
1043 }
1044 return *this;
1045 }
1046
1047
1049 assert(TST && "InternalIterator is invalid with a null TST.");
1050 assert(!isEnd() && "Index exceeds number of arguments.");
1051 if (CurrentTA == EndTA)
1053 else
1054 return *CurrentTA;
1055 }
1056
1057
1058 pointer operator->() const {
1059 assert(TST && "InternalIterator is invalid with a null TST.");
1061 }
1062 };
1063
1064 InternalIterator SugaredIterator;
1065 InternalIterator DesugaredIterator;
1066
1067 public:
1069 : SugaredIterator(TST),
1070 DesugaredIterator(
1071 (TST->isSugared() && !TST->isTypeAlias())
1072 ? GetTemplateSpecializationType(Context, TST->desugar())
1073 : nullptr) {}
1074
1075
1076 TSTiterator &operator++() {
1077 ++SugaredIterator;
1078 if (DesugaredIterator.isValid())
1079 ++DesugaredIterator;
1080 return *this;
1081 }
1082
1083
1085 return *SugaredIterator;
1086 }
1087
1088
1089 pointer operator->() const {
1091 }
1092
1093
1094 bool isEnd() const {
1095 return SugaredIterator.isEnd();
1096 }
1097
1098
1099
1100 bool hasDesugaredTA() const {
1101 return DesugaredIterator.isValid() && !DesugaredIterator.isEnd();
1102 }
1103
1104
1105 reference getDesugaredTA() const {
1106 assert(DesugaredIterator.isValid() &&
1107 "Desugared TemplateArgument should not be used.");
1108 return *DesugaredIterator;
1109 }
1110 };
1111
1112
1113
1114
1119 return TST;
1120
1122 Ty = SubstType->getReplacementType();
1123
1125
1126 if (!RT)
1127 return nullptr;
1128
1130 dyn_cast(RT->getDecl());
1131
1132 if (!CTSD)
1133 return nullptr;
1134
1139
1141 }
1142
1143
1144 static bool OnlyPerformTypeDiff(ASTContext &Context, QualType FromType,
1149 return true;
1150
1151 if (Context.hasSameType(FromType, ToType))
1152 return true;
1153
1154 FromArgTST = GetTemplateSpecializationType(Context, FromType);
1155 ToArgTST = GetTemplateSpecializationType(Context, ToType);
1156
1157 if (!FromArgTST || !ToArgTST)
1158 return true;
1159
1160 if (!hasSameTemplate(Context, FromArgTST, ToArgTST))
1161 return true;
1162
1163 return false;
1164 }
1165
1166
1167 void DiffTypes(const TSTiterator &FromIter, const TSTiterator &ToIter) {
1168 QualType FromType = GetType(FromIter);
1169 QualType ToType = GetType(ToIter);
1170
1171 bool FromDefault = FromIter.isEnd() && !FromType.isNull();
1172 bool ToDefault = ToIter.isEnd() && !ToType.isNull();
1173
1176 if (OnlyPerformTypeDiff(Context, FromType, ToType, FromArgTST, ToArgTST)) {
1177 Tree.SetTypeDiff(FromType, ToType, FromDefault, ToDefault);
1180 } else {
1181 assert(FromArgTST && ToArgTST &&
1182 "Both template specializations need to be valid.");
1189 FromQual, ToQual, FromDefault, ToDefault);
1190 DiffTemplate(FromArgTST, ToArgTST);
1191 }
1192 }
1193
1194
1195
1196 void DiffTemplateTemplates(const TSTiterator &FromIter,
1197 const TSTiterator &ToIter) {
1199 TemplateDecl *ToDecl = GetTemplateDecl(ToIter);
1200 Tree.SetTemplateTemplateDiff(FromDecl, ToDecl, FromIter.isEnd() && FromDecl,
1201 ToIter.isEnd() && ToDecl);
1204 }
1205
1206
1207 static void InitializeNonTypeDiffVariables(ASTContext &Context,
1208 const TSTiterator &Iter,
1210 llvm::APSInt &Value, bool &HasInt,
1211 QualType &IntType, bool &IsNullPtr,
1213 bool &NeedAddressOf) {
1214 if (.isEnd()) {
1215 switch (Iter->getKind()) {
1217
1218
1219
1220 return;
1223 HasInt = true;
1224 IntType = Iter->getIntegralType();
1225 return;
1227 VD = Iter->getAsDecl();
1228 QualType ArgType = Iter->getParamTypeForDecl();
1232 NeedAddressOf = true;
1233 return;
1234 }
1236 IsNullPtr = true;
1237 return;
1240 break;
1245 llvm_unreachable("TemplateArgument kind is not expected for NTTP");
1247 llvm_unreachable("TemplateArgument kind should be handled elsewhere");
1248 }
1249 } else if (->isParameterPack()) {
1250 E = Default->getDefaultArgument().getArgument().getAsExpr();
1251 }
1252
1253 if (.hasDesugaredTA())
1254 return;
1255
1259
1260
1261 return;
1264 HasInt = true;
1266 return;
1273 NeedAddressOf = true;
1274 return;
1275 }
1277 IsNullPtr = true;
1278 return;
1280
1281
1282
1283 if ()
1285 return;
1290 llvm_unreachable("TemplateArgument kind is not expected for NTTP");
1292 llvm_unreachable("TemplateArgument kind should be handled elsewhere");
1293 }
1294 llvm_unreachable("Unexpected TemplateArgument kind");
1295 }
1296
1297
1298
1299 void DiffNonTypes(const TSTiterator &FromIter, const TSTiterator &ToIter,
1302 Expr *FromExpr = nullptr, *ToExpr = nullptr;
1303 llvm::APSInt FromInt, ToInt;
1304 QualType FromIntType, ToIntType;
1305 ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr;
1306 bool HasFromInt = false, HasToInt = false, FromNullPtr = false,
1307 ToNullPtr = false, NeedFromAddressOf = false, NeedToAddressOf = false;
1308 InitializeNonTypeDiffVariables(
1309 Context, FromIter, FromDefaultNonTypeDecl, FromInt, HasFromInt,
1310 FromIntType, FromNullPtr, FromExpr, FromValueDecl, NeedFromAddressOf);
1311 InitializeNonTypeDiffVariables(Context, ToIter, ToDefaultNonTypeDecl, ToInt,
1312 HasToInt, ToIntType, ToNullPtr, ToExpr,
1313 ToValueDecl, NeedToAddressOf);
1314
1315 bool FromDefault = FromIter.isEnd() &&
1316 (FromExpr || FromValueDecl || HasFromInt || FromNullPtr);
1317 bool ToDefault = ToIter.isEnd() &&
1318 (ToExpr || ToValueDecl || HasToInt || ToNullPtr);
1319
1320 bool FromDeclaration = FromValueDecl || FromNullPtr;
1321 bool ToDeclaration = ToValueDecl || ToNullPtr;
1322
1323 if (FromDeclaration && HasToInt) {
1324 Tree.SetFromDeclarationAndToIntegerDiff(
1325 FromValueDecl, NeedFromAddressOf, FromNullPtr, FromExpr, ToInt,
1326 HasToInt, ToIntType, ToExpr, FromDefault, ToDefault);
1327 Tree.SetSame(false);
1328 return;
1329
1330 }
1331
1332 if (HasFromInt && ToDeclaration) {
1333 Tree.SetFromIntegerAndToDeclarationDiff(
1334 FromInt, HasFromInt, FromIntType, FromExpr, ToValueDecl,
1335 NeedToAddressOf, ToNullPtr, ToExpr, FromDefault, ToDefault);
1336 Tree.SetSame(false);
1337 return;
1338 }
1339
1340 if (HasFromInt || HasToInt) {
1341 Tree.SetIntegerDiff(FromInt, ToInt, HasFromInt, HasToInt, FromIntType,
1342 ToIntType, FromExpr, ToExpr, FromDefault, ToDefault);
1343 if (HasFromInt && HasToInt) {
1344 Tree.SetSame(Context.hasSameType(FromIntType, ToIntType) &&
1345 FromInt == ToInt);
1346 }
1347 return;
1348 }
1349
1350 if (FromDeclaration || ToDeclaration) {
1351 Tree.SetDeclarationDiff(FromValueDecl, ToValueDecl, NeedFromAddressOf,
1352 NeedToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
1353 ToExpr, FromDefault, ToDefault);
1354 bool BothNull = FromNullPtr && ToNullPtr;
1355 bool SameValueDecl =
1356 FromValueDecl && ToValueDecl &&
1357 NeedFromAddressOf == NeedToAddressOf &&
1359 Tree.SetSame(BothNull || SameValueDecl);
1360 return;
1361 }
1362
1363 assert((FromExpr || ToExpr) && "Both template arguments cannot be empty.");
1364 Tree.SetExpressionDiff(FromExpr, ToExpr, FromDefault, ToDefault);
1365 Tree.SetSame(IsEqualExpr(Context, FromExpr, ToExpr));
1366 }
1367
1368
1369
1372
1373
1374
1383 unsigned TotalArgs = 0;
1384 for (TSTiterator FromIter(Context, FromTST), ToIter(Context, ToTST);
1385 !FromIter.isEnd() || !ToIter.isEnd(); ++TotalArgs) {
1386 Tree.AddNode();
1387
1388
1389
1390
1391 unsigned FromParamIndex = std::min(TotalArgs, ParamsFrom->size() - 1);
1392 unsigned ToParamIndex = std::min(TotalArgs, ParamsTo->size() - 1);
1395
1396 assert(FromParamND->getKind() == ToParamND->getKind() &&
1397 "Parameter Decl are not the same kind.");
1398
1399 if (isa(FromParamND)) {
1400 DiffTypes(FromIter, ToIter);
1401 } else if (isa(FromParamND)) {
1402 DiffTemplateTemplates(FromIter, ToIter);
1403 } else if (isa(FromParamND)) {
1405 cast(FromParamND);
1407 cast(ToParamND);
1408 DiffNonTypes(FromIter, ToIter, FromDefaultNonTypeDecl,
1409 ToDefaultNonTypeDecl);
1410 } else {
1411 llvm_unreachable("Unexpected Decl type.");
1412 }
1413
1414 ++FromIter;
1415 ++ToIter;
1417 }
1418 }
1419
1420
1421 static void makeTemplateList(
1424 while (TST) {
1425 TemplateList.push_back(TST);
1427 return;
1429 }
1430 }
1431
1432
1433
1434 static bool hasSameBaseTemplate(ASTContext &Context,
1438 true) ==
1440 true);
1441 }
1442
1443
1444
1445
1446
1447 static bool hasSameTemplate(ASTContext &Context,
1450
1451 if (hasSameBaseTemplate(Context, FromTST, ToTST))
1452 return true;
1453
1454
1456 ToTemplateList;
1457
1458 makeTemplateList(FromTemplateList, FromTST);
1459 makeTemplateList(ToTemplateList, ToTST);
1460
1462 FromIter = FromTemplateList.rbegin(), FromEnd = FromTemplateList.rend(),
1463 ToIter = ToTemplateList.rbegin(), ToEnd = ToTemplateList.rend();
1464
1465
1466 if (!hasSameBaseTemplate(Context, *FromIter, *ToIter))
1467 return false;
1468
1469
1470
1471
1472 for (; FromIter != FromEnd && ToIter != ToEnd; ++FromIter, ++ToIter) {
1473 if (!hasSameBaseTemplate(Context, *FromIter, *ToIter))
1474 break;
1475 }
1476
1477 FromTST = FromIter[-1];
1478 ToTST = ToIter[-1];
1479
1480 return true;
1481 }
1482
1483
1484
1485 static QualType GetType(const TSTiterator &Iter) {
1486 if (.isEnd())
1487 return Iter->getAsType();
1488 if (Iter.hasDesugaredTA())
1489 return Iter.getDesugaredTA().getAsType();
1491 }
1492
1493
1494
1495 static TemplateDecl *GetTemplateDecl(const TSTiterator &Iter) {
1496 if (.isEnd())
1497 return Iter->getAsTemplate().getAsTemplateDecl();
1498 if (Iter.hasDesugaredTA())
1499 return Iter.getDesugaredTA().getAsTemplate().getAsTemplateDecl();
1500 return nullptr;
1501 }
1502
1503
1504
1505
1506 static bool IsEqualExpr(ASTContext &Context, Expr *FromExpr, Expr *ToExpr) {
1507 if (FromExpr == ToExpr)
1508 return true;
1509
1510 if (!FromExpr || !ToExpr)
1511 return false;
1512
1513 llvm::FoldingSetNodeID FromID, ToID;
1514 FromExpr->Profile(FromID, Context, true);
1515 ToExpr->Profile(ToID, Context, true);
1516 return FromID == ToID;
1517 }
1518
1519
1520
1521
1522
1523
1524 void TreeToString(int Indent = 1) {
1525 if (PrintTree) {
1526 OS << '\n';
1527 OS.indent(2 * Indent);
1528 ++Indent;
1529 }
1530
1531
1532
1533 switch (Tree.GetKind()) {
1534 case DiffTree::Invalid:
1535 llvm_unreachable("Template diffing failed with bad DiffNode");
1536 case DiffTree::Type: {
1538 Tree.GetTypeDiff(FromType, ToType);
1539 PrintTypeNames(FromType, ToType, Tree.FromDefault(), Tree.ToDefault(),
1540 Tree.NodeIsSame());
1541 return;
1542 }
1543 case DiffTree::Expression: {
1544 Expr *FromExpr, *ToExpr;
1545 Tree.GetExpressionDiff(FromExpr, ToExpr);
1546 PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(),
1547 Tree.NodeIsSame());
1548 return;
1549 }
1550 case DiffTree::TemplateTemplate: {
1552 Tree.GetTemplateTemplateDiff(FromTD, ToTD);
1553 PrintTemplateTemplate(FromTD, ToTD, Tree.FromDefault(),
1554 Tree.ToDefault(), Tree.NodeIsSame());
1555 return;
1556 }
1557 case DiffTree::Integer: {
1558 llvm::APSInt FromInt, ToInt;
1559 Expr *FromExpr, *ToExpr;
1560 bool IsValidFromInt, IsValidToInt;
1561 QualType FromIntType, ToIntType;
1562 Tree.GetIntegerDiff(FromInt, ToInt, IsValidFromInt, IsValidToInt,
1563 FromIntType, ToIntType, FromExpr, ToExpr);
1564 PrintAPSInt(FromInt, ToInt, IsValidFromInt, IsValidToInt, FromIntType,
1565 ToIntType, FromExpr, ToExpr, Tree.FromDefault(),
1566 Tree.ToDefault(), Tree.NodeIsSame());
1567 return;
1568 }
1569 case DiffTree::Declaration: {
1570 ValueDecl *FromValueDecl, *ToValueDecl;
1571 bool FromAddressOf, ToAddressOf;
1572 bool FromNullPtr, ToNullPtr;
1573 Expr *FromExpr, *ToExpr;
1574 Tree.GetDeclarationDiff(FromValueDecl, ToValueDecl, FromAddressOf,
1575 ToAddressOf, FromNullPtr, ToNullPtr, FromExpr,
1576 ToExpr);
1577 PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
1578 FromNullPtr, ToNullPtr, FromExpr, ToExpr,
1579 Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
1580 return;
1581 }
1582 case DiffTree::FromDeclarationAndToInteger: {
1584 bool FromAddressOf;
1585 bool FromNullPtr;
1586 Expr *FromExpr;
1587 llvm::APSInt ToInt;
1588 bool IsValidToInt;
1590 Expr *ToExpr;
1591 Tree.GetFromDeclarationAndToIntegerDiff(
1592 FromValueDecl, FromAddressOf, FromNullPtr, FromExpr, ToInt,
1593 IsValidToInt, ToIntType, ToExpr);
1594 assert((FromValueDecl || FromNullPtr) && IsValidToInt);
1595 PrintValueDeclAndInteger(FromValueDecl, FromAddressOf, FromNullPtr,
1596 FromExpr, Tree.FromDefault(), ToInt, ToIntType,
1597 ToExpr, Tree.ToDefault());
1598 return;
1599 }
1600 case DiffTree::FromIntegerAndToDeclaration: {
1601 llvm::APSInt FromInt;
1602 bool IsValidFromInt;
1604 Expr *FromExpr;
1606 bool ToAddressOf;
1607 bool ToNullPtr;
1608 Expr *ToExpr;
1609 Tree.GetFromIntegerAndToDeclarationDiff(
1610 FromInt, IsValidFromInt, FromIntType, FromExpr, ToValueDecl,
1611 ToAddressOf, ToNullPtr, ToExpr);
1612 assert(IsValidFromInt && (ToValueDecl || ToNullPtr));
1613 PrintIntegerAndValueDecl(FromInt, FromIntType, FromExpr,
1614 Tree.FromDefault(), ToValueDecl, ToAddressOf,
1615 ToNullPtr, ToExpr, Tree.ToDefault());
1616 return;
1617 }
1618 case DiffTree::Template: {
1619
1622 Tree.GetTemplateDiff(FromTD, ToTD, FromQual, ToQual);
1623
1624 PrintQualifiers(FromQual, ToQual);
1625
1626 if (.HasChildren()) {
1627
1628
1630 return;
1631 }
1632
1634 Tree.MoveToChild();
1635 unsigned NumElideArgs = 0;
1636 bool AllArgsElided = true;
1637 do {
1638 if (ElideType) {
1639 if (Tree.NodeIsSame()) {
1640 ++NumElideArgs;
1641 continue;
1642 }
1643 AllArgsElided = false;
1644 if (NumElideArgs > 0) {
1645 PrintElideArgs(NumElideArgs, Indent);
1646 NumElideArgs = 0;
1647 OS << ", ";
1648 }
1649 }
1650 TreeToString(Indent);
1651 if (Tree.HasNextSibling())
1652 OS << ", ";
1653 } while (Tree.AdvanceSibling());
1654 if (NumElideArgs > 0) {
1655 if (AllArgsElided)
1656 OS << "...";
1657 else
1658 PrintElideArgs(NumElideArgs, Indent);
1659 }
1660
1661 Tree.Parent();
1662 OS << ">";
1663 return;
1664 }
1665 }
1666 }
1667
1668
1669
1670
1671
1672
1673 void Bold() {
1674 assert(!IsBold && "Attempting to bold text that is already bold.");
1675 IsBold = true;
1676 if (ShowColor)
1678 }
1679
1680
1681 void Unbold() {
1682 assert(IsBold && "Attempting to remove bold from unbold text.");
1683 IsBold = false;
1684 if (ShowColor)
1686 }
1687
1688
1689
1690
1691
1692
1694 bool FromDefault, bool ToDefault, bool Same) {
1695 assert((!FromType.isNull() || !ToType.isNull()) &&
1696 "Only one template argument may be missing.");
1697
1698 if (Same) {
1700 return;
1701 }
1702
1703 if (!FromType.isNull() && !ToType.isNull() &&
1708 PrintQualifiers(FromQual, ToQual);
1710 return;
1711 }
1712
1713 std::string FromTypeStr = FromType.isNull() ? "(no argument)"
1715 std::string ToTypeStr = ToType.isNull() ? "(no argument)"
1717
1718
1719 if (FromTypeStr == ToTypeStr) {
1720 const auto *FromElTy = dyn_cast(FromType),
1721 *ToElTy = dyn_cast(ToType);
1722 if (FromElTy || ToElTy) {
1723 std::string FromNamedTypeStr =
1724 FromElTy ? FromElTy->getNamedType().getAsString(Policy)
1725 : FromTypeStr;
1726 std::string ToNamedTypeStr =
1727 ToElTy ? ToElTy->getNamedType().getAsString(Policy) : ToTypeStr;
1728 if (FromNamedTypeStr != ToNamedTypeStr) {
1729 FromTypeStr = FromNamedTypeStr;
1730 ToTypeStr = ToNamedTypeStr;
1731 goto PrintTypes;
1732 }
1733 }
1734
1735 std::string FromCanTypeStr =
1738 if (FromCanTypeStr != ToCanTypeStr) {
1739 FromTypeStr = FromCanTypeStr;
1740 ToTypeStr = ToCanTypeStr;
1741 }
1742 }
1743
1744 PrintTypes:
1745 if (PrintTree) OS << '[';
1746 OS << (FromDefault ? "(default) " : "");
1748 OS << FromTypeStr;
1749 Unbold();
1750 if (PrintTree) {
1751 OS << " != " << (ToDefault ? "(default) " : "");
1753 OS << ToTypeStr;
1754 Unbold();
1755 OS << "]";
1756 }
1757 }
1758
1759
1760
1761 void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromDefault,
1762 bool ToDefault, bool Same) {
1763 assert((FromExpr || ToExpr) &&
1764 "Only one template argument may be missing.");
1765 if (Same) {
1766 PrintExpr(FromExpr);
1767 } else if (!PrintTree) {
1768 OS << (FromDefault ? "(default) " : "");
1770 PrintExpr(FromExpr);
1771 Unbold();
1772 } else {
1773 OS << (FromDefault ? "[(default) " : "[");
1775 PrintExpr(FromExpr);
1776 Unbold();
1777 OS << " != " << (ToDefault ? "(default) " : "");
1779 PrintExpr(ToExpr);
1780 Unbold();
1781 OS << ']';
1782 }
1783 }
1784
1785
1786 void PrintExpr(const Expr *E) {
1787 if (E) {
1789 return;
1790 }
1791 OS << "(no argument)";
1792 }
1793
1794
1795
1797 bool FromDefault, bool ToDefault, bool Same) {
1798 assert((FromTD || ToTD) && "Only one template argument may be missing.");
1799
1800 std::string FromName =
1801 std::string(FromTD ? FromTD->getName() : "(no argument)");
1802 std::string ToName = std::string(ToTD ? ToTD->getName() : "(no argument)");
1803 if (FromTD && ToTD && FromName == ToName) {
1806 }
1807
1808 if (Same) {
1809 OS << "template " << FromTD->getDeclName();
1810 } else if (!PrintTree) {
1811 OS << (FromDefault ? "(default) template " : "template ");
1813 OS << FromName;
1814 Unbold();
1815 } else {
1816 OS << (FromDefault ? "[(default) template " : "[template ");
1818 OS << FromName;
1819 Unbold();
1820 OS << " != " << (ToDefault ? "(default) template " : "template ");
1822 OS << ToName;
1823 Unbold();
1824 OS << ']';
1825 }
1826 }
1827
1828
1829
1830 void PrintAPSInt(const llvm::APSInt &FromInt, const llvm::APSInt &ToInt,
1831 bool IsValidFromInt, bool IsValidToInt, QualType FromIntType,
1833 bool FromDefault, bool ToDefault, bool Same) {
1834 assert((IsValidFromInt || IsValidToInt) &&
1835 "Only one integral argument may be missing.");
1836
1837 if (Same) {
1839 OS << ((FromInt == 0) ? "false" : "true");
1840 } else {
1841 OS << toString(FromInt, 10);
1842 }
1843 return;
1844 }
1845
1846 bool PrintType = IsValidFromInt && IsValidToInt &&
1847 !Context.hasSameType(FromIntType, ToIntType);
1848
1849 if (!PrintTree) {
1850 OS << (FromDefault ? "(default) " : "");
1851 PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
1852 } else {
1853 OS << (FromDefault ? "[(default) " : "[");
1854 PrintAPSInt(FromInt, FromExpr, IsValidFromInt, FromIntType, PrintType);
1855 OS << " != " << (ToDefault ? "(default) " : "");
1856 PrintAPSInt(ToInt, ToExpr, IsValidToInt, ToIntType, PrintType);
1857 OS << ']';
1858 }
1859 }
1860
1861
1862
1863 void PrintAPSInt(const llvm::APSInt &Val, Expr *E, bool Valid,
1864 QualType IntType, bool PrintType) {
1866 if (Valid) {
1867 if (HasExtraInfo(E)) {
1868 PrintExpr(E);
1869 Unbold();
1870 OS << " aka ";
1872 }
1873 if (PrintType) {
1874 Unbold();
1875 OS << "(";
1878 Unbold();
1879 OS << ") ";
1881 }
1883 OS << ((Val == 0) ? "false" : "true");
1884 } else {
1886 }
1887 } else if (E) {
1888 PrintExpr(E);
1889 } else {
1890 OS << "(no argument)";
1891 }
1892 Unbold();
1893 }
1894
1895
1896
1897 bool HasExtraInfo(Expr *E) {
1898 if () return false;
1899
1901
1902 auto CheckIntegerLiteral = [](Expr *E) {
1903 if (auto *TemplateExpr = dyn_cast(E))
1904 E = TemplateExpr->getReplacement();
1905 return isa(E);
1906 };
1907
1908 if (CheckIntegerLiteral(E)) return false;
1909
1911 if (UO->getOpcode() == UO_Minus)
1912 if (CheckIntegerLiteral(UO->getSubExpr()))
1913 return false;
1914
1915 if (isa(E))
1916 return false;
1917
1918 return true;
1919 }
1920
1921 void PrintValueDecl(ValueDecl *VD, bool AddressOf, Expr *E, bool NullPtr) {
1922 if (VD) {
1923 if (AddressOf)
1924 OS << "&";
1925 else if (auto *TPO = dyn_cast(VD)) {
1926
1927
1928
1929 TPO->getType().getUnqualifiedType().print(OS, Policy);
1930 TPO->printAsInit(OS, Policy);
1931 return;
1932 }
1934 return;
1935 }
1936
1937 if (NullPtr) {
1939 PrintExpr(E);
1940 if (IsBold) {
1941 Unbold();
1942 OS << " aka ";
1944 } else {
1945 OS << " aka ";
1946 }
1947 }
1948
1949 OS << "nullptr";
1950 return;
1951 }
1952
1953 if (E) {
1954 PrintExpr(E);
1955 return;
1956 }
1957
1958 OS << "(no argument)";
1959 }
1960
1961
1962
1963 void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
1964 bool FromAddressOf, bool ToAddressOf, bool FromNullPtr,
1965 bool ToNullPtr, Expr *FromExpr, Expr *ToExpr,
1966 bool FromDefault, bool ToDefault, bool Same) {
1967 assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) &&
1968 "Only one Decl argument may be NULL");
1969
1970 if (Same) {
1971 PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
1972 } else if (!PrintTree) {
1973 OS << (FromDefault ? "(default) " : "");
1975 PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
1976 Unbold();
1977 } else {
1978 OS << (FromDefault ? "[(default) " : "[");
1980 PrintValueDecl(FromValueDecl, FromAddressOf, FromExpr, FromNullPtr);
1981 Unbold();
1982 OS << " != " << (ToDefault ? "(default) " : "");
1984 PrintValueDecl(ToValueDecl, ToAddressOf, ToExpr, ToNullPtr);
1985 Unbold();
1986 OS << ']';
1987 }
1988 }
1989
1990
1991
1992 void PrintValueDeclAndInteger(ValueDecl *VD, bool NeedAddressOf,
1993 bool IsNullPtr, Expr *VDExpr, bool DefaultDecl,
1994 const llvm::APSInt &Val, QualType IntType,
1995 Expr *IntExpr, bool DefaultInt) {
1996 if (!PrintTree) {
1997 OS << (DefaultDecl ? "(default) " : "");
1999 PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
2000 Unbold();
2001 } else {
2002 OS << (DefaultDecl ? "[(default) " : "[");
2004 PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
2005 Unbold();
2006 OS << " != " << (DefaultInt ? "(default) " : "");
2007 PrintAPSInt(Val, IntExpr, true , IntType, false );
2008 OS << ']';
2009 }
2010 }
2011
2012
2013
2014 void PrintIntegerAndValueDecl(const llvm::APSInt &Val, QualType IntType,
2016 bool NeedAddressOf, bool IsNullPtr,
2017 Expr *VDExpr, bool DefaultDecl) {
2018 if (!PrintTree) {
2019 OS << (DefaultInt ? "(default) " : "");
2020 PrintAPSInt(Val, IntExpr, true , IntType, false );
2021 } else {
2022 OS << (DefaultInt ? "[(default) " : "[");
2023 PrintAPSInt(Val, IntExpr, true , IntType, false );
2024 OS << " != " << (DefaultDecl ? "(default) " : "");
2026 PrintValueDecl(VD, NeedAddressOf, VDExpr, IsNullPtr);
2027 Unbold();
2028 OS << ']';
2029 }
2030 }
2031
2032
2033 void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
2034 if (PrintTree) {
2035 OS << '\n';
2036 for (unsigned i = 0; i < Indent; ++i)
2037 OS << " ";
2038 }
2039 if (NumElideArgs == 0) return;
2040 if (NumElideArgs == 1)
2041 OS << "[...]";
2042 else
2043 OS << "[" << NumElideArgs << " * ...]";
2044 }
2045
2046
2048
2049 if (FromQual.empty() && ToQual.empty())
2050 return;
2051
2052
2053 if (FromQual == ToQual) {
2054 PrintQualifier(FromQual, false);
2055 return;
2056 }
2057
2058
2060 ToQual);
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072 if (PrintTree) {
2073 OS << "[";
2074 if (CommonQual.empty() && FromQual.empty()) {
2076 OS << "(no qualifiers) ";
2077 Unbold();
2078 } else {
2079 PrintQualifier(CommonQual, false);
2080 PrintQualifier(FromQual, true);
2081 }
2082 OS << "!= ";
2083 if (CommonQual.empty() && ToQual.empty()) {
2085 OS << "(no qualifiers)";
2086 Unbold();
2087 } else {
2088 PrintQualifier(CommonQual, false,
2089 !ToQual.empty());
2090 PrintQualifier(ToQual, true,
2091 false);
2092 }
2093 OS << "] ";
2094 } else {
2095 PrintQualifier(CommonQual, false);
2096 PrintQualifier(FromQual, true);
2097 }
2098 }
2099
2100 void PrintQualifier(Qualifiers Q, bool ApplyBold,
2101 bool AppendSpaceIfNonEmpty = true) {
2102 if (Q.empty()) return;
2103 if (ApplyBold) Bold();
2104 Q.print(OS, Policy, AppendSpaceIfNonEmpty);
2105 if (ApplyBold) Unbold();
2106 }
2107
2108public:
2109
2110 TemplateDiff(raw_ostream &OS, ASTContext &Context, QualType FromType,
2111 QualType ToType, bool PrintTree, bool PrintFromType,
2112 bool ElideType, bool ShowColor)
2113 : Context(Context),
2114 Policy(Context.getLangOpts()),
2115 ElideType(ElideType),
2116 PrintTree(PrintTree),
2117 ShowColor(ShowColor),
2118
2119 FromTemplateType(PrintFromType ? FromType : ToType),
2120 ToTemplateType(PrintFromType ? ToType : FromType),
2121 OS(OS),
2123 }
2124
2125
2126 void DiffTemplate() {
2129
2131 GetTemplateSpecializationType(Context, FromTemplateType);
2133 GetTemplateSpecializationType(Context, ToTemplateType);
2134
2135
2136 if (!FromOrigTST || !ToOrigTST)
2137 return;
2138
2139
2140 if (!hasSameTemplate(Context, FromOrigTST, ToOrigTST)) {
2141 return;
2142 }
2143
2146
2147
2148 Tree.SetTemplateDiff(
2150 true),
2152 FromQual, ToQual, false , false );
2153
2154 DiffTemplate(FromOrigTST, ToOrigTST);
2155 }
2156
2157
2158
2159
2160 bool Emit() {
2161 Tree.StartTraverse();
2162 if (Tree.Empty())
2163 return false;
2164
2165 TreeToString();
2166 assert(!IsBold && "Bold is applied to end of string.");
2167 return true;
2168 }
2169};
2170}
2171
2172
2173
2174
2176 QualType ToType, bool PrintTree,
2177 bool PrintFromType, bool ElideType,
2179 if (PrintTree)
2180 PrintFromType = true;
2181 TemplateDiff TD(OS, Context, FromType, ToType, PrintTree, PrintFromType,
2183 TD.DiffTemplate();
2184 return TD.Emit();
2185}
Defines the clang::ASTContext interface.
static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, QualType ToType, bool PrintTree, bool PrintFromType, bool ElideType, bool ShowColors, raw_ostream &OS)
FormatTemplateTypeDiff - A helper static function to start the template diff and return the properly ...
static std::string ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, ArrayRef< DiagnosticsEngine::ArgumentValue > PrevArgs, ArrayRef< intptr_t > QualTypeVals)
Convert the given type to a string suitable for printing as part of a diagnostic.
This file provides some common utility functions for processing Lambda related AST Constructs.
clang::CharUnits operator*(clang::CharUnits::QuantityType Scale, const clang::CharUnits &CU)
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.
const NamedDecl * FromDecl
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
QualType getRValueReferenceType(QualType T) const
Return the uniqued reference to the type for an rvalue reference to the specified type.
QualType getBuiltinVaListType() const
Retrieve the type of the __builtin_va_list type.
QualType getObjCClassType() const
Represents the Objective-C Class type.
QualType getAttributedType(attr::Kind attrKind, QualType modifiedType, QualType equivalentType, const Attr *attr=nullptr) const
QualType getTemplateSpecializationType(TemplateName T, ArrayRef< TemplateArgument > Args, QualType Canon=QualType()) const
QualType getBuiltinMSVaListType() const
Retrieve the type of the __builtin_ms_va_list type.
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.
TemplateName getCanonicalTemplateName(TemplateName Name, bool IgnoreDeduced=false) const
Retrieves the "canonical" template name that refers to a given template.
QualType getPointerType(QualType T) const
Return the uniqued reference to the type for a pointer to the specified type.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const
Return the unique reference to the type for the specified type declaration.
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
QualType getObjCProtoType() const
Retrieve the type of the Objective-C Protocol class.
QualType getObjCSelType() const
Retrieve the type that corresponds to the predefined Objective-C 'SEL' type.
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
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.
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
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.
Attr - This represents one attribute.
const char * getSpelling() const
An attributed type is a type to which a type attribute has been applied.
static std::optional< NullabilityKind > stripOuterNullability(QualType &T)
Strip off the top-level nullability annotation on the given type, if it's there.
Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained by a type-constraint.
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...
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_declarationname
DeclarationName.
@ ak_nestednamespec
NestedNameSpecifier *.
Represents a type that was referred to using an elaborated type keyword, e.g., struct S,...
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.
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.
Represents a C++ nested name specifier, such as "\::std::vector::".
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.
Represents a class type in Objective C.
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].
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
RecordDecl * getDecl() const
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.
ArrayRef< TemplateArgument > asArray() const
Produce this as an array ref.
Represents a template argument.
QualType getParamTypeForDecl() const
Expr * getAsExpr() const
Retrieve the template argument as an expression.
pack_iterator pack_end() const
Iterator referencing one past the last argument of a template argument pack.
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.
The base class of all kinds of template declarations (e.g., class, function, etc.).
TemplateParameterList * getTemplateParameters() const
Get the list of template parameters.
Represents a C++ template name within the type system.
TemplateDecl * getAsTemplateDecl(bool IgnoreDeduced=false) const
Retrieve the underlying template declaration that this template name refers to, if known.
Stores a list of template parameters for a TemplateDecl and its derived classes.
NamedDecl * getParam(unsigned Idx)
Represents a type template specialization; the template must be a class template, a type alias templa...
QualType getAliasedType() const
Get the aliased type, if this is a specialization of a type alias template.
ArrayRef< TemplateArgument > template_arguments() const
TemplateName getTemplateName() const
Retrieve the name of the template that we are specializing.
bool isTypeAlias() const
Determine if this template specialization type is for a type alias template that has been substituted...
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'.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a GCC generic vector type.
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)
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.
__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