Index: lib/Frontend/PrintPreprocessedOutput.cpp =================================================================== --- lib/Frontend/PrintPreprocessedOutput.cpp +++ lib/Frontend/PrintPreprocessedOutput.cpp @@ -588,6 +588,37 @@ Callbacks->setEmittedDirectiveOnThisLine(); } }; +struct OMPPragmaHandler : public PragmaHandler { + const char *Prefix; + PrintPPOutputPPCallbacks *Callbacks; + + OMPPragmaHandler(const char *prefix, PrintPPOutputPPCallbacks *callbacks) + : Prefix(prefix), Callbacks(callbacks) {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &PragmaTok) override { + + // 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. + + // Figure out what line we went to and insert the appropriate number of + // newline characters. + Callbacks->startNewLineIfNeeded(); + Callbacks->MoveToLine(PragmaTok.getLocation()); + Callbacks->OS.write(Prefix, strlen(Prefix)); + // Read and print all of the pragma tokens. + while (PragmaTok.isNot(tok::eod)) { + if (PragmaTok.hasLeadingSpace()) + Callbacks->OS << ' '; + std::string TokSpell = PP.getSpelling(PragmaTok); + Callbacks->OS.write(&TokSpell[0], TokSpell.size()); + PP.Lex(PragmaTok); + } + Callbacks->setEmittedDirectiveOnThisLine(); + } +}; } // end anonymous namespace @@ -722,6 +753,7 @@ PP.AddPragmaHandler("GCC", new UnknownPragmaHandler("#pragma GCC",Callbacks)); PP.AddPragmaHandler("clang", new UnknownPragmaHandler("#pragma clang", Callbacks)); + PP.AddPragmaHandler("omp", new OMPPragmaHandler("#pragma omp", Callbacks)); PP.addPPCallbacks(std::unique_ptr(Callbacks)); Index: test/OpenMP/preprocessor.c =================================================================== --- /dev/null +++ test/OpenMP/preprocessor.c @@ -0,0 +1,30 @@ +// RUN: %clang -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 map_to_be_expanded(x) map(tofrom:x) +#define sched_to_be_expanded(x) schedule(x,N) +#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) reduction(+:reda) reduction(*:redb) + #pragma omp parallel for sched_to_be_expanded(static) \ + 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; + } +}