@@ -63,7 +63,9 @@ getNewFieldsOrder(const RecordDecl *Definition,
6363 NameToIndex[Field->getName ()] = Field->getFieldIndex ();
6464
6565 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 " ;
6769 return {};
6870 }
6971 SmallVector<unsigned , 4 > NewFieldsOrder;
@@ -116,26 +118,77 @@ findMembersUsedInInitExpr(const CXXCtorInitializer *Initializer,
116118 return Results;
117119}
118120
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.
122169static SourceRange getFullFieldSourceRange (const FieldDecl &Field,
123170 const ASTContext &Context) {
124- SourceRange Range = Field.getSourceRange ();
171+ const SourceRange Range = Field.getSourceRange ();
172+ SourceLocation Begin = Range.getBegin ();
125173 SourceLocation End = Range.getEnd ();
126174 const SourceManager &SM = Context.getSourceManager ();
127175 const LangOptions &LangOpts = Context.getLangOpts ();
128176 while (true ) {
129177 std::optional<Token> CurrentToken = Lexer::findNextToken (End, SM, LangOpts);
130178
131- if (!CurrentToken || CurrentToken-> is (tok::semi) )
132- break ;
179+ if (!CurrentToken)
180+ return SourceRange (Begin, End) ;
133181
134182 if (CurrentToken->is (tok::eof))
135183 return Range; // Something is wrong, return the original range.
184+
136185 End = CurrentToken->getLastLoc ();
186+
187+ if (CurrentToken->is (tok::semi))
188+ break ;
137189 }
138- return SourceRange (Range.getBegin (), End);
190+ End = getEndOfTrailingComment (End, SM, LangOpts);
191+ return SourceRange (Begin, End);
139192}
140193
141194// / Reorders fields in the definition of a struct/class.
0 commit comments