Feature:
OpenMP support. Sub-Feature: Support for "#pragma omp ..." registration with Preprocessor. Files Changed/Added: * include/clang/Basic/DiagnosticGroups.td (C) * include/clang/Basic/DiagnosticParseKinds.td (C) * include/clang/Basic/TokenKinds.def (C) * include/clang/Parse/Parser.h (C) * lib/Parse/Parser.cpp (C) Test Cases Changed/Added: * test/Preprocessor/pragma_omp.c (A) * test/Preprocessor/pragma_omp_ignored_warning.c (A) llvm-svn: 166869
This commit is contained in:
parent
6a682be48b
commit
5d61097dd9
|
@ -251,6 +251,7 @@ def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
|
|||
def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
|
||||
def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes]>;
|
||||
def UnknownPragmas : DiagGroup<"unknown-pragmas">;
|
||||
def OpenMPPragmas : DiagGroup<"openmp-pragmas">;
|
||||
def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
|
||||
def UnknownAttributes : DiagGroup<"attributes">;
|
||||
def IgnoredAttributes : DiagGroup<"ignored-attributes">;
|
||||
|
|
|
@ -734,6 +734,11 @@ def err_pragma_fp_contract_scope : Error<
|
|||
"'#pragma fp_contract' should only appear at file scope or at the start of a "
|
||||
"compound expression">;
|
||||
|
||||
// OpenMP
|
||||
def warn_pragma_omp_ignored : Warning<
|
||||
"pragma omp ignored; did you forget to add '-fopenmp' flag?">,
|
||||
InGroup<OpenMPPragmas>;
|
||||
|
||||
// OpenCL Section 6.8.g
|
||||
def err_not_opencl_storage_class_specifier : Error<
|
||||
"OpenCL does not support the '%0' storage class specifier">;
|
||||
|
|
|
@ -637,6 +637,42 @@ ANNOTATION(pragma_fp_contract)
|
|||
// handles them.
|
||||
ANNOTATION(pragma_opencl_extension)
|
||||
|
||||
// Annotations for OpenMP pragma directive statements - "\#pragam omp ..."
|
||||
// The lexer produces these so that they only take effect when the parser
|
||||
// handles them.
|
||||
//
|
||||
// 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.
|
||||
ANNOTATION(pragma_omp_parallel)
|
||||
|
||||
// OpenMP work sharing constructs.
|
||||
ANNOTATION(pragma_omp_for)
|
||||
ANNOTATION(pragma_omp_sections)
|
||||
ANNOTATION(pragma_omp_single)
|
||||
ANNOTATION(pragma_omp_section)
|
||||
|
||||
// OpenMP combined parallel work sharing constructs.
|
||||
// TODO
|
||||
|
||||
// OpenMP tasking constructs.
|
||||
ANNOTATION(pragma_omp_task)
|
||||
ANNOTATION(pragma_omp_taskyield)
|
||||
|
||||
// OpenMP master and synchronization constructs.
|
||||
ANNOTATION(pragma_omp_master)
|
||||
ANNOTATION(pragma_omp_critical)
|
||||
ANNOTATION(pragma_omp_barrier)
|
||||
ANNOTATION(pragma_omp_taskwait)
|
||||
ANNOTATION(pragma_omp_atomic)
|
||||
ANNOTATION(pragma_omp_flush)
|
||||
ANNOTATION(pragma_omp_ordered)
|
||||
|
||||
// OpenMP data environment related constructs.
|
||||
ANNOTATION(pragma_omp_threadprivate)
|
||||
|
||||
#undef ANNOTATION
|
||||
#undef TESTING_KEYWORD
|
||||
#undef OBJC2_AT_KEYWORD
|
||||
|
|
|
@ -43,6 +43,7 @@ namespace clang {
|
|||
class InMessageExpressionRAIIObject;
|
||||
class PoisonSEHIdentifiersRAIIObject;
|
||||
class VersionTuple;
|
||||
class OpenMP;
|
||||
|
||||
/// PrettyStackTraceParserEntry - If a crash happens while the parser is active,
|
||||
/// an entry is printed for it.
|
||||
|
@ -180,6 +181,8 @@ class Parser : public CodeCompletionHandler {
|
|||
OwningPtr<PragmaHandler> OpenCLExtensionHandler;
|
||||
OwningPtr<CommentHandler> CommentSemaHandler;
|
||||
|
||||
OwningPtr<OpenMP> OpenMPHandler;
|
||||
|
||||
/// Whether the '>' token acts as an operator or not. This will be
|
||||
/// true except when we are parsing an expression within a C++
|
||||
/// template argument list, where the '>' closes the template
|
||||
|
|
|
@ -23,6 +23,237 @@
|
|||
#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.
|
||||
|
@ -98,6 +329,8 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies)
|
|||
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
|
||||
|
@ -456,6 +689,8 @@ Parser::~Parser() {
|
|||
|
||||
PP.clearCodeCompletionHandler();
|
||||
|
||||
OpenMPHandler.reset();
|
||||
|
||||
assert(TemplateIds.empty() && "Still alive TemplateIdAnnotations around?");
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// RUN: %clang_cc1 -E -verify %s
|
||||
// RUN: %clang_cc1 -E -verify -fopenmp %s
|
||||
// RUN: %clang_cc1 -Eonly -verify %s
|
||||
// RUN: %clang_cc1 -Eonly -verify -fopenmp %s
|
||||
// RUN: %clang_cc1 -E -P -verify %s
|
||||
// RUN: %clang_cc1 -E -P -verify -fopenmp %s
|
||||
|
||||
int pragma_omp_test() {
|
||||
int i, VarA;
|
||||
#pragma omp parallel // expected-no-diagnostics
|
||||
{
|
||||
#pragma omp for // expected-no-diagnostics
|
||||
for(i=0; i<10; i++) {
|
||||
VarA = 29;
|
||||
}
|
||||
}
|
||||
return VarA;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
|
||||
int pragma_omp_ignored_warning_test() {
|
||||
int i, VarA;
|
||||
#pragma omp parallel // expected-warning {{pragma omp ignored; did you forget to add '-fopenmp' flag?}}
|
||||
{
|
||||
#pragma omp for
|
||||
for(i=0; i<10; i++) {
|
||||
VarA = 29;
|
||||
}
|
||||
}
|
||||
return VarA;
|
||||
}
|
Loading…
Reference in New Issue