@@ -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,78 @@ 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,
123- const ASTContext &Context) {
124- SourceRange Range = Field.getSourceRange ();
170+ const ASTContext &Context,
171+ const bool WithTrailingComments) {
172+ const SourceRange Range = Field.getSourceRange ();
173+ SourceLocation Begin = Range.getBegin ();
125174 SourceLocation End = Range.getEnd ();
126175 const SourceManager &SM = Context.getSourceManager ();
127176 const LangOptions &LangOpts = Context.getLangOpts ();
128177 while (true ) {
129178 std::optional<Token> CurrentToken = Lexer::findNextToken (End, SM, LangOpts);
130179
131- if (!CurrentToken || CurrentToken-> is (tok::semi) )
132- break ;
180+ if (!CurrentToken)
181+ return SourceRange (Begin, End) ;
133182
134183 if (CurrentToken->is (tok::eof))
135184 return Range; // Something is wrong, return the original range.
185+
136186 End = CurrentToken->getLastLoc ();
187+
188+ if (CurrentToken->is (tok::semi))
189+ break ;
137190 }
138- return SourceRange (Range.getBegin (), End);
191+ End = getEndOfTrailingComment (End, SM, LangOpts);
192+ return SourceRange (Begin, End);
139193}
140194
141195// / Reorders fields in the definition of a struct/class.
0 commit comments