compnerd created this revision. compnerd added reviewers: dgoldman, rsmith, aaron.ballman. Herald added subscribers: usaxena95, kadircet, kbarton, nemanjai. compnerd requested review of this revision. Herald added a subscriber: ilya-biryukov. Herald added a project: clang.
Allow a preprocessor observer to be notified of mark pragmas. Although this does not impact code generation in any way, it is useful for other clients, such as clangd, to be able to identify any marked regions. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D105368 Files: clang/include/clang/Lex/PPCallbacks.h clang/include/clang/Lex/Preprocessor.h clang/lib/Lex/Pragma.cpp clang/unittests/Lex/PPCallbacksTest.cpp
Index: clang/unittests/Lex/PPCallbacksTest.cpp =================================================================== --- clang/unittests/Lex/PPCallbacksTest.cpp +++ clang/unittests/Lex/PPCallbacksTest.cpp @@ -112,6 +112,20 @@ unsigned State; }; +class PragmaMarkCallbacks : public PPCallbacks { +public: + struct Mark { + SourceLocation Location; + StringRef Trivia; + }; + + std::vector<Mark> Marks; + + void PragmaMark(SourceLocation Loc, StringRef Trivia) override { + Marks.emplace_back(Mark{Loc, Trivia}); + } +}; + // PPCallbacks test fixture. class PPCallbacksTest : public ::testing::Test { protected: @@ -256,6 +270,36 @@ return Callbacks->Results; } + std::vector<PragmaMarkCallbacks::Mark> + PragmaMarkCall(const char *SourceText) { + std::unique_ptr<llvm::MemoryBuffer> SourceBuf = + llvm::MemoryBuffer::getMemBuffer(SourceText, "test.c"); + SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf))); + + HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr, + Diags, LangOpts, Target.get()); + TrivialModuleLoader ModLoader; + + Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts, + SourceMgr, HeaderInfo, ModLoader, /*IILookup=*/nullptr, + /*OwnsHeaderSearch=*/false); + PP.Initialize(*Target); + + auto *Callbacks = new PragmaMarkCallbacks; + PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks)); + + // Lex source text. + PP.EnterMainSourceFile(); + while (true) { + Token Tok; + PP.Lex(Tok); + if (Tok.is(tok::eof)) + break; + } + + return Callbacks->Marks; + } + PragmaOpenCLExtensionCallbacks::CallbackParameters PragmaOpenCLExtensionCall(const char *SourceText) { LangOptions OpenCLLangOpts; @@ -424,6 +468,24 @@ ASSERT_EQ(ExpectedState, Parameters.State); } +TEST_F(PPCallbacksTest, CollectMarks) { + const char *Source = + "#pragma mark\n" + "#pragma mark\r\n" + "#pragma mark - trivia\n" + "#pragma mark - trivia\r\n"; + + auto Marks = PragmaMarkCall(Source); + + ASSERT_EQ(4u, Marks.size()); + ASSERT_TRUE(Marks[0].Trivia.empty()); + ASSERT_TRUE(Marks[1].Trivia.empty()); + ASSERT_FALSE(Marks[2].Trivia.empty()); + ASSERT_FALSE(Marks[3].Trivia.empty()); + ASSERT_EQ(" - trivia", Marks[2].Trivia); + ASSERT_EQ(" - trivia", Marks[3].Trivia); +} + TEST_F(PPCallbacksTest, DirectiveExprRanges) { const auto &Results1 = DirectiveExprRange("#if FLUZZY_FLOOF\n#endif\n"); EXPECT_EQ(Results1.size(), 1U); Index: clang/lib/Lex/Pragma.cpp =================================================================== --- clang/lib/Lex/Pragma.cpp +++ clang/lib/Lex/Pragma.cpp @@ -412,9 +412,13 @@ HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry()); } -void Preprocessor::HandlePragmaMark() { +void Preprocessor::HandlePragmaMark(Token &MarkTok) { assert(CurPPLexer && "No current lexer?"); - CurLexer->ReadToEndOfLine(); + + SmallString<64> Buffer; + CurLexer->ReadToEndOfLine(&Buffer); + if (Callbacks) + Callbacks->PragmaMark(MarkTok.getLocation(), Buffer); } /// HandlePragmaPoison - Handle \#pragma GCC poison. PoisonTok is the 'poison'. @@ -992,7 +996,7 @@ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &MarkTok) override { - PP.HandlePragmaMark(); + PP.HandlePragmaMark(MarkTok); } }; Index: clang/include/clang/Lex/Preprocessor.h =================================================================== --- clang/include/clang/Lex/Preprocessor.h +++ clang/include/clang/Lex/Preprocessor.h @@ -2365,7 +2365,7 @@ public: void HandlePragmaOnce(Token &OnceTok); - void HandlePragmaMark(); + void HandlePragmaMark(Token &MarkTok); void HandlePragmaPoison(); void HandlePragmaSystemHeader(Token &SysHeaderTok); void HandlePragmaDependency(Token &DependencyTok); Index: clang/include/clang/Lex/PPCallbacks.h =================================================================== --- clang/include/clang/Lex/PPCallbacks.h +++ clang/include/clang/Lex/PPCallbacks.h @@ -191,6 +191,10 @@ StringRef Str) { } + /// Callback invoked when a \#pragma mark comment is read. + virtual void PragmaMark(SourceLocation Loc, StringRef Trivia) { + } + /// Callback invoked when a \#pragma detect_mismatch directive is /// read. virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits