Index: lib/Frontend/PrintPreprocessedOutput.cpp =================================================================== --- lib/Frontend/PrintPreprocessedOutput.cpp +++ lib/Frontend/PrintPreprocessedOutput.cpp @@ -562,8 +562,13 @@ const char *Prefix; PrintPPOutputPPCallbacks *Callbacks; - UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks) - : Prefix(prefix), Callbacks(callbacks) {} + // Set to true if tokens should be expanded + unsigned ShouldExpandTokens : 1; + + UnknownPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks, + bool RequireTokenExpansion) + : Prefix(prefix), Callbacks(callbacks), + ShouldExpandTokens(RequireTokenExpansion) {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &PragmaTok) override { // Figure out what line we went to and insert the appropriate number of @@ -571,16 +576,24 @@ Callbacks->startNewLineIfNeeded(); Callbacks->MoveToLine(PragmaTok.getLocation()); Callbacks->OS.write(Prefix, strlen(Prefix)); + + Token PrevToken; + Token PrevPrevToken; + PrevToken.startToken(); + PrevPrevToken.startToken(); + // Read and print all of the pragma tokens. while (PragmaTok.isNot(tok::eod)) { - if (PragmaTok.hasLeadingSpace()) + if (PragmaTok.hasLeadingSpace() || + Callbacks->AvoidConcat(PrevPrevToken, PrevToken, PragmaTok)) Callbacks->OS << ' '; std::string TokSpell = PP.getSpelling(PragmaTok); Callbacks->OS.write(&TokSpell[0], TokSpell.size()); - // Expand macros in pragmas with -fms-extensions. The assumption is that - // the majority of pragmas in such a file will be Microsoft pragmas. - if (PP.getLangOpts().MicrosoftExt) + PrevPrevToken = PrevToken; + PrevToken = PragmaTok; + + if (ShouldExpandTokens) PP.Lex(PragmaTok); else PP.LexUnexpandedToken(PragmaTok); @@ -718,10 +731,29 @@ PrintPPOutputPPCallbacks *Callbacks = new PrintPPOutputPPCallbacks( PP, *OS, !Opts.ShowLineMarkers, Opts.ShowMacros, Opts.UseLineDirectives); - PP.AddPragmaHandler(new UnknownPragmaHandler("#pragma", Callbacks)); - PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks)); - PP.AddPragmaHandler("clang", - new UnknownPragmaHandler("#pragma clang", Callbacks)); + + // Expand macros in pragmas with -fms-extensions. The assumption is that + // the majority of pragmas in such a file will be Microsoft pragmas. + PP.AddPragmaHandler(new UnknownPragmaHandler( + "#pragma", Callbacks, + /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); + PP.AddPragmaHandler( + "GCC", new UnknownPragmaHandler( + "#pragma GCC", Callbacks, + /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); + PP.AddPragmaHandler( + "clang", new UnknownPragmaHandler( + "#pragma clang", Callbacks, + /*RequireTokenExpansion=*/PP.getLangOpts().MicrosoftExt)); + + // The tokens after pragma omp need to be expanded. + // + // OpenMP [2.1, Directive format] + // Preprocessing tokens following the #pragma omp are subject to macro + // replacement. + PP.AddPragmaHandler("omp", + new UnknownPragmaHandler("#pragma omp", Callbacks, + /*RequireTokenExpansion=*/true)); PP.addPPCallbacks(std::unique_ptr(Callbacks)); Index: test/Preprocessor/openmp-macro-expansion.c =================================================================== --- /dev/null +++ test/Preprocessor/openmp-macro-expansion.c @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -fopenmp -E -o - %s 2>&1 | FileCheck %s + +// This is to make sure the pragma name is not expanded! +#define omp (0xDEADBEEF) + +#define N 2 +#define M 1 +#define E N> + +#define map_to_be_expanded(x) map(tofrom:x) +#define sched_to_be_expanded(x,s) schedule(x,s) +#define reda_to_be_expanded(x) reduction(+:x) +#define redb_to_be_expanded(x,op) reduction(op:x) + +void foo(int *a, int *b) { + //CHECK: omp target map(a[0:2]) map(tofrom:b[0:2*1]) + #pragma omp target map(a[0:N]) map_to_be_expanded(b[0:2*M]) + { + int reda; + int redb; + //CHECK: omp parallel for schedule(static,2> >1) reduction(+:reda) reduction(*:redb) + #pragma omp parallel for sched_to_be_expanded(static, E>1) \ + reda_to_be_expanded(reda) redb_to_be_expanded(redb,*) + for (int i = 0; i < N; ++i) { + reda += a[i]; + redb += b[i]; + } + a[0] = reda; + b[0] = redb; + } +}