23
23
#include " clang/Basic/Builtins.h"
24
24
#include " clang/Basic/OperatorKinds.h"
25
25
#include " clang/Basic/SourceManager.h"
26
+ #include " clang/Tooling/DesignatedInitializers.h"
26
27
#include " llvm/ADT/DenseSet.h"
27
- #include " llvm/ADT/ScopeExit.h"
28
28
#include " llvm/ADT/StringExtras.h"
29
29
#include " llvm/ADT/StringRef.h"
30
30
#include " llvm/ADT/Twine.h"
@@ -42,169 +42,6 @@ namespace {
42
42
// For now, inlay hints are always anchored at the left or right of their range.
43
43
enum class HintSide { Left, Right };
44
44
45
- // Helper class to iterate over the designator names of an aggregate type.
46
- //
47
- // For an array type, yields [0], [1], [2]...
48
- // For aggregate classes, yields null for each base, then .field1, .field2, ...
49
- class AggregateDesignatorNames {
50
- public:
51
- AggregateDesignatorNames (QualType T) {
52
- if (!T.isNull ()) {
53
- T = T.getCanonicalType ();
54
- if (T->isArrayType ()) {
55
- IsArray = true ;
56
- Valid = true ;
57
- return ;
58
- }
59
- if (const RecordDecl *RD = T->getAsRecordDecl ()) {
60
- Valid = true ;
61
- FieldsIt = RD->field_begin ();
62
- FieldsEnd = RD->field_end ();
63
- if (const auto *CRD = llvm::dyn_cast<CXXRecordDecl>(RD)) {
64
- BasesIt = CRD->bases_begin ();
65
- BasesEnd = CRD->bases_end ();
66
- Valid = CRD->isAggregate ();
67
- }
68
- OneField = Valid && BasesIt == BasesEnd && FieldsIt != FieldsEnd &&
69
- std::next (FieldsIt) == FieldsEnd;
70
- }
71
- }
72
- }
73
- // Returns false if the type was not an aggregate.
74
- operator bool () { return Valid; }
75
- // Advance to the next element in the aggregate.
76
- void next () {
77
- if (IsArray)
78
- ++Index;
79
- else if (BasesIt != BasesEnd)
80
- ++BasesIt;
81
- else if (FieldsIt != FieldsEnd)
82
- ++FieldsIt;
83
- }
84
- // Print the designator to Out.
85
- // Returns false if we could not produce a designator for this element.
86
- bool append (std::string &Out, bool ForSubobject) {
87
- if (IsArray) {
88
- Out.push_back (' [' );
89
- Out.append (std::to_string (Index));
90
- Out.push_back (' ]' );
91
- return true ;
92
- }
93
- if (BasesIt != BasesEnd)
94
- return false ; // Bases can't be designated. Should we make one up?
95
- if (FieldsIt != FieldsEnd) {
96
- llvm::StringRef FieldName;
97
- if (const IdentifierInfo *II = FieldsIt->getIdentifier ())
98
- FieldName = II->getName ();
99
-
100
- // For certain objects, their subobjects may be named directly.
101
- if (ForSubobject &&
102
- (FieldsIt->isAnonymousStructOrUnion () ||
103
- // std::array<int,3> x = {1,2,3}. Designators not strictly valid!
104
- (OneField && isReservedName (FieldName))))
105
- return true ;
106
-
107
- if (!FieldName.empty () && !isReservedName (FieldName)) {
108
- Out.push_back (' .' );
109
- Out.append (FieldName.begin (), FieldName.end ());
110
- return true ;
111
- }
112
- return false ;
113
- }
114
- return false ;
115
- }
116
-
117
- private:
118
- bool Valid = false ;
119
- bool IsArray = false ;
120
- bool OneField = false ; // e.g. std::array { T __elements[N]; }
121
- unsigned Index = 0 ;
122
- CXXRecordDecl::base_class_const_iterator BasesIt;
123
- CXXRecordDecl::base_class_const_iterator BasesEnd;
124
- RecordDecl::field_iterator FieldsIt;
125
- RecordDecl::field_iterator FieldsEnd;
126
- };
127
-
128
- // Collect designator labels describing the elements of an init list.
129
- //
130
- // This function contributes the designators of some (sub)object, which is
131
- // represented by the semantic InitListExpr Sem.
132
- // This includes any nested subobjects, but *only* if they are part of the same
133
- // original syntactic init list (due to brace elision).
134
- // In other words, it may descend into subobjects but not written init-lists.
135
- //
136
- // For example: struct Outer { Inner a,b; }; struct Inner { int x, y; }
137
- // Outer o{{1, 2}, 3};
138
- // This function will be called with Sem = { {1, 2}, {3, ImplicitValue} }
139
- // It should generate designators '.a:' and '.b.x:'.
140
- // '.a:' is produced directly without recursing into the written sublist.
141
- // (The written sublist will have a separate collectDesignators() call later).
142
- // Recursion with Prefix='.b' and Sem = {3, ImplicitValue} produces '.b.x:'.
143
- void collectDesignators (const InitListExpr *Sem,
144
- llvm::DenseMap<SourceLocation, std::string> &Out,
145
- const llvm::DenseSet<SourceLocation> &NestedBraces,
146
- std::string &Prefix) {
147
- if (!Sem || Sem->isTransparent ())
148
- return ;
149
- assert (Sem->isSemanticForm ());
150
-
151
- // The elements of the semantic form all correspond to direct subobjects of
152
- // the aggregate type. `Fields` iterates over these subobject names.
153
- AggregateDesignatorNames Fields (Sem->getType ());
154
- if (!Fields)
155
- return ;
156
- for (const Expr *Init : Sem->inits ()) {
157
- auto Next = llvm::make_scope_exit ([&, Size (Prefix.size ())] {
158
- Fields.next (); // Always advance to the next subobject name.
159
- Prefix.resize (Size); // Erase any designator we appended.
160
- });
161
- // Skip for a broken initializer or if it is a "hole" in a subobject that
162
- // was not explicitly initialized.
163
- if (!Init || llvm::isa<ImplicitValueInitExpr>(Init))
164
- continue ;
165
-
166
- const auto *BraceElidedSubobject = llvm::dyn_cast<InitListExpr>(Init);
167
- if (BraceElidedSubobject &&
168
- NestedBraces.contains (BraceElidedSubobject->getLBraceLoc ()))
169
- BraceElidedSubobject = nullptr ; // there were braces!
170
-
171
- if (!Fields.append (Prefix, BraceElidedSubobject != nullptr ))
172
- continue ; // no designator available for this subobject
173
- if (BraceElidedSubobject) {
174
- // If the braces were elided, this aggregate subobject is initialized
175
- // inline in the same syntactic list.
176
- // Descend into the semantic list describing the subobject.
177
- // (NestedBraces are still correct, they're from the same syntactic list).
178
- collectDesignators (BraceElidedSubobject, Out, NestedBraces, Prefix);
179
- continue ;
180
- }
181
- Out.try_emplace (Init->getBeginLoc (), Prefix);
182
- }
183
- }
184
-
185
- // Get designators describing the elements of a (syntactic) init list.
186
- // This does not produce designators for any explicitly-written nested lists.
187
- llvm::DenseMap<SourceLocation, std::string>
188
- getDesignators (const InitListExpr *Syn) {
189
- assert (Syn->isSyntacticForm ());
190
-
191
- // collectDesignators needs to know which InitListExprs in the semantic tree
192
- // were actually written, but InitListExpr::isExplicit() lies.
193
- // Instead, record where braces of sub-init-lists occur in the syntactic form.
194
- llvm::DenseSet<SourceLocation> NestedBraces;
195
- for (const Expr *Init : Syn->inits ())
196
- if (auto *Nested = llvm::dyn_cast<InitListExpr>(Init))
197
- NestedBraces.insert (Nested->getLBraceLoc ());
198
-
199
- // Traverse the semantic form to find the designators.
200
- // We use their SourceLocation to correlate with the syntactic form later.
201
- llvm::DenseMap<SourceLocation, std::string> Designators;
202
- std::string EmptyPrefix;
203
- collectDesignators (Syn->isSemanticForm () ? Syn : Syn->getSemanticForm (),
204
- Designators, NestedBraces, EmptyPrefix);
205
- return Designators;
206
- }
207
-
208
45
void stripLeadingUnderscores (StringRef &Name) { Name = Name.ltrim (' _' ); }
209
46
210
47
// getDeclForType() returns the decl responsible for Type's spelling.
@@ -854,7 +691,7 @@ class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
854
691
if (Syn->isIdiomaticZeroInitializer (AST.getLangOpts ()))
855
692
return true ;
856
693
llvm::DenseMap<SourceLocation, std::string> Designators =
857
- getDesignators (Syn);
694
+ clang::tooling:: getDesignators (Syn);
858
695
for (const Expr *Init : Syn->inits ()) {
859
696
if (llvm::isa<DesignatedInitExpr>(Init))
860
697
continue ;
0 commit comments