1818#include " clang/Basic/SourceLocation.h"
1919#include " clang/Basic/SourceManager.h"
2020#include " clang/Basic/Stack.h"
21+ #include " clang/Basic/TokenKinds.h"
2122#include " clang/Frontend/ASTUnit.h"
2223#include " clang/Frontend/CompilerInstance.h"
2324#include " clang/Frontend/FrontendDiagnostic.h"
@@ -105,9 +106,34 @@ class DeserializedDeclsLineRangePrinter : public ASTConsumer,
105106 return Column < other.Column ;
106107 }
107108
108- static Position GetSpelling (const SourceManager &SM,
109- const SourceLocation &SL) {
110- return {SM.getSpellingLineNumber (SL), SM.getSpellingColumnNumber (SL)};
109+ static Position GetBeginSpelling (const SourceManager &SM,
110+ const CharSourceRange &R) {
111+ SourceLocation Begin = R.getBegin ();
112+ return {SM.getSpellingLineNumber (Begin),
113+ SM.getSpellingColumnNumber (Begin)};
114+ }
115+
116+ static Position GetEndSpelling (const SourceManager &SM,
117+ const CharSourceRange &R,
118+ const LangOptions &LangOpts) {
119+ SourceLocation End = R.getEnd ();
120+ if (R.isTokenRange ()) {
121+ // Compute end location for end character of the range.
122+ // The returned location is exclusive.
123+ End = Lexer::getLocForEndOfToken (End, 0 , SM, LangOpts);
124+ } else {
125+ // If end already points at the last character in the range, advance one
126+ // location, so that end location is exclusive.
127+ End = End.getLocWithOffset (1 );
128+ }
129+ // Relex the token past the end location of the last token in the source
130+ // range. If it's a semicolon, advance the location by one token.
131+ Token PossiblySemi;
132+ Lexer::getRawToken (End, PossiblySemi, SM, LangOpts, true );
133+ if (PossiblySemi.is (tok::semi))
134+ End = Lexer::getLocForEndOfToken (PossiblySemi.getLocation (), 0 , SM,
135+ LangOpts);
136+ return {SM.getSpellingLineNumber (End), SM.getSpellingColumnNumber (End)};
111137 }
112138 };
113139
@@ -130,21 +156,18 @@ class DeserializedDeclsLineRangePrinter : public ASTConsumer,
130156 if (!R.isValid ())
131157 continue ;
132158
133- SourceLocation End = R.getEnd ();
134- if (R.isTokenRange ())
135- End = Lexer::getLocForEndOfToken (End, 0 , SM, D->getLangOpts ());
136-
137159 auto *F = SM.getFileEntryForID (SM.getFileID (R.getBegin ()));
138- if (F != SM.getFileEntryForID (SM.getFileID (End ))) {
160+ if (F != SM.getFileEntryForID (SM.getFileID (R. getEnd () ))) {
139161 // Such cases are rare and difficult to handle.
140162 continue ;
141163 }
142164
143165 auto &Data = FileToLines[F];
144166 if (!Data.Ref )
145167 Data.Ref = SM.getFileEntryRefForID (SM.getFileID (R.getBegin ()));
146- Data.FromTo .push_back ({Position::GetSpelling (SM, R.getBegin ()),
147- Position::GetSpelling (SM, End)});
168+ Data.FromTo .push_back (
169+ {Position::GetBeginSpelling (SM, R),
170+ Position::GetEndSpelling (SM, R, D->getLangOpts ())});
148171 }
149172
150173 // To simplify output, merge consecutive and intersecting ranges.
0 commit comments