diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp --- a/clang-tools-extra/clangd/ParsedAST.cpp +++ b/clang-tools-extra/clangd/ParsedAST.cpp @@ -134,8 +134,9 @@ ReplayPreamble(const IncludeStructure &Includes, PPCallbacks *Delegate, const SourceManager &SM, Preprocessor &PP, const LangOptions &LangOpts) - : Includes(Includes), Delegate(Delegate), SM(SM), PP(PP), - LangOpts(LangOpts) {} + : Includes(Includes), Delegate(Delegate), SM(SM), PP(PP) { + MainFileTokens = syntax::tokenize(SM.getMainFileID(), SM, LangOpts); + } // In a normal compile, the preamble traverses the following structure: // @@ -167,29 +168,50 @@ if (auto FE = SM.getFileManager().getFile(Inc.Resolved)) File = *FE; + // Re-lex the #include directive to find its interesting parts. + auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset) + .getRawEncoding(); + auto HashTok = + llvm::find_if(MainFileTokens, [&HashLoc](const syntax::Token &T) { + return T.location().getRawEncoding() == HashLoc; + }); + assert(HashTok != MainFileTokens.end() && HashTok->kind() == tok::hash); + + auto IncTok = std::next(HashTok); + assert(IncTok != MainFileTokens.end()); + + auto FileTok = std::next(IncTok); + assert(FileTok != MainFileTokens.end()); + + // We imitate the PP logic here, except clang::Token::Flags, none of the + // callers seem to care about it (yet). + Token IncludeTok; + IncludeTok.startToken(); + IncludeTok.setLocation(IncTok->location()); + IncludeTok.setLength(IncTok->length()); + IncludeTok.setKind(tok::raw_identifier); + IncludeTok.setRawIdentifierData(IncTok->text(SM).data()); + PP.LookUpIdentifierInfo(IncludeTok); + + // Again we imitate PP logic here, except clang::Token::Flags. + Token FilenameTok; + FilenameTok.startToken(); + FilenameTok.setLocation(FileTok->location()); + // Note that we can't make use of FileTok->length/text in here as in the + // case of angled includes this will contain tok::less instead of + // filename. Whereas Inc.Written contains the full header name including + // quotes/angles. + FilenameTok.setLength(Inc.Written.length()); + FilenameTok.setKind(tok::header_name); + FilenameTok.setLiteralData(Inc.Written.data()); + llvm::StringRef WrittenFilename = llvm::StringRef(Inc.Written).drop_front().drop_back(); - bool Angled = llvm::StringRef(Inc.Written).startswith("<"); - - // Re-lex the #include directive to find its interesting parts. - llvm::StringRef Src = SM.getBufferData(SM.getMainFileID()); - Lexer RawLexer(SM.getLocForStartOfFile(SM.getMainFileID()), LangOpts, - Src.begin(), Src.begin() + Inc.HashOffset, Src.end()); - Token HashTok, IncludeTok, FilenameTok; - RawLexer.LexFromRawLexer(HashTok); - assert(HashTok.getKind() == tok::hash); - RawLexer.setParsingPreprocessorDirective(true); - RawLexer.LexFromRawLexer(IncludeTok); - IdentifierInfo *II = PP.getIdentifierInfo(IncludeTok.getRawIdentifier()); - IncludeTok.setIdentifierInfo(II); - IncludeTok.setKind(II->getTokenID()); - RawLexer.LexIncludeFilename(FilenameTok); - - Delegate->InclusionDirective( - HashTok.getLocation(), IncludeTok, WrittenFilename, Angled, - CharSourceRange::getCharRange(FilenameTok.getLocation(), - FilenameTok.getEndLoc()), - File, "SearchPath", "RelPath", /*Imported=*/nullptr, Inc.FileKind); + Delegate->InclusionDirective(HashTok->location(), IncludeTok, + WrittenFilename, Inc.Written.front() == '<', + FileTok->range(SM).toCharRange(SM), File, + "SearchPath", "RelPath", + /*Imported=*/nullptr, Inc.FileKind); if (File) // FIXME: Use correctly named FileEntryRef. Delegate->FileSkipped(FileEntryRef(File->getName(), *File), FilenameTok, @@ -205,7 +227,7 @@ PPCallbacks *Delegate; const SourceManager &SM; Preprocessor &PP; - const LangOptions &LangOpts; + std::vector MainFileTokens; }; } // namespace