@@ -63,7 +63,9 @@ getNewFieldsOrder(const RecordDecl *Definition,
63
63
NameToIndex[Field->getName ()] = Field->getFieldIndex ();
64
64
65
65
if (DesiredFieldsOrder.size () != NameToIndex.size ()) {
66
- llvm::errs () << " Number of provided fields doesn't match definition.\n " ;
66
+ llvm::errs () << " Number of provided fields (" << DesiredFieldsOrder.size ()
67
+ << " ) doesn't match definition (" << NameToIndex.size ()
68
+ << " ).\n " ;
67
69
return {};
68
70
}
69
71
SmallVector<unsigned , 4 > NewFieldsOrder;
@@ -116,26 +118,77 @@ findMembersUsedInInitExpr(const CXXCtorInitializer *Initializer,
116
118
return Results;
117
119
}
118
120
119
- // / Returns the full source range for the field declaration up to (not
120
- // / including) the trailing semicolumn, including potential macro invocations,
121
- // / e.g. `int a GUARDED_BY(mu);`.
121
+ // / Returns the next token after `Loc` (including comment tokens).
122
+ static std::optional<Token> getTokenAfter (SourceLocation Loc,
123
+ const SourceManager &SM,
124
+ const LangOptions &LangOpts) {
125
+ if (Loc.isMacroID ()) {
126
+ return std::nullopt;
127
+ }
128
+ Loc = Lexer::getLocForEndOfToken (Loc, 0 , SM, LangOpts);
129
+
130
+ // Break down the source location.
131
+ std::pair<FileID, unsigned > LocInfo = SM.getDecomposedLoc (Loc);
132
+
133
+ // Try to load the file buffer.
134
+ bool InvalidTemp = false ;
135
+ StringRef File = SM.getBufferData (LocInfo.first , &InvalidTemp);
136
+ if (InvalidTemp)
137
+ return std::nullopt;
138
+
139
+ const char *TokenBegin = File.data () + LocInfo.second ;
140
+
141
+ Lexer lexer (SM.getLocForStartOfFile (LocInfo.first ), LangOpts, File.begin (),
142
+ TokenBegin, File.end ());
143
+ lexer.SetCommentRetentionState (true );
144
+ // Find the token.
145
+ Token Tok;
146
+ lexer.LexFromRawLexer (Tok);
147
+ return Tok;
148
+ }
149
+
150
+ // / Returns the end of the trailing comments after `Loc`.
151
+ static SourceLocation getEndOfTrailingComment (SourceLocation Loc,
152
+ const SourceManager &SM,
153
+ const LangOptions &LangOpts) {
154
+ // We consider any following comment token that is indented more than the
155
+ // first comment to be part of the trailing comment.
156
+ const unsigned Column = SM.getPresumedColumnNumber (Loc);
157
+ std::optional<Token> Tok = getTokenAfter (Loc, SM, LangOpts);
158
+ while (Tok && Tok->is (tok::comment) &&
159
+ SM.getPresumedColumnNumber (Tok->getLocation ()) > Column) {
160
+ Loc = Tok->getEndLoc ();
161
+ Tok = getTokenAfter (Loc, SM, LangOpts);
162
+ }
163
+ return Loc;
164
+ }
165
+
166
+ // / Returns the full source range for the field declaration up to (including)
167
+ // / the trailing semicolumn, including potential macro invocations,
168
+ // / e.g. `int a GUARDED_BY(mu);`. If there is a trailing comment, include it.
122
169
static SourceRange getFullFieldSourceRange (const FieldDecl &Field,
123
170
const ASTContext &Context) {
124
- SourceRange Range = Field.getSourceRange ();
171
+ const SourceRange Range = Field.getSourceRange ();
172
+ SourceLocation Begin = Range.getBegin ();
125
173
SourceLocation End = Range.getEnd ();
126
174
const SourceManager &SM = Context.getSourceManager ();
127
175
const LangOptions &LangOpts = Context.getLangOpts ();
128
176
while (true ) {
129
177
std::optional<Token> CurrentToken = Lexer::findNextToken (End, SM, LangOpts);
130
178
131
- if (!CurrentToken || CurrentToken-> is (tok::semi) )
132
- break ;
179
+ if (!CurrentToken)
180
+ return SourceRange (Begin, End) ;
133
181
134
182
if (CurrentToken->is (tok::eof))
135
183
return Range; // Something is wrong, return the original range.
184
+
136
185
End = CurrentToken->getLastLoc ();
186
+
187
+ if (CurrentToken->is (tok::semi))
188
+ break ;
137
189
}
138
- return SourceRange (Range.getBegin (), End);
190
+ End = getEndOfTrailingComment (End, SM, LangOpts);
191
+ return SourceRange (Begin, End);
139
192
}
140
193
141
194
// / Reorders fields in the definition of a struct/class.
0 commit comments