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 (Iter.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;

1239 E = Iter->getAsExpr();

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 (Default->isParameterPack()) {

1250 E = Default->getDefaultArgument().getArgument().getAsExpr();

1251 }

1252

1253 if (Iter.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 (E)

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 (Iter.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 (Iter.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 (Tree.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 (E) 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) {

1938 if (E && !isa(E)) {

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