annotate clang-tools-extra/clangd/InlayHints.cpp @ 266:00f31e85ec16 default tip

Added tag current for changeset 31d058e83c98
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 14 Oct 2023 10:13:55 +0900
parents 1f2b6ac9f198
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 //===--- InlayHints.cpp ------------------------------------------*- C++-*-===//
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 //
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 //
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 #include "InlayHints.h"
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
9 #include "AST.h"
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
10 #include "Config.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
11 #include "HeuristicResolver.h"
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 #include "ParsedAST.h"
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
13 #include "SourceCode.h"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
14 #include "clang/AST/ASTDiagnostic.h"
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
15 #include "clang/AST/Decl.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 #include "clang/AST/DeclarationName.h"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
17 #include "clang/AST/Expr.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 #include "clang/AST/ExprCXX.h"
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 #include "clang/AST/RecursiveASTVisitor.h"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
20 #include "clang/AST/Stmt.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
21 #include "clang/AST/StmtVisitor.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
22 #include "clang/AST/Type.h"
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
23 #include "clang/Basic/Builtins.h"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
24 #include "clang/Basic/OperatorKinds.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 #include "clang/Basic/SourceManager.h"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
26 #include "llvm/ADT/DenseSet.h"
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
27 #include "llvm/ADT/ScopeExit.h"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
28 #include "llvm/ADT/StringExtras.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
29 #include "llvm/ADT/StringRef.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
30 #include "llvm/ADT/Twine.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
31 #include "llvm/Support/Casting.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
32 #include "llvm/Support/SaveAndRestore.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
33 #include "llvm/Support/ScopedPrinter.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
34 #include "llvm/Support/raw_ostream.h"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
35 #include <optional>
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
36 #include <string>
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
37
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 namespace clang {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 namespace clangd {
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
40 namespace {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
41
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
42 // For now, inlay hints are always anchored at the left or right of their range.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
43 enum class HintSide { Left, Right };
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
44
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
45 // Helper class to iterate over the designator names of an aggregate type.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
46 //
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
47 // For an array type, yields [0], [1], [2]...
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
48 // For aggregate classes, yields null for each base, then .field1, .field2, ...
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
49 class AggregateDesignatorNames {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
50 public:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
51 AggregateDesignatorNames(QualType T) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
52 if (!T.isNull()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
53 T = T.getCanonicalType();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
54 if (T->isArrayType()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
55 IsArray = true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
56 Valid = true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
57 return;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
58 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
59 if (const RecordDecl *RD = T->getAsRecordDecl()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
60 Valid = true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
61 FieldsIt = RD->field_begin();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
62 FieldsEnd = RD->field_end();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
63 if (const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(RD)) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
64 BasesIt = CRD->bases_begin();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
65 BasesEnd = CRD->bases_end();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
66 Valid = CRD->isAggregate();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
67 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
68 OneField = Valid && BasesIt == BasesEnd && FieldsIt != FieldsEnd &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
69 std::next(FieldsIt) == FieldsEnd;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
70 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
71 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
72 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
73 // Returns false if the type was not an aggregate.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
74 operator bool() { return Valid; }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
75 // Advance to the next element in the aggregate.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
76 void next() {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
77 if (IsArray)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
78 ++Index;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
79 else if (BasesIt != BasesEnd)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
80 ++BasesIt;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
81 else if (FieldsIt != FieldsEnd)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
82 ++FieldsIt;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
83 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
84 // Print the designator to Out.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
85 // Returns false if we could not produce a designator for this element.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
86 bool append(std::string &Out, bool ForSubobject) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
87 if (IsArray) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
88 Out.push_back('[');
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
89 Out.append(std::to_string(Index));
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
90 Out.push_back(']');
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
91 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
92 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
93 if (BasesIt != BasesEnd)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
94 return false; // Bases can't be designated. Should we make one up?
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
95 if (FieldsIt != FieldsEnd) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
96 llvm::StringRef FieldName;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
97 if (const IdentifierInfo *II = FieldsIt->getIdentifier())
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
98 FieldName = II->getName();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
99
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
100 // For certain objects, their subobjects may be named directly.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
101 if (ForSubobject &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
102 (FieldsIt->isAnonymousStructOrUnion() ||
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
103 // std::array<int,3> x = {1,2,3}. Designators not strictly valid!
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
104 (OneField && isReservedName(FieldName))))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
105 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
106
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
107 if (!FieldName.empty() && !isReservedName(FieldName)) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
108 Out.push_back('.');
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
109 Out.append(FieldName.begin(), FieldName.end());
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
110 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
111 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
112 return false;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
113 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
114 return false;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
115 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
116
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
117 private:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
118 bool Valid = false;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
119 bool IsArray = false;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
120 bool OneField = false; // e.g. std::array { T __elements[N]; }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
121 unsigned Index = 0;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
122 CXXRecordDecl::base_class_const_iterator BasesIt;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
123 CXXRecordDecl::base_class_const_iterator BasesEnd;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
124 RecordDecl::field_iterator FieldsIt;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
125 RecordDecl::field_iterator FieldsEnd;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
126 };
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
127
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
128 // Collect designator labels describing the elements of an init list.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
129 //
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
130 // This function contributes the designators of some (sub)object, which is
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
131 // represented by the semantic InitListExpr Sem.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
132 // This includes any nested subobjects, but *only* if they are part of the same
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
133 // original syntactic init list (due to brace elision).
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
134 // In other words, it may descend into subobjects but not written init-lists.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
135 //
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
136 // For example: struct Outer { Inner a,b; }; struct Inner { int x, y; }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
137 // Outer o{{1, 2}, 3};
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
138 // This function will be called with Sem = { {1, 2}, {3, ImplicitValue} }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
139 // It should generate designators '.a:' and '.b.x:'.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
140 // '.a:' is produced directly without recursing into the written sublist.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
141 // (The written sublist will have a separate collectDesignators() call later).
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
142 // Recursion with Prefix='.b' and Sem = {3, ImplicitValue} produces '.b.x:'.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
143 void collectDesignators(const InitListExpr *Sem,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
144 llvm::DenseMap<SourceLocation, std::string> &Out,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
145 const llvm::DenseSet<SourceLocation> &NestedBraces,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
146 std::string &Prefix) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
147 if (!Sem || Sem->isTransparent())
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
148 return;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
149 assert(Sem->isSemanticForm());
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
150
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
151 // The elements of the semantic form all correspond to direct subobjects of
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
152 // the aggregate type. `Fields` iterates over these subobject names.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
153 AggregateDesignatorNames Fields(Sem->getType());
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
154 if (!Fields)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
155 return;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
156 for (const Expr *Init : Sem->inits()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
157 auto Next = llvm::make_scope_exit([&, Size(Prefix.size())] {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
158 Fields.next(); // Always advance to the next subobject name.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
159 Prefix.resize(Size); // Erase any designator we appended.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
160 });
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
161 // Skip for a broken initializer or if it is a "hole" in a subobject that
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
162 // was not explicitly initialized.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
163 if (!Init || llvm::isa<ImplicitValueInitExpr>(Init))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
164 continue;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
165
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
166 const auto *BraceElidedSubobject = llvm::dyn_cast<InitListExpr>(Init);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
167 if (BraceElidedSubobject &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
168 NestedBraces.contains(BraceElidedSubobject->getLBraceLoc()))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
169 BraceElidedSubobject = nullptr; // there were braces!
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
170
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
171 if (!Fields.append(Prefix, BraceElidedSubobject != nullptr))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
172 continue; // no designator available for this subobject
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
173 if (BraceElidedSubobject) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
174 // If the braces were elided, this aggregate subobject is initialized
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
175 // inline in the same syntactic list.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
176 // Descend into the semantic list describing the subobject.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
177 // (NestedBraces are still correct, they're from the same syntactic list).
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
178 collectDesignators(BraceElidedSubobject, Out, NestedBraces, Prefix);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
179 continue;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
180 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
181 Out.try_emplace(Init->getBeginLoc(), Prefix);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
182 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
183 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
184
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
185 // Get designators describing the elements of a (syntactic) init list.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
186 // This does not produce designators for any explicitly-written nested lists.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
187 llvm::DenseMap<SourceLocation, std::string>
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
188 getDesignators(const InitListExpr *Syn) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
189 assert(Syn->isSyntacticForm());
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
190
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
191 // collectDesignators needs to know which InitListExprs in the semantic tree
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
192 // were actually written, but InitListExpr::isExplicit() lies.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
193 // Instead, record where braces of sub-init-lists occur in the syntactic form.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
194 llvm::DenseSet<SourceLocation> NestedBraces;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
195 for (const Expr *Init : Syn->inits())
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
196 if (auto *Nested = llvm::dyn_cast<InitListExpr>(Init))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
197 NestedBraces.insert(Nested->getLBraceLoc());
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
198
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
199 // Traverse the semantic form to find the designators.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
200 // We use their SourceLocation to correlate with the syntactic form later.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
201 llvm::DenseMap<SourceLocation, std::string> Designators;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
202 std::string EmptyPrefix;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
203 collectDesignators(Syn->isSemanticForm() ? Syn : Syn->getSemanticForm(),
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
204 Designators, NestedBraces, EmptyPrefix);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
205 return Designators;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
206 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
207
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
208 void stripLeadingUnderscores(StringRef &Name) { Name = Name.ltrim('_'); }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
209
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
210 // getDeclForType() returns the decl responsible for Type's spelling.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
211 // This is the inverse of ASTContext::getTypeDeclType().
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
212 template <typename Ty, typename = decltype(((Ty *)nullptr)->getDecl())>
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
213 const NamedDecl *getDeclForTypeImpl(const Ty *T) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
214 return T->getDecl();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
215 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
216 const NamedDecl *getDeclForTypeImpl(const void *T) { return nullptr; }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
217 const NamedDecl *getDeclForType(const Type *T) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
218 switch (T->getTypeClass()) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
219 #define ABSTRACT_TYPE(TY, BASE)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
220 #define TYPE(TY, BASE) \
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
221 case Type::TY: \
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
222 return getDeclForTypeImpl(llvm::cast<TY##Type>(T));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
223 #include "clang/AST/TypeNodes.inc"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
224 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
225 llvm_unreachable("Unknown TypeClass enum");
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
226 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
227
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
228 // getSimpleName() returns the plain identifier for an entity, if any.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
229 llvm::StringRef getSimpleName(const DeclarationName &DN) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
230 if (IdentifierInfo *Ident = DN.getAsIdentifierInfo())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
231 return Ident->getName();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
232 return "";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
233 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
234 llvm::StringRef getSimpleName(const NamedDecl &D) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
235 return getSimpleName(D.getDeclName());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
236 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
237 llvm::StringRef getSimpleName(QualType T) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
238 if (const auto *ET = llvm::dyn_cast<ElaboratedType>(T))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
239 return getSimpleName(ET->getNamedType());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
240 if (const auto *BT = llvm::dyn_cast<BuiltinType>(T)) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
241 PrintingPolicy PP(LangOptions{});
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
242 PP.adjustForCPlusPlus();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
243 return BT->getName(PP);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
244 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
245 if (const auto *D = getDeclForType(T.getTypePtr()))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
246 return getSimpleName(D->getDeclName());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
247 return "";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
248 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
249
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
250 // Returns a very abbreviated form of an expression, or "" if it's too complex.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
251 // For example: `foo->bar()` would produce "bar".
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
252 // This is used to summarize e.g. the condition of a while loop.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
253 std::string summarizeExpr(const Expr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
254 struct Namer : ConstStmtVisitor<Namer, std::string> {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
255 std::string Visit(const Expr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
256 if (E == nullptr)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
257 return "";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
258 return ConstStmtVisitor::Visit(E->IgnoreImplicit());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
259 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
260
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
261 // Any sort of decl reference, we just use the unqualified name.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
262 std::string VisitMemberExpr(const MemberExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
263 return getSimpleName(*E->getMemberDecl()).str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
264 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
265 std::string VisitDeclRefExpr(const DeclRefExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
266 return getSimpleName(*E->getFoundDecl()).str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
267 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
268 std::string VisitCallExpr(const CallExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
269 return Visit(E->getCallee());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
270 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
271 std::string
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
272 VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
273 return getSimpleName(E->getMember()).str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
274 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
275 std::string
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
276 VisitDependentScopeMemberExpr(const DependentScopeDeclRefExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
277 return getSimpleName(E->getDeclName()).str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
278 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
279 std::string VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
280 return getSimpleName(E->getType()).str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
281 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
282 std::string VisitCXXTemporaryObjectExpr(const CXXTemporaryObjectExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
283 return getSimpleName(E->getType()).str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
284 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
285
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
286 // Step through implicit nodes that clang doesn't classify as such.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
287 std::string VisitCXXMemberCallExpr(const CXXMemberCallExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
288 // Call to operator bool() inside if (X): dispatch to X.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
289 if (E->getNumArgs() == 0 &&
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
290 E->getMethodDecl()->getDeclName().getNameKind() ==
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
291 DeclarationName::CXXConversionFunctionName &&
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
292 E->getSourceRange() ==
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
293 E->getImplicitObjectArgument()->getSourceRange())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
294 return Visit(E->getImplicitObjectArgument());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
295 return ConstStmtVisitor::VisitCXXMemberCallExpr(E);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
296 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
297 std::string VisitCXXConstructExpr(const CXXConstructExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
298 if (E->getNumArgs() == 1)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
299 return Visit(E->getArg(0));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
300 return "";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
301 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
302
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
303 // Literals are just printed
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
304 std::string VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
305 return E->getValue() ? "true" : "false";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
306 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
307 std::string VisitIntegerLiteral(const IntegerLiteral *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
308 return llvm::to_string(E->getValue());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
309 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
310 std::string VisitFloatingLiteral(const FloatingLiteral *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
311 std::string Result;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
312 llvm::raw_string_ostream OS(Result);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
313 E->getValue().print(OS);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
314 // Printer adds newlines?!
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
315 Result.resize(llvm::StringRef(Result).rtrim().size());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
316 return Result;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
317 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
318 std::string VisitStringLiteral(const StringLiteral *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
319 std::string Result = "\"";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
320 if (E->containsNonAscii()) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
321 Result += "...";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
322 } else if (E->getLength() > 10) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
323 Result += E->getString().take_front(7);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
324 Result += "...";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
325 } else {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
326 llvm::raw_string_ostream OS(Result);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
327 llvm::printEscapedString(E->getString(), OS);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
328 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
329 Result.push_back('"');
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
330 return Result;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
331 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
332
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
333 // Simple operators. Motivating cases are `!x` and `I < Length`.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
334 std::string printUnary(llvm::StringRef Spelling, const Expr *Operand,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
335 bool Prefix) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
336 std::string Sub = Visit(Operand);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
337 if (Sub.empty())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
338 return "";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
339 if (Prefix)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
340 return (Spelling + Sub).str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
341 Sub += Spelling;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
342 return Sub;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
343 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
344 bool InsideBinary = false; // No recursing into binary expressions.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
345 std::string printBinary(llvm::StringRef Spelling, const Expr *LHSOp,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
346 const Expr *RHSOp) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
347 if (InsideBinary)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
348 return "";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
349 llvm::SaveAndRestore InBinary(InsideBinary, true);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
350
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
351 std::string LHS = Visit(LHSOp);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
352 std::string RHS = Visit(RHSOp);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
353 if (LHS.empty() && RHS.empty())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
354 return "";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
355
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
356 if (LHS.empty())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
357 LHS = "...";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
358 LHS.push_back(' ');
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
359 LHS += Spelling;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
360 LHS.push_back(' ');
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
361 if (RHS.empty())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
362 LHS += "...";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
363 else
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
364 LHS += RHS;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
365 return LHS;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
366 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
367 std::string VisitUnaryOperator(const UnaryOperator *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
368 return printUnary(E->getOpcodeStr(E->getOpcode()), E->getSubExpr(),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
369 !E->isPostfix());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
370 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
371 std::string VisitBinaryOperator(const BinaryOperator *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
372 return printBinary(E->getOpcodeStr(E->getOpcode()), E->getLHS(),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
373 E->getRHS());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
374 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
375 std::string VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *E) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
376 const char *Spelling = getOperatorSpelling(E->getOperator());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
377 // Handle weird unary-that-look-like-binary postfix operators.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
378 if ((E->getOperator() == OO_PlusPlus ||
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
379 E->getOperator() == OO_MinusMinus) &&
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
380 E->getNumArgs() == 2)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
381 return printUnary(Spelling, E->getArg(0), false);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
382 if (E->isInfixBinaryOp())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
383 return printBinary(Spelling, E->getArg(0), E->getArg(1));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
384 if (E->getNumArgs() == 1) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
385 switch (E->getOperator()) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
386 case OO_Plus:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
387 case OO_Minus:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
388 case OO_Star:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
389 case OO_Amp:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
390 case OO_Tilde:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
391 case OO_Exclaim:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
392 case OO_PlusPlus:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
393 case OO_MinusMinus:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
394 return printUnary(Spelling, E->getArg(0), true);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
395 default:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
396 break;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
397 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
398 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
399 return "";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
400 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
401 };
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
402 return Namer{}.Visit(E);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
403 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
404
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
405 // Determines if any intermediate type in desugaring QualType QT is of
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
406 // substituted template parameter type. Ignore pointer or reference wrappers.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
407 bool isSugaredTemplateParameter(QualType QT) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
408 static auto PeelWrapper = [](QualType QT) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
409 // Neither `PointerType` nor `ReferenceType` is considered as sugared
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
410 // type. Peel it.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
411 QualType Peeled = QT->getPointeeType();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
412 return Peeled.isNull() ? QT : Peeled;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
413 };
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
414
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
415 // This is a bit tricky: we traverse the type structure and find whether or
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
416 // not a type in the desugaring process is of SubstTemplateTypeParmType.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
417 // During the process, we may encounter pointer or reference types that are
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
418 // not marked as sugared; therefore, the desugar function won't apply. To
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
419 // move forward the traversal, we retrieve the pointees using
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
420 // QualType::getPointeeType().
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
421 //
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
422 // However, getPointeeType could leap over our interests: The QT::getAs<T>()
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
423 // invoked would implicitly desugar the type. Consequently, if the
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
424 // SubstTemplateTypeParmType is encompassed within a TypedefType, we may lose
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
425 // the chance to visit it.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
426 // For example, given a QT that represents `std::vector<int *>::value_type`:
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
427 // `-ElaboratedType 'value_type' sugar
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
428 // `-TypedefType 'vector<int *>::value_type' sugar
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
429 // |-Typedef 'value_type'
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
430 // `-SubstTemplateTypeParmType 'int *' sugar class depth 0 index 0 T
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
431 // |-ClassTemplateSpecialization 'vector'
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
432 // `-PointerType 'int *'
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
433 // `-BuiltinType 'int'
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
434 // Applying `getPointeeType` to QT results in 'int', a child of our target
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
435 // node SubstTemplateTypeParmType.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
436 //
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
437 // As such, we always prefer the desugared over the pointee for next type
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
438 // in the iteration. It could avoid the getPointeeType's implicit desugaring.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
439 while (true) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
440 if (QT->getAs<SubstTemplateTypeParmType>())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
441 return true;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
442 QualType Desugared = QT->getLocallyUnqualifiedSingleStepDesugaredType();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
443 if (Desugared != QT)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
444 QT = Desugared;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
445 else if (auto Peeled = PeelWrapper(Desugared); Peeled != QT)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
446 QT = Peeled;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
447 else
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
448 break;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
449 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
450 return false;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
451 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
452
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
453 // A simple wrapper for `clang::desugarForDiagnostic` that provides optional
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
454 // semantic.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
455 std::optional<QualType> desugar(ASTContext &AST, QualType QT) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
456 bool ShouldAKA = false;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
457 auto Desugared = clang::desugarForDiagnostic(AST, QT, ShouldAKA);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
458 if (!ShouldAKA)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
459 return std::nullopt;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
460 return Desugared;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
461 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
462
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
463 // Apply a series of heuristic methods to determine whether or not a QualType QT
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
464 // is suitable for desugaring (e.g. getting the real name behind the using-alias
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
465 // name). If so, return the desugared type. Otherwise, return the unchanged
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
466 // parameter QT.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
467 //
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
468 // This could be refined further. See
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
469 // https://github.com/clangd/clangd/issues/1298.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
470 QualType maybeDesugar(ASTContext &AST, QualType QT) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
471 // Prefer desugared type for name that aliases the template parameters.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
472 // This can prevent things like printing opaque `: type` when accessing std
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
473 // containers.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
474 if (isSugaredTemplateParameter(QT))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
475 return desugar(AST, QT).value_or(QT);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
476
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
477 // Prefer desugared type for `decltype(expr)` specifiers.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
478 if (QT->isDecltypeType())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
479 return QT.getCanonicalType();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
480 if (const AutoType *AT = QT->getContainedAutoType())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
481 if (!AT->getDeducedType().isNull() &&
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
482 AT->getDeducedType()->isDecltypeType())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
483 return QT.getCanonicalType();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
484
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
485 return QT;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
486 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
487
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
488 class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
489 public:
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
490 InlayHintVisitor(std::vector<InlayHint> &Results, ParsedAST &AST,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
491 const Config &Cfg, std::optional<Range> RestrictRange)
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
492 : Results(Results), AST(AST.getASTContext()), Tokens(AST.getTokens()),
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
493 Cfg(Cfg), RestrictRange(std::move(RestrictRange)),
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
494 MainFileID(AST.getSourceManager().getMainFileID()),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
495 Resolver(AST.getHeuristicResolver()),
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
496 TypeHintPolicy(this->AST.getPrintingPolicy()) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
497 bool Invalid = false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
498 llvm::StringRef Buf =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
499 AST.getSourceManager().getBufferData(MainFileID, &Invalid);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
500 MainFileBuf = Invalid ? StringRef{} : Buf;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
501
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
502 TypeHintPolicy.SuppressScope = true; // keep type names short
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
503 TypeHintPolicy.AnonymousTagLocations =
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
504 false; // do not print lambda locations
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
505
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
506 // Not setting PrintCanonicalTypes for "auto" allows
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
507 // SuppressDefaultTemplateArgs (set by default) to have an effect.
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
508 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
509
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
510 bool VisitTypeLoc(TypeLoc TL) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
511 if (const auto *DT = llvm::dyn_cast<DecltypeType>(TL.getType()))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
512 if (QualType UT = DT->getUnderlyingType(); !UT->isDependentType())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
513 addTypeHint(TL.getSourceRange(), UT, ": ");
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
514 return true;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
515 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
516
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
517 bool VisitCXXConstructExpr(CXXConstructExpr *E) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
518 // Weed out constructor calls that don't look like a function call with
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
519 // an argument list, by checking the validity of getParenOrBraceRange().
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
520 // Also weed out std::initializer_list constructors as there are no names
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
521 // for the individual arguments.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
522 if (!E->getParenOrBraceRange().isValid() ||
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
523 E->isStdInitListInitialization()) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
524 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
525 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
526
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
527 processCall(E->getConstructor(), {E->getArgs(), E->getNumArgs()});
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
528 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
529 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
530
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
531 bool VisitCallExpr(CallExpr *E) {
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
532 if (!Cfg.InlayHints.Parameters)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
533 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
534
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
535 // Do not show parameter hints for operator calls written using operator
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
536 // syntax or user-defined literals. (Among other reasons, the resulting
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
537 // hints can look awkard, e.g. the expression can itself be a function
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
538 // argument and then we'd get two hints side by side).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
539 if (isa<CXXOperatorCallExpr>(E) || isa<UserDefinedLiteral>(E))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
540 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
541
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
542 auto CalleeDecls = Resolver->resolveCalleeOfCallExpr(E);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
543 if (CalleeDecls.size() != 1)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
544 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
545 const FunctionDecl *Callee = nullptr;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
546 if (const auto *FD = dyn_cast<FunctionDecl>(CalleeDecls[0]))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
547 Callee = FD;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
548 else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CalleeDecls[0]))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
549 Callee = FTD->getTemplatedDecl();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
550 if (!Callee)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
551 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
552
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
553 processCall(Callee, {E->getArgs(), E->getNumArgs()});
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
554 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
555 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
556
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
557 bool VisitFunctionDecl(FunctionDecl *D) {
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
558 if (auto *FPT =
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
559 llvm::dyn_cast<FunctionProtoType>(D->getType().getTypePtr())) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
560 if (!FPT->hasTrailingReturn()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
561 if (auto FTL = D->getFunctionTypeLoc())
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
562 addReturnTypeHint(D, FTL.getRParenLoc());
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
563 }
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
564 }
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
565 if (Cfg.InlayHints.BlockEnd && D->isThisDeclarationADefinition()) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
566 // We use `printName` here to properly print name of ctor/dtor/operator
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
567 // overload.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
568 if (const Stmt *Body = D->getBody())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
569 addBlockEndHint(Body->getSourceRange(), "", printName(AST, *D), "");
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
570 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
571 return true;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
572 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
573
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
574 bool VisitForStmt(ForStmt *S) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
575 if (Cfg.InlayHints.BlockEnd) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
576 std::string Name;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
577 // Common case: for (int I = 0; I < N; I++). Use "I" as the name.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
578 if (auto *DS = llvm::dyn_cast_or_null<DeclStmt>(S->getInit());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
579 DS && DS->isSingleDecl())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
580 Name = getSimpleName(llvm::cast<NamedDecl>(*DS->getSingleDecl()));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
581 else
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
582 Name = summarizeExpr(S->getCond());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
583 markBlockEnd(S->getBody(), "for", Name);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
584 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
585 return true;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
586 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
587
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
588 bool VisitCXXForRangeStmt(CXXForRangeStmt *S) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
589 if (Cfg.InlayHints.BlockEnd)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
590 markBlockEnd(S->getBody(), "for", getSimpleName(*S->getLoopVariable()));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
591 return true;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
592 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
593
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
594 bool VisitWhileStmt(WhileStmt *S) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
595 if (Cfg.InlayHints.BlockEnd)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
596 markBlockEnd(S->getBody(), "while", summarizeExpr(S->getCond()));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
597 return true;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
598 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
599
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
600 bool VisitSwitchStmt(SwitchStmt *S) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
601 if (Cfg.InlayHints.BlockEnd)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
602 markBlockEnd(S->getBody(), "switch", summarizeExpr(S->getCond()));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
603 return true;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
604 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
605
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
606 // If/else chains are tricky.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
607 // if (cond1) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
608 // } else if (cond2) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
609 // } // mark as "cond1" or "cond2"?
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
610 // For now, the answer is neither, just mark as "if".
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
611 // The ElseIf is a different IfStmt that doesn't know about the outer one.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
612 llvm::DenseSet<const IfStmt *> ElseIfs; // not eligible for names
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
613 bool VisitIfStmt(IfStmt *S) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
614 if (Cfg.InlayHints.BlockEnd) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
615 if (const auto *ElseIf = llvm::dyn_cast_or_null<IfStmt>(S->getElse()))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
616 ElseIfs.insert(ElseIf);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
617 // Don't use markBlockEnd: the relevant range is [then.begin, else.end].
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
618 if (const auto *EndCS = llvm::dyn_cast<CompoundStmt>(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
619 S->getElse() ? S->getElse() : S->getThen())) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
620 addBlockEndHint(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
621 {S->getThen()->getBeginLoc(), EndCS->getRBracLoc()}, "if",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
622 ElseIfs.contains(S) ? "" : summarizeExpr(S->getCond()), "");
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
623 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
624 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
625 return true;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
626 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
627
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
628 void markBlockEnd(const Stmt *Body, llvm::StringRef Label,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
629 llvm::StringRef Name = "") {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
630 if (const auto *CS = llvm::dyn_cast_or_null<CompoundStmt>(Body))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
631 addBlockEndHint(CS->getSourceRange(), Label, Name, "");
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
632 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
633
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
634 bool VisitTagDecl(TagDecl *D) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
635 if (Cfg.InlayHints.BlockEnd && D->isThisDeclarationADefinition()) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
636 std::string DeclPrefix = D->getKindName().str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
637 if (const auto *ED = dyn_cast<EnumDecl>(D)) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
638 if (ED->isScoped())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
639 DeclPrefix += ED->isScopedUsingClassTag() ? " class" : " struct";
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
640 };
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
641 addBlockEndHint(D->getBraceRange(), DeclPrefix, getSimpleName(*D), ";");
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
642 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
643 return true;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
644 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
645
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
646 bool VisitNamespaceDecl(NamespaceDecl *D) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
647 if (Cfg.InlayHints.BlockEnd) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
648 // For namespace, the range actually starts at the namespace keyword. But
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
649 // it should be fine since it's usually very short.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
650 addBlockEndHint(D->getSourceRange(), "namespace", getSimpleName(*D), "");
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
651 }
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
652 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
653 }
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
654
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
655 bool VisitLambdaExpr(LambdaExpr *E) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
656 FunctionDecl *D = E->getCallOperator();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
657 if (!E->hasExplicitResultType())
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
658 addReturnTypeHint(D, E->hasExplicitParameters()
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
659 ? D->getFunctionTypeLoc().getRParenLoc()
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
660 : E->getIntroducerRange().getEnd());
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
661 return true;
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
662 }
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
663
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
664 void addReturnTypeHint(FunctionDecl *D, SourceRange Range) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
665 auto *AT = D->getReturnType()->getContainedAutoType();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
666 if (!AT || AT->getDeducedType().isNull())
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
667 return;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
668 addTypeHint(Range, D->getReturnType(), /*Prefix=*/"-> ");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
669 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
670
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
671 bool VisitVarDecl(VarDecl *D) {
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
672 // Do not show hints for the aggregate in a structured binding,
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
673 // but show hints for the individual bindings.
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
674 if (auto *DD = dyn_cast<DecompositionDecl>(D)) {
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
675 for (auto *Binding : DD->bindings()) {
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
676 // For structured bindings, print canonical types. This is important
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
677 // because for bindings that use the tuple_element protocol, the
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
678 // non-canonical types would be "tuple_element<I, A>::type".
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
679 if (auto Type = Binding->getType(); !Type.isNull())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
680 addTypeHint(Binding->getLocation(), Type.getCanonicalType(),
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
681 /*Prefix=*/": ");
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
682 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
683 return true;
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
684 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
685
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
686 if (auto *AT = D->getType()->getContainedAutoType()) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
687 if (AT->isDeduced() && !D->getType()->isDependentType()) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
688 // Our current approach is to place the hint on the variable
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
689 // and accordingly print the full type
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
690 // (e.g. for `const auto& x = 42`, print `const int&`).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
691 // Alternatively, we could place the hint on the `auto`
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
692 // (and then just print the type deduced for the `auto`).
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
693 addTypeHint(D->getLocation(), D->getType(), /*Prefix=*/": ");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
694 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
695 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
696
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
697 // Handle templates like `int foo(auto x)` with exactly one instantiation.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
698 if (auto *PVD = llvm::dyn_cast<ParmVarDecl>(D)) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
699 if (D->getIdentifier() && PVD->getType()->isDependentType() &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
700 !getContainedAutoParamType(D->getTypeSourceInfo()->getTypeLoc())
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
701 .isNull()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
702 if (auto *IPVD = getOnlyParamInstantiation(PVD))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
703 addTypeHint(D->getLocation(), IPVD->getType(), /*Prefix=*/": ");
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
704 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
705 }
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
706
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
707 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
708 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
709
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
710 ParmVarDecl *getOnlyParamInstantiation(ParmVarDecl *D) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
711 auto *TemplateFunction = llvm::dyn_cast<FunctionDecl>(D->getDeclContext());
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
712 if (!TemplateFunction)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
713 return nullptr;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
714 auto *InstantiatedFunction = llvm::dyn_cast_or_null<FunctionDecl>(
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
715 getOnlyInstantiation(TemplateFunction));
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
716 if (!InstantiatedFunction)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
717 return nullptr;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
718
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
719 unsigned ParamIdx = 0;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
720 for (auto *Param : TemplateFunction->parameters()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
721 // Can't reason about param indexes in the presence of preceding packs.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
722 // And if this param is a pack, it may expand to multiple params.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
723 if (Param->isParameterPack())
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
724 return nullptr;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
725 if (Param == D)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
726 break;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
727 ++ParamIdx;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
728 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
729 assert(ParamIdx < TemplateFunction->getNumParams() &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
730 "Couldn't find param in list?");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
731 assert(ParamIdx < InstantiatedFunction->getNumParams() &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
732 "Instantiated function has fewer (non-pack) parameters?");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
733 return InstantiatedFunction->getParamDecl(ParamIdx);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
734 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
735
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
736 bool VisitInitListExpr(InitListExpr *Syn) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
737 // We receive the syntactic form here (shouldVisitImplicitCode() is false).
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
738 // This is the one we will ultimately attach designators to.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
739 // It may have subobject initializers inlined without braces. The *semantic*
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
740 // form of the init-list has nested init-lists for these.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
741 // getDesignators will look at the semantic form to determine the labels.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
742 assert(Syn->isSyntacticForm() && "RAV should not visit implicit code!");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
743 if (!Cfg.InlayHints.Designators)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
744 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
745 if (Syn->isIdiomaticZeroInitializer(AST.getLangOpts()))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
746 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
747 llvm::DenseMap<SourceLocation, std::string> Designators =
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
748 getDesignators(Syn);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
749 for (const Expr *Init : Syn->inits()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
750 if (llvm::isa<DesignatedInitExpr>(Init))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
751 continue;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
752 auto It = Designators.find(Init->getBeginLoc());
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
753 if (It != Designators.end() &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
754 !isPrecededByParamNameComment(Init, It->second))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
755 addDesignatorHint(Init->getSourceRange(), It->second);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
756 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
757 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
758 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
759
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
760 // FIXME: Handle RecoveryExpr to try to hint some invalid calls.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
761
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
762 private:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
763 using NameVec = SmallVector<StringRef, 8>;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
764
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
765 void processCall(const FunctionDecl *Callee,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
766 llvm::ArrayRef<const Expr *> Args) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
767 if (!Cfg.InlayHints.Parameters || Args.size() == 0 || !Callee)
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
768 return;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
769
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
770 // The parameter name of a move or copy constructor is not very interesting.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
771 if (auto *Ctor = dyn_cast<CXXConstructorDecl>(Callee))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
772 if (Ctor->isCopyOrMoveConstructor())
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
773 return;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
774
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
775 // Resolve parameter packs to their forwarded parameter
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
776 auto ForwardedParams = resolveForwardingParameters(Callee);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
777
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
778 NameVec ParameterNames = chooseParameterNames(ForwardedParams);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
779
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
780 // Exclude setters (i.e. functions with one argument whose name begins with
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
781 // "set"), and builtins like std::move/forward/... as their parameter name
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
782 // is also not likely to be interesting.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
783 if (isSetter(Callee, ParameterNames) || isSimpleBuiltin(Callee))
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
784 return;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
785
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
786 for (size_t I = 0; I < ParameterNames.size() && I < Args.size(); ++I) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
787 // Pack expansion expressions cause the 1:1 mapping between arguments and
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
788 // parameters to break down, so we don't add further inlay hints if we
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
789 // encounter one.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
790 if (isa<PackExpansionExpr>(Args[I])) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
791 break;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
792 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
793
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
794 StringRef Name = ParameterNames[I];
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
795 bool NameHint = shouldHintName(Args[I], Name);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
796 bool ReferenceHint =
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
797 shouldHintReference(Callee->getParamDecl(I), ForwardedParams[I]);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
798
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
799 if (NameHint || ReferenceHint) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
800 addInlayHint(Args[I]->getSourceRange(), HintSide::Left,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
801 InlayHintKind::Parameter, ReferenceHint ? "&" : "",
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
802 NameHint ? Name : "", ": ");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
803 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
804 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
805 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
806
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
807 static bool isSetter(const FunctionDecl *Callee, const NameVec &ParamNames) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
808 if (ParamNames.size() != 1)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
809 return false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
810
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
811 StringRef Name = getSimpleName(*Callee);
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
812 if (!Name.starts_with_insensitive("set"))
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
813 return false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
814
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
815 // In addition to checking that the function has one parameter and its
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
816 // name starts with "set", also check that the part after "set" matches
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
817 // the name of the parameter (ignoring case). The idea here is that if
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
818 // the parameter name differs, it may contain extra information that
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
819 // may be useful to show in a hint, as in:
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
820 // void setTimeout(int timeoutMillis);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
821 // This currently doesn't handle cases where params use snake_case
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
822 // and functions don't, e.g.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
823 // void setExceptionHandler(EHFunc exception_handler);
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
824 // We could improve this by replacing `equals_insensitive` with some
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
825 // `sloppy_equals` which ignores case and also skips underscores.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
826 StringRef WhatItIsSetting = Name.substr(3).ltrim("_");
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
827 return WhatItIsSetting.equals_insensitive(ParamNames[0]);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
828 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
829
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
830 // Checks if the callee is one of the builtins
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
831 // addressof, as_const, forward, move(_if_noexcept)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
832 static bool isSimpleBuiltin(const FunctionDecl *Callee) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
833 switch (Callee->getBuiltinID()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
834 case Builtin::BIaddressof:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
835 case Builtin::BIas_const:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
836 case Builtin::BIforward:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
837 case Builtin::BImove:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
838 case Builtin::BImove_if_noexcept:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
839 return true;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
840 default:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
841 return false;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
842 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
843 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
844
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
845 bool shouldHintName(const Expr *Arg, StringRef ParamName) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
846 if (ParamName.empty())
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
847 return false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
848
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
849 // If the argument expression is a single name and it matches the
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
850 // parameter name exactly, omit the name hint.
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
851 if (ParamName == getSpelledIdentifier(Arg))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
852 return false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
853
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
854 // Exclude argument expressions preceded by a /*paramName*/.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
855 if (isPrecededByParamNameComment(Arg, ParamName))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
856 return false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
857
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
858 return true;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
859 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
860
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
861 bool shouldHintReference(const ParmVarDecl *Param,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
862 const ParmVarDecl *ForwardedParam) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
863 // We add a & hint only when the argument is passed as mutable reference.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
864 // For parameters that are not part of an expanded pack, this is
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
865 // straightforward. For expanded pack parameters, it's likely that they will
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
866 // be forwarded to another function. In this situation, we only want to add
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
867 // the reference hint if the argument is actually being used via mutable
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
868 // reference. This means we need to check
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
869 // 1. whether the value category of the argument is preserved, i.e. each
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
870 // pack expansion uses std::forward correctly.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
871 // 2. whether the argument is ever copied/cast instead of passed
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
872 // by-reference
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
873 // Instead of checking this explicitly, we use the following proxy:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
874 // 1. the value category can only change from rvalue to lvalue during
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
875 // forwarding, so checking whether both the parameter of the forwarding
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
876 // function and the forwarded function are lvalue references detects such
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
877 // a conversion.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
878 // 2. if the argument is copied/cast somewhere in the chain of forwarding
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
879 // calls, it can only be passed on to an rvalue reference or const lvalue
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
880 // reference parameter. Thus if the forwarded parameter is a mutable
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
881 // lvalue reference, it cannot have been copied/cast to on the way.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
882 // Additionally, we should not add a reference hint if the forwarded
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
883 // parameter was only partially resolved, i.e. points to an expanded pack
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
884 // parameter, since we do not know how it will be used eventually.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
885 auto Type = Param->getType();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
886 auto ForwardedType = ForwardedParam->getType();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
887 return Type->isLValueReferenceType() &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
888 ForwardedType->isLValueReferenceType() &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
889 !ForwardedType.getNonReferenceType().isConstQualified() &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
890 !isExpandedFromParameterPack(ForwardedParam);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
891 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
892
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
893 // Checks if "E" is spelled in the main file and preceded by a C-style comment
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
894 // whose contents match ParamName (allowing for whitespace and an optional "="
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
895 // at the end.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
896 bool isPrecededByParamNameComment(const Expr *E, StringRef ParamName) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
897 auto &SM = AST.getSourceManager();
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
898 auto FileLoc = SM.getFileLoc(E->getBeginLoc());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
899 auto Decomposed = SM.getDecomposedLoc(FileLoc);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
900 if (Decomposed.first != MainFileID)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
901 return false;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
902
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
903 StringRef SourcePrefix = MainFileBuf.substr(0, Decomposed.second);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
904 // Allow whitespace between comment and expression.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
905 SourcePrefix = SourcePrefix.rtrim();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
906 // Check for comment ending.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
907 if (!SourcePrefix.consume_back("*/"))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
908 return false;
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
909 // Ignore some punctuation and whitespace around comment.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
910 // In particular this allows designators to match nicely.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
911 llvm::StringLiteral IgnoreChars = " =.";
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
912 SourcePrefix = SourcePrefix.rtrim(IgnoreChars);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
913 ParamName = ParamName.trim(IgnoreChars);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
914 // Other than that, the comment must contain exactly ParamName.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
915 if (!SourcePrefix.consume_back(ParamName))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
916 return false;
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
917 SourcePrefix = SourcePrefix.rtrim(IgnoreChars);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
918 return SourcePrefix.endswith("/*");
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
919 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
920
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
921 // If "E" spells a single unqualified identifier, return that name.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
922 // Otherwise, return an empty string.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
923 static StringRef getSpelledIdentifier(const Expr *E) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
924 E = E->IgnoreUnlessSpelledInSource();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
925
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
926 if (auto *DRE = dyn_cast<DeclRefExpr>(E))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
927 if (!DRE->getQualifier())
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
928 return getSimpleName(*DRE->getDecl());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
929
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
930 if (auto *ME = dyn_cast<MemberExpr>(E))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
931 if (!ME->getQualifier() && ME->isImplicitAccess())
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
932 return getSimpleName(*ME->getMemberDecl());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
933
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
934 return {};
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
935 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
936
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
937 NameVec chooseParameterNames(SmallVector<const ParmVarDecl *> Parameters) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
938 NameVec ParameterNames;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
939 for (const auto *P : Parameters) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
940 if (isExpandedFromParameterPack(P)) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
941 // If we haven't resolved a pack paramater (e.g. foo(Args... args)) to a
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
942 // non-pack parameter, then hinting as foo(args: 1, args: 2, args: 3) is
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
943 // unlikely to be useful.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
944 ParameterNames.emplace_back();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
945 } else {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
946 auto SimpleName = getSimpleName(*P);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
947 // If the parameter is unnamed in the declaration:
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
948 // attempt to get its name from the definition
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
949 if (SimpleName.empty()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
950 if (const auto *PD = getParamDefinition(P)) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
951 SimpleName = getSimpleName(*PD);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
952 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
953 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
954 ParameterNames.emplace_back(SimpleName);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
955 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
956 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
957
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
958 // Standard library functions often have parameter names that start
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
959 // with underscores, which makes the hints noisy, so strip them out.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
960 for (auto &Name : ParameterNames)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
961 stripLeadingUnderscores(Name);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
962
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
963 return ParameterNames;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
964 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
965
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
966 // for a ParmVarDecl from a function declaration, returns the corresponding
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
967 // ParmVarDecl from the definition if possible, nullptr otherwise.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
968 static const ParmVarDecl *getParamDefinition(const ParmVarDecl *P) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
969 if (auto *Callee = dyn_cast<FunctionDecl>(P->getDeclContext())) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
970 if (auto *Def = Callee->getDefinition()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
971 auto I = std::distance(Callee->param_begin(),
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
972 llvm::find(Callee->parameters(), P));
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
973 if (I < Callee->getNumParams()) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
974 return Def->getParamDecl(I);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
975 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
976 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
977 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
978 return nullptr;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
979 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
980
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
981 // We pass HintSide rather than SourceLocation because we want to ensure
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
982 // it is in the same file as the common file range.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
983 void addInlayHint(SourceRange R, HintSide Side, InlayHintKind Kind,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
984 llvm::StringRef Prefix, llvm::StringRef Label,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
985 llvm::StringRef Suffix) {
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
986 auto LSPRange = getHintRange(R);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
987 if (!LSPRange)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
988 return;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
989
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
990 addInlayHint(*LSPRange, Side, Kind, Prefix, Label, Suffix);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
991 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
992
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
993 void addInlayHint(Range LSPRange, HintSide Side, InlayHintKind Kind,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
994 llvm::StringRef Prefix, llvm::StringRef Label,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
995 llvm::StringRef Suffix) {
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
996 // We shouldn't get as far as adding a hint if the category is disabled.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
997 // We'd like to disable as much of the analysis as possible above instead.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
998 // Assert in debug mode but add a dynamic check in production.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
999 assert(Cfg.InlayHints.Enabled && "Shouldn't get here if disabled!");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1000 switch (Kind) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1001 #define CHECK_KIND(Enumerator, ConfigProperty) \
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1002 case InlayHintKind::Enumerator: \
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1003 assert(Cfg.InlayHints.ConfigProperty && \
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1004 "Shouldn't get here if kind is disabled!"); \
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1005 if (!Cfg.InlayHints.ConfigProperty) \
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1006 return; \
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1007 break
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1008 CHECK_KIND(Parameter, Parameters);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1009 CHECK_KIND(Type, DeducedTypes);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1010 CHECK_KIND(Designator, Designators);
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1011 CHECK_KIND(BlockEnd, BlockEnd);
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1012 #undef CHECK_KIND
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1013 }
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1014
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1015 Position LSPPos = Side == HintSide::Left ? LSPRange.start : LSPRange.end;
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1016 if (RestrictRange &&
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1017 (LSPPos < RestrictRange->start || !(LSPPos < RestrictRange->end)))
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1018 return;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1019 bool PadLeft = Prefix.consume_front(" ");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1020 bool PadRight = Suffix.consume_back(" ");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1021 Results.push_back(InlayHint{LSPPos, (Prefix + Label + Suffix).str(), Kind,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1022 PadLeft, PadRight, LSPRange});
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1023 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1024
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1025 // Get the range of the main file that *exactly* corresponds to R.
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1026 std::optional<Range> getHintRange(SourceRange R) {
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1027 const auto &SM = AST.getSourceManager();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1028 auto Spelled = Tokens.spelledForExpanded(Tokens.expandedTokens(R));
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1029 // TokenBuffer will return null if e.g. R corresponds to only part of a
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1030 // macro expansion.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1031 if (!Spelled || Spelled->empty())
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1032 return std::nullopt;
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1033 // Hint must be within the main file, not e.g. a non-preamble include.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1034 if (SM.getFileID(Spelled->front().location()) != SM.getMainFileID() ||
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1035 SM.getFileID(Spelled->back().location()) != SM.getMainFileID())
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1036 return std::nullopt;
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1037 return Range{sourceLocToPosition(SM, Spelled->front().location()),
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1038 sourceLocToPosition(SM, Spelled->back().endLocation())};
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1039 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1040
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
1041 void addTypeHint(SourceRange R, QualType T, llvm::StringRef Prefix) {
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1042 if (!Cfg.InlayHints.DeducedTypes || T.isNull())
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
1043 return;
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
1044
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1045 // The sugared type is more useful in some cases, and the canonical
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1046 // type in other cases.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1047 auto Desugared = maybeDesugar(AST, T);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1048 std::string TypeName = Desugared.getAsString(TypeHintPolicy);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1049 if (T != Desugared && !shouldPrintTypeHint(TypeName)) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1050 // If the desugared type is too long to display, fallback to the sugared
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1051 // type.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1052 TypeName = T.getAsString(TypeHintPolicy);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1053 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1054 if (shouldPrintTypeHint(TypeName))
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1055 addInlayHint(R, HintSide::Right, InlayHintKind::Type, Prefix, TypeName,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1056 /*Suffix=*/"");
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1057 }
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1058
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1059 void addDesignatorHint(SourceRange R, llvm::StringRef Text) {
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1060 addInlayHint(R, HintSide::Left, InlayHintKind::Designator,
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1061 /*Prefix=*/"", Text, /*Suffix=*/"=");
223
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
1062 }
5f17cb93ff66 LLVM13 (2021/7/18)
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 221
diff changeset
1063
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1064 bool shouldPrintTypeHint(llvm::StringRef TypeName) const noexcept {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1065 return Cfg.InlayHints.TypeNameLimit == 0 ||
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1066 TypeName.size() < Cfg.InlayHints.TypeNameLimit;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1067 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1068
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1069 void addBlockEndHint(SourceRange BraceRange, StringRef DeclPrefix,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1070 StringRef Name, StringRef OptionalPunctuation) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1071 auto HintRange = computeBlockEndHintRange(BraceRange, OptionalPunctuation);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1072 if (!HintRange)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1073 return;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1074
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1075 std::string Label = DeclPrefix.str();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1076 if (!Label.empty() && !Name.empty())
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1077 Label += ' ';
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1078 Label += Name;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1079
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1080 constexpr unsigned HintMaxLengthLimit = 60;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1081 if (Label.length() > HintMaxLengthLimit)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1082 return;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1083
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1084 addInlayHint(*HintRange, HintSide::Right, InlayHintKind::BlockEnd, " // ",
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1085 Label, "");
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1086 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1087
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1088 // Compute the LSP range to attach the block end hint to, if any allowed.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1089 // 1. "}" is the last non-whitespace character on the line. The range of "}"
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1090 // is returned.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1091 // 2. After "}", if the trimmed trailing text is exactly
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1092 // `OptionalPunctuation`, say ";". The range of "} ... ;" is returned.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1093 // Otherwise, the hint shouldn't be shown.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1094 std::optional<Range> computeBlockEndHintRange(SourceRange BraceRange,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1095 StringRef OptionalPunctuation) {
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1096 constexpr unsigned HintMinLineLimit = 2;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1097
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1098 auto &SM = AST.getSourceManager();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1099 auto [BlockBeginFileId, BlockBeginOffset] =
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1100 SM.getDecomposedLoc(SM.getFileLoc(BraceRange.getBegin()));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1101 auto RBraceLoc = SM.getFileLoc(BraceRange.getEnd());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1102 auto [RBraceFileId, RBraceOffset] = SM.getDecomposedLoc(RBraceLoc);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1103
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1104 // Because we need to check the block satisfies the minimum line limit, we
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1105 // require both source location to be in the main file. This prevents hint
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1106 // to be shown in weird cases like '{' is actually in a "#include", but it's
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1107 // rare anyway.
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1108 if (BlockBeginFileId != MainFileID || RBraceFileId != MainFileID)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1109 return std::nullopt;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1110
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1111 StringRef RestOfLine = MainFileBuf.substr(RBraceOffset).split('\n').first;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1112 if (!RestOfLine.starts_with("}"))
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1113 return std::nullopt;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1114
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1115 StringRef TrimmedTrailingText = RestOfLine.drop_front().trim();
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1116 if (!TrimmedTrailingText.empty() &&
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1117 TrimmedTrailingText != OptionalPunctuation)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1118 return std::nullopt;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1119
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1120 auto BlockBeginLine = SM.getLineNumber(BlockBeginFileId, BlockBeginOffset);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1121 auto RBraceLine = SM.getLineNumber(RBraceFileId, RBraceOffset);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1122
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1123 // Don't show hint on trivial blocks like `class X {};`
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1124 if (BlockBeginLine + HintMinLineLimit - 1 > RBraceLine)
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1125 return std::nullopt;
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1126
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1127 // This is what we attach the hint to, usually "}" or "};".
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1128 StringRef HintRangeText = RestOfLine.take_front(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1129 TrimmedTrailingText.empty()
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1130 ? 1
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1131 : TrimmedTrailingText.bytes_end() - RestOfLine.bytes_begin());
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1132
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1133 Position HintStart = sourceLocToPosition(SM, RBraceLoc);
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1134 Position HintEnd = sourceLocToPosition(
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1135 SM, RBraceLoc.getLocWithOffset(HintRangeText.size()));
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1136 return Range{HintStart, HintEnd};
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1137 }
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1138
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1139 std::vector<InlayHint> &Results;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1140 ASTContext &AST;
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1141 const syntax::TokenBuffer &Tokens;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1142 const Config &Cfg;
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1143 std::optional<Range> RestrictRange;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1144 FileID MainFileID;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1145 StringRef MainFileBuf;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1146 const HeuristicResolver *Resolver;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1147 PrintingPolicy TypeHintPolicy;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1148 };
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1149
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1150 } // namespace
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1151
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1152 std::vector<InlayHint> inlayHints(ParsedAST &AST,
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
1153 std::optional<Range> RestrictRange) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1154 std::vector<InlayHint> Results;
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1155 const auto &Cfg = Config::current();
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1156 if (!Cfg.InlayHints.Enabled)
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1157 return Results;
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1158 InlayHintVisitor Visitor(Results, AST, Cfg, std::move(RestrictRange));
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1159 Visitor.TraverseAST(AST.getASTContext());
236
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1160
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1161 // De-duplicate hints. Duplicates can sometimes occur due to e.g. explicit
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1162 // template instantiations.
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1163 llvm::sort(Results);
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1164 Results.erase(std::unique(Results.begin(), Results.end()), Results.end());
c4bab56944e8 LLVM 16
kono
parents: 223
diff changeset
1165
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1166 return Results;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1167 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1168
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1169 } // namespace clangd
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
diff changeset
1170 } // namespace clang