diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def --- a/clang/include/clang/Basic/TokenKinds.def +++ b/clang/include/clang/Basic/TokenKinds.def @@ -830,6 +830,11 @@ PRAGMA_ANNOTATION(pragma_openmp) PRAGMA_ANNOTATION(pragma_openmp_end) +// Annotations for code transformation pragmas +// #pragma clang transform ... +PRAGMA_ANNOTATION(pragma_transform) +PRAGMA_ANNOTATION(pragma_transform_end) + // Annotations for loop pragma directives #pragma clang loop ... // The lexer produces these so that they only take effect when the parser // handles #pragma loop ... directives. diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -195,6 +195,7 @@ std::unique_ptr NoUnrollHintHandler; std::unique_ptr UnrollAndJamHintHandler; std::unique_ptr NoUnrollAndJamHintHandler; + std::unique_ptr TransformHandler; std::unique_ptr FPHandler; std::unique_ptr STDCFENVHandler; std::unique_ptr STDCCXLIMITHandler; diff --git a/clang/lib/Parse/ParsePragma.cpp b/clang/lib/Parse/ParsePragma.cpp --- a/clang/lib/Parse/ParsePragma.cpp +++ b/clang/lib/Parse/ParsePragma.cpp @@ -225,6 +225,12 @@ Token &FirstToken) override; }; +struct PragmaTransformHandler : public PragmaHandler { + PragmaTransformHandler() : PragmaHandler("transform") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, + Token &FirstToken) override; +}; + struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler { PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {} }; @@ -376,6 +382,9 @@ std::make_unique("nounroll_and_jam"); PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get()); + TransformHandler = std::make_unique(); + PP.AddPragmaHandler("clang", TransformHandler.get()); + FPHandler = std::make_unique(); PP.AddPragmaHandler("clang", FPHandler.get()); @@ -482,6 +491,9 @@ PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get()); NoUnrollAndJamHintHandler.reset(); + PP.RemovePragmaHandler("clang", TransformHandler.get()); + TransformHandler.reset(); + PP.RemovePragmaHandler("clang", FPHandler.get()); FPHandler.reset(); @@ -3008,6 +3020,71 @@ /*DisableMacroExpansion=*/false, /*IsReinject=*/false); } +/// Handle +/// #pragma clang transform ... +void PragmaTransformHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducer Introducer, + Token &FirstTok) { + // "clang" token is not passed + // "transform" is FirstTok + // Everything up until tok::eod (or tok::eof) is wrapped between + // tok::annot_pragma_transform and tok::annot_pragma_transform_end, and + // pushed-back into the token stream. The tok::eod/eof is consumed as well: + // + // Token stream before: + // FirstTok:"transform" | [clauses..] eod ... + // + // Token stream after : + // "transform" [clauses..] eod | ... + // After pushing the annotation tokens: + // + // | annot_pragma_transform [clauses..] annot_pragma_transform_end ... + // + // The symbol | is before the next token returned by PP.Lex() + SmallVector PragmaToks; + + Token StartTok; + StartTok.startToken(); + StartTok.setKind(tok::annot_pragma_transform); + StartTok.setLocation(FirstTok.getLocation()); + PragmaToks.push_back(StartTok); + + SourceLocation EodLoc = FirstTok.getLocation(); + while (true) { + Token Tok; + PP.Lex(Tok); + + // TODO: Handle nested pragmas as in r325369. + assert(!Tok.isAnnotation()); + assert(Tok.isNot(tok::annot_pragma_transform)); + assert(Tok.isNot(tok::annot_pragma_transform_end)); + assert(Tok.isNot(tok::annot_pragma_openmp)); + assert(Tok.isNot(tok::annot_pragma_openmp_end)); + assert(Tok.isNot(tok::annot_pragma_loop_hint)); + + if (Tok.is(tok::eod) || Tok.is(tok::eof)) { + EodLoc = Tok.getLocation(); + break; + } + + PragmaToks.push_back(Tok); + } + + Token EndTok; + EndTok.startToken(); + EndTok.setKind(tok::annot_pragma_transform_end); + EndTok.setLocation(EodLoc); + PragmaToks.push_back(EndTok); + + // Copy tokens for the preprocessor to own and free. + auto Toks = std::make_unique(PragmaToks.size()); + std::copy(PragmaToks.begin(), PragmaToks.end(), Toks.get()); + + // Handle in parser + PP.EnterTokenStream(std::move(Toks), PragmaToks.size(), + /*DisableMacroExpansion=*/false, /*IsReinject=*/false); +} + /// Handle the Microsoft \#pragma intrinsic extension. /// /// The syntax is: