#include "clang/AST/ASTConsumer.h"
using namespace clang;
+
+namespace clang {
+
+/// \brief An instance of this interface is defined to initiate OpenMP parsing,
+/// and to help Parser during subsequent parsing of OpenMP constrcuts.
+class OpenMP {
+ // Private Member Objects.
+private:
+ // \brief The member object reference to the Preprocessor.
+ Preprocessor &PP;
+
+ // \brief Handler objects which handle different OpenMP pragma directive
+ // statements.
+ OwningPtr<PragmaHandler> ParallelHandler;
+ OwningPtr<PragmaHandler> ForHandler;
+ OwningPtr<PragmaHandler> SectionsHandler;
+ OwningPtr<PragmaHandler> SectionHandler;
+ OwningPtr<PragmaHandler> SingleHandler;
+ OwningPtr<PragmaHandler> TaskHandler;
+ OwningPtr<PragmaHandler> MasterHandler;
+ OwningPtr<PragmaHandler> CriticalHandler;
+ OwningPtr<PragmaHandler> BarrierHandler;
+ OwningPtr<PragmaHandler> TaskwaitHandler;
+ OwningPtr<PragmaHandler> TaskyieldHandler;
+ OwningPtr<PragmaHandler> AtomicHandler;
+ OwningPtr<PragmaHandler> FlushHandler;
+ OwningPtr<PragmaHandler> OrderedHandler;
+ OwningPtr<PragmaHandler> ThreadPrivateHandler;
+
+ // \brief When an OpenMP pragma is ignored, we emit a warning message
+ // saying so, but only once per translation unit irrespective of the
+ // number of OpenMP pragmas appeared in the translation unit. This flag
+ // keeps track of whether the unkown pragma warning message is emitted
+ // or not for the current translation unit.
+ bool OmpUnknownWarned;
+
+ // Private Member Methods.
+private:
+ // \brief When source contains omp pragmas, but user does not pass the
+ // '-fopenmp' flag, we emit a warning message saying so, but only once per
+ // source file.
+ void SetPragmaOmpUnknownWarned() { OmpUnknownWarned = true; }
+ void ResetPragmaOmpUnknownWarned() { OmpUnknownWarned = false; }
+ bool PragmaOmpUnknownWarned() { return OmpUnknownWarned; }
+
+ // \brief Handles "\#pragma omp ...".
+ // It Checks if the user has passed the flag, '-fopenmp', if so,
+ // it enters the *token* which is *representing* the current OpenMP
+ // pragma *directive* into the TokenStream, so that the Parser can
+ // recognizes it and can parse the respective OpenMP pragma directive
+ // statement. Otherwise, it reports a warning that the current OpenMP
+ // directive statement will be ignored. However, note that only
+ // *one* warning message per translation unit is reported
+ // irrespective of the number of OpenMP directive statments which
+ // appear in the translation unit.
+ void HandlePragma(Token &OmpTok, tok::TokenKind TKind) {
+ if (!PP.getLangOpts().OpenMP) {
+ if (!PragmaOmpUnknownWarned()) {
+ PP.Diag(OmpTok, diag::warn_pragma_omp_ignored);
+ SetPragmaOmpUnknownWarned();
+ }
+ } else {
+ Token *Toks = new Token[1];
+ Toks[0].startToken();
+ Toks[0].setKind(TKind);
+ Toks[0].setLocation(OmpTok.getLocation());
+ PP.EnterTokenStream(Toks, 1, /*DisableMacroExpansion=*/true,
+ /*OwnsTokens=*/false);
+ }
+ }
+
+ // Constructors and Destructors.
+public:
+ OpenMP(Preprocessor &pp);
+ ~OpenMP();
+
+private:
+ // \brief An OpenMP pragma handler interface. It acts as an intermediate
+ // between the Preprocessor class and the OpenMP (this) class. It by passes
+ // the omp pragma handling call to OpenMP class upon requested by the
+ // Preprocessor.
+ struct PragmaOmpHandler : public PragmaHandler {
+ friend class OpenMP;
+ tok::TokenKind TKind;
+ OpenMP *Omp;
+ PragmaOmpHandler(tok::TokenKind Kind, StringRef Name, OpenMP *omp)
+ : PragmaHandler(Name), TKind(Kind), Omp(omp) {}
+ virtual ~PragmaOmpHandler() { Omp = 0; }
+ virtual void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer,
+ Token &OmpTok) {
+ Omp->HandlePragma(OmpTok, TKind);
+ }
+ };
+};
+
+} // end of namespace clang
+
+OpenMP::OpenMP(Preprocessor &pp)
+ : PP(pp) {
+
+ // Add "#pragma omp ..." handlers. These are removed and destroyed
+ // in the destructor.
+ //
+ // Note that OpenMP pragma annotations below are listed in the same order
+ // as listed in the OpenMP 3.1 standard specification document. Please
+ // do *adhere* to the same order.
+
+ // OpenMP parallel constructs.
+ ParallelHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_parallel, "parallel", this));
+ PP.AddPragmaHandler("omp", ParallelHandler.get());
+
+ // OpenMP work sharing constructs.
+ ForHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_for, "for", this));
+ PP.AddPragmaHandler("omp", ForHandler.get());
+
+ SectionsHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_sections, "sections", this));
+ PP.AddPragmaHandler("omp", SectionsHandler.get());
+
+ SingleHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_single, "single", this));
+ PP.AddPragmaHandler("omp", SingleHandler.get());
+
+ SectionHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_section, "section", this));
+ PP.AddPragmaHandler("omp", SectionHandler.get());
+
+ // OpenMP combined parallel work sharing constructs.
+ // FIXME: not supported yet.
+
+ // OpenMP tasking constructs.
+ TaskHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_task, "task", this));
+ PP.AddPragmaHandler("omp", TaskHandler.get());
+
+ TaskyieldHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_taskyield, "taskyield", this));
+ PP.AddPragmaHandler("omp", TaskyieldHandler.get());
+
+ // OpenMP master and synchronization constructs.
+ MasterHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_master, "master", this));
+ PP.AddPragmaHandler("omp", MasterHandler.get());
+
+ CriticalHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_critical, "critical", this));
+ PP.AddPragmaHandler("omp", CriticalHandler.get());
+
+ BarrierHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_barrier, "barrier", this));
+ PP.AddPragmaHandler("omp", BarrierHandler.get());
+
+ TaskwaitHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_taskwait, "taskwait", this));
+ PP.AddPragmaHandler("omp", TaskwaitHandler.get());
+
+ AtomicHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_atomic, "atomic", this));
+ PP.AddPragmaHandler("omp", AtomicHandler.get());
+
+ FlushHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_flush, "flush", this));
+ PP.AddPragmaHandler("omp", FlushHandler.get());
+
+ OrderedHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_ordered, "ordered", this));
+ PP.AddPragmaHandler("omp", OrderedHandler.get());
+
+ // OpenMP data environment related constructs.
+ ThreadPrivateHandler.reset(new PragmaOmpHandler(
+ tok::annot_pragma_omp_threadprivate, "threadprivate", this));
+ PP.AddPragmaHandler("omp", ThreadPrivateHandler.get());
+
+ // We have not yet reported the unknown OpenMP pragma *warning* message
+ // as we have not yet started the processing of translation unit.
+ ResetPragmaOmpUnknownWarned();
+}
+
+OpenMP::~OpenMP() {
+ // Remove the "#pragma omp ..." handlers we installed.
+ //
+ // Note that OpenMP pragma annotations below are listed in the same order
+ // as listed in the OpenMP 3.1 standard specification document. Please
+ // do *adhere* to the same order.
+
+ // OpenMP parallel constructs.
+ PP.RemovePragmaHandler("omp", ParallelHandler.get());
+ ParallelHandler.reset();
+
+ // OpenMP work sharing constructs.
+ PP.RemovePragmaHandler("omp", ForHandler.get());
+ ForHandler.reset();
+ PP.RemovePragmaHandler("omp", SectionsHandler.get());
+ SectionsHandler.reset();
+ PP.RemovePragmaHandler("omp", SingleHandler.get());
+ SingleHandler.reset();
+ PP.RemovePragmaHandler("omp", SectionHandler.get());
+ SectionHandler.reset();
+
+ // OpenMP combined parallel work sharing constructs.
+ // FIXME: Yet to support.
+
+ // OpenMP tasking constructs.
+ PP.RemovePragmaHandler("omp", TaskHandler.get());
+ TaskHandler.reset();
+ PP.RemovePragmaHandler("omp", TaskyieldHandler.get());
+ TaskyieldHandler.reset();
+
+ // OpenMP master and synchronization constructs.
+ PP.RemovePragmaHandler("omp", MasterHandler.get());
+ MasterHandler.reset();
+ PP.RemovePragmaHandler("omp", CriticalHandler.get());
+ CriticalHandler.reset();
+ PP.RemovePragmaHandler("omp", BarrierHandler.get());
+ BarrierHandler.reset();
+ PP.RemovePragmaHandler("omp", TaskwaitHandler.get());
+ TaskwaitHandler.reset();
+ PP.RemovePragmaHandler("omp", AtomicHandler.get());
+ AtomicHandler.reset();
+ PP.RemovePragmaHandler("omp", FlushHandler.get());
+ FlushHandler.reset();
+ PP.RemovePragmaHandler("omp", OrderedHandler.get());
+ OrderedHandler.reset();
+
+ // OpenMP data environment related constructs.
+ PP.RemovePragmaHandler("omp", ThreadPrivateHandler.get());
+ ThreadPrivateHandler.reset();
+}
+
namespace {
/// \brief A comment handler that passes comments found by the preprocessor
/// to the parser action.
PP.addCommentHandler(CommentSemaHandler.get());
PP.setCodeCompletionHandler(*this);
+
+ OpenMPHandler.reset(new OpenMP(pp));
}
/// If a crash happens while the parser is active, print out a line indicating
PP.clearCodeCompletionHandler();
+ OpenMPHandler.reset();
+
assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");
}