Meinersbur updated this revision to Diff 227561. Meinersbur added a comment.
- Implement -f(no-)experimental-transform-pragma Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D69088/new/ https://reviews.llvm.org/D69088 Files: clang/include/clang/Basic/LangOptions.def clang/include/clang/Basic/TokenKinds.def clang/include/clang/Driver/Options.td clang/include/clang/Parse/Parser.h clang/lib/Frontend/CompilerInvocation.cpp clang/lib/Parse/ParsePragma.cpp clang/test/Parser/pragma-no-transform.cpp
Index: clang/test/Parser/pragma-no-transform.cpp =================================================================== --- /dev/null +++ clang/test/Parser/pragma-no-transform.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -std=c++11 -fno-experimental-transform-pragma -Wall -verify %s + +void pragma_transform(int *List, int Length) { +/* expected-warning@+1 {{unknown pragma ignored}} */ +#pragma clang transform unroll partial(4) + for (int i = 0; i < Length; i+=1) + List[i] = i; +} + Index: clang/lib/Parse/ParsePragma.cpp =================================================================== --- clang/lib/Parse/ParsePragma.cpp +++ clang/lib/Parse/ParsePragma.cpp @@ -247,6 +247,12 @@ void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, Token &FirstToken) override; +struct PragmaTransformHandler : public PragmaHandler { + PragmaTransformHandler() : PragmaHandler("transform") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer, + Token &FirstToken) override; +}; + private: Sema &Actions; }; @@ -382,6 +388,11 @@ AttributePragmaHandler = std::make_unique<PragmaAttributeHandler>(AttrFactory); PP.AddPragmaHandler("clang", AttributePragmaHandler.get()); + + if (getLangOpts().ExperimentalTransformPragma) { + TransformHandler = std::make_unique<PragmaTransformHandler>(); + PP.AddPragmaHandler("clang", TransformHandler.get()); + } } void Parser::resetPragmaHandlers() { @@ -487,6 +498,11 @@ PP.RemovePragmaHandler("clang", AttributePragmaHandler.get()); AttributePragmaHandler.reset(); + + if (getLangOpts().ExperimentalTransformPragma) { + PP.RemovePragmaHandler("clang", TransformHandler.get()); + TransformHandler.reset(); + } } /// Handle the annotation token produced for #pragma unused(...) @@ -3008,6 +3024,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" | <trans> [clauses..] eod ... + // + // Token stream after : + // "transform" <trans> [clauses..] eod | ... + // After pushing the annotation tokens: + // + // | annot_pragma_transform <trans> [clauses..] annot_pragma_transform_end ... + // + // The symbol | is before the next token returned by PP.Lex() + SmallVector<Token, 16> 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<Token[]>(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: Index: clang/lib/Frontend/CompilerInvocation.cpp =================================================================== --- clang/lib/Frontend/CompilerInvocation.cpp +++ clang/lib/Frontend/CompilerInvocation.cpp @@ -3227,6 +3227,11 @@ Opts.CompleteMemberPointers = Args.hasArg(OPT_fcomplete_member_pointers); Opts.BuildingPCHWithObjectFile = Args.hasArg(OPT_building_pch_with_obj); + + // Enable or disable support for #pragma clang transform. + Opts.ExperimentalTransformPragma = + Args.hasFlag(options::OPT_fexperimental_transform_pragma, + options::OPT_fno_experimental_transform_pragma, false); } static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { Index: clang/include/clang/Parse/Parser.h =================================================================== --- clang/include/clang/Parse/Parser.h +++ clang/include/clang/Parse/Parser.h @@ -200,6 +200,7 @@ std::unique_ptr<PragmaHandler> STDCCXLIMITHandler; std::unique_ptr<PragmaHandler> STDCUnknownHandler; std::unique_ptr<PragmaHandler> AttributePragmaHandler; + std::unique_ptr<PragmaHandler> TransformHandler; std::unique_ptr<CommentHandler> CommentSemaHandler; Index: clang/include/clang/Driver/Options.td =================================================================== --- clang/include/clang/Driver/Options.td +++ clang/include/clang/Driver/Options.td @@ -1661,6 +1661,10 @@ Flags<[NoArgumentUnused, HelpHidden]>; def static_openmp: Flag<["-"], "static-openmp">, HelpText<"Use the static host OpenMP runtime while linking.">; +def fexperimental_transform_pragma : Flag<["-"], "fexperimental-transform-pragma">, Group<f_Group>, + Flags<[CC1Option, HelpHidden]>, HelpText<"Parse experimental #pragma clang transform directives.">; +def fno_experimental_transform_pragma : Flag<["-"], "fno-experimental-transform-pragma">, Group<f_Group>, + Flags<[CC1Option, HelpHidden]>; def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>; def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>; def fno_escaping_block_tail_calls : Flag<["-"], "fno-escaping-block-tail-calls">, Group<f_Group>, Flags<[CC1Option]>; Index: clang/include/clang/Basic/TokenKinds.def =================================================================== --- clang/include/clang/Basic/TokenKinds.def +++ 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. Index: clang/include/clang/Basic/LangOptions.def =================================================================== --- clang/include/clang/Basic/LangOptions.def +++ clang/include/clang/Basic/LangOptions.def @@ -230,6 +230,8 @@ LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP") +LANGOPT(ExperimentalTransformPragma, 1, 0, "Enable #pragma clang transform") + LANGOPT(SizedDeallocation , 1, 0, "sized deallocation") LANGOPT(AlignedAllocation , 1, 0, "aligned allocation") LANGOPT(AlignedAllocationUnavailable, 1, 0, "aligned allocation functions are unavailable")
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits