summaryrefslogtreecommitdiff
path: root/clang/lib/Parse/ParseOpenMP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Parse/ParseOpenMP.cpp')
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp429
1 files changed, 292 insertions, 137 deletions
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 91fe10e667db..1095919baa7d 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -12,6 +12,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/StmtOpenMP.h"
+#include "clang/Basic/OpenMPKinds.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Parse/RAIIObjectsForParser.h"
@@ -20,6 +21,7 @@
#include "llvm/ADT/UniqueVector.h"
using namespace clang;
+using namespace llvm::omp;
//===----------------------------------------------------------------------===//
// OpenMP declarative directives.
@@ -27,7 +29,7 @@ using namespace clang;
namespace {
enum OpenMPDirectiveKindEx {
- OMPD_cancellation = OMPD_unknown + 1,
+ OMPD_cancellation = unsigned(OMPD_unknown) + 1,
OMPD_data,
OMPD_declare,
OMPD_end,
@@ -44,7 +46,20 @@ enum OpenMPDirectiveKindEx {
OMPD_target_teams_distribute_parallel,
OMPD_mapper,
OMPD_variant,
- OMPD_parallel_master,
+};
+
+// Helper to unify the enum class OpenMPDirectiveKind with its extension
+// the OpenMPDirectiveKindEx enum which allows to use them together as if they
+// are unsigned values.
+struct OpenMPDirectiveKindExWrapper {
+ OpenMPDirectiveKindExWrapper(unsigned Value) : Value(Value) {}
+ OpenMPDirectiveKindExWrapper(OpenMPDirectiveKind DK) : Value(unsigned(DK)) {}
+ bool operator==(OpenMPDirectiveKind V) const { return Value == unsigned(V); }
+ bool operator!=(OpenMPDirectiveKind V) const { return Value != unsigned(V); }
+ bool operator<(OpenMPDirectiveKind V) const { return Value < unsigned(V); }
+ operator unsigned() const { return Value; }
+ operator OpenMPDirectiveKind() const { return OpenMPDirectiveKind(Value); }
+ unsigned Value;
};
class DeclDirectiveListParserHelper final {
@@ -68,11 +83,11 @@ public:
// Map token string to extended OMP token kind that are
// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
static unsigned getOpenMPDirectiveKindEx(StringRef S) {
- auto DKind = getOpenMPDirectiveKind(S);
+ OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
if (DKind != OMPD_unknown)
return DKind;
- return llvm::StringSwitch<unsigned>(S)
+ return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
.Case("cancellation", OMPD_cancellation)
.Case("data", OMPD_data)
.Case("declare", OMPD_declare)
@@ -87,11 +102,11 @@ static unsigned getOpenMPDirectiveKindEx(StringRef S) {
.Default(OMPD_unknown);
}
-static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
+static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
// Array of foldings: F[i][0] F[i][1] ===> F[i][2].
// E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd
// TODO: add other combined directives in topological order.
- static const unsigned F[][3] = {
+ static const OpenMPDirectiveKindExWrapper F[][3] = {
{OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
{OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
{OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
@@ -140,10 +155,12 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
{OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
{OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
{OMPD_parallel, OMPD_master, OMPD_parallel_master},
- {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop}};
+ {OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
+ {OMPD_parallel_master_taskloop, OMPD_simd,
+ OMPD_parallel_master_taskloop_simd}};
enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
Token Tok = P.getCurToken();
- unsigned DKind =
+ OpenMPDirectiveKindExWrapper DKind =
Tok.isAnnotation()
? static_cast<unsigned>(OMPD_unknown)
: getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
@@ -155,7 +172,7 @@ static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) {
continue;
Tok = P.getPreprocessor().LookAhead(0);
- unsigned SDKind =
+ OpenMPDirectiveKindExWrapper SDKind =
Tok.isAnnotation()
? static_cast<unsigned>(OMPD_unknown)
: getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
@@ -237,8 +254,9 @@ Parser::DeclGroupPtrTy
Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
- if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPDirectiveName(OMPD_declare_reduction))) {
+ if (T.expectAndConsume(
+ diag::err_expected_lparen_after,
+ getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
return DeclGroupPtrTy();
}
@@ -325,9 +343,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
Scope::OpenMPDirectiveScope);
// Parse <combiner> expression.
Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
- ExprResult CombinerResult =
- Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
- D->getLocation(), /*DiscardedValue*/ false);
+ ExprResult CombinerResult = Actions.ActOnFinishFullExpr(
+ ParseExpression().get(), D->getLocation(), /*DiscardedValue*/ false);
Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
@@ -366,14 +383,8 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
// Check if initializer is omp_priv <init_expr> or something else.
if (Tok.is(tok::identifier) &&
Tok.getIdentifierInfo()->isStr("omp_priv")) {
- if (Actions.getLangOpts().CPlusPlus) {
- InitializerResult = Actions.ActOnFinishFullExpr(
- ParseAssignmentExpression().get(), D->getLocation(),
- /*DiscardedValue*/ false);
- } else {
- ConsumeToken();
- ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
- }
+ ConsumeToken();
+ ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
} else {
InitializerResult = Actions.ActOnFinishFullExpr(
ParseAssignmentExpression().get(), D->getLocation(),
@@ -417,7 +428,8 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
return;
}
- ExprResult Init(ParseInitializer());
+ PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
+ ExprResult Init = ParseInitializer();
if (Init.isInvalid()) {
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
@@ -495,7 +507,7 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
// Parse '('
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPDirectiveName(OMPD_declare_mapper))) {
+ getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
return DeclGroupPtrTy();
}
@@ -722,10 +734,12 @@ static bool parseDeclareSimdClauses(
CKind == OMPC_linear) {
Parser::OpenMPVarListDataTy Data;
SmallVectorImpl<Expr *> *Vars = &Uniforms;
- if (CKind == OMPC_aligned)
+ if (CKind == OMPC_aligned) {
Vars = &Aligneds;
- else if (CKind == OMPC_linear)
+ } else if (CKind == OMPC_linear) {
+ Data.ExtraModifier = OMPC_LINEAR_val;
Vars = &Linears;
+ }
P.ConsumeToken();
if (P.ParseOpenMPVarList(OMPD_declare_simd,
@@ -734,11 +748,15 @@ static bool parseDeclareSimdClauses(
if (CKind == OMPC_aligned) {
Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
} else if (CKind == OMPC_linear) {
- if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
- Data.DepLinMapLoc))
- Data.LinKind = OMPC_LINEAR_val;
+ assert(0 <= Data.ExtraModifier &&
+ Data.ExtraModifier <= OMPC_LINEAR_unknown &&
+ "Unexpected linear modifier.");
+ if (P.getActions().CheckOpenMPLinearModifier(
+ static_cast<OpenMPLinearClauseKind>(Data.ExtraModifier),
+ Data.DepLinMapLastLoc))
+ Data.ExtraModifier = OMPC_LINEAR_val;
LinModifiers.append(Linears.size() - LinModifiers.size(),
- Data.LinKind);
+ Data.ExtraModifier);
Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
}
} else
@@ -795,16 +813,11 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
/// Parse optional 'score' '(' <expr> ')' ':'.
static ExprResult parseContextScore(Parser &P) {
ExprResult ScoreExpr;
- SmallString<16> Buffer;
+ Sema::OMPCtxStringType Buffer;
StringRef SelectorName =
P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
- OMPDeclareVariantAttr::ScoreType ScoreKind =
- OMPDeclareVariantAttr::ScoreUnknown;
- (void)OMPDeclareVariantAttr::ConvertStrToScoreType(SelectorName, ScoreKind);
- if (ScoreKind == OMPDeclareVariantAttr::ScoreUnknown)
+ if (!SelectorName.equals("score"))
return ScoreExpr;
- assert(ScoreKind == OMPDeclareVariantAttr::ScoreSpecified &&
- "Expected \"score\" clause.");
(void)P.ConsumeToken();
SourceLocation RLoc;
ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
@@ -820,11 +833,10 @@ static ExprResult parseContextScore(Parser &P) {
/// Parse context selector for 'implementation' selector set:
/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
/// ')'
-static void parseImplementationSelector(
- Parser &P, SourceLocation Loc, llvm::StringMap<SourceLocation> &UsedCtx,
- llvm::function_ref<void(SourceRange,
- const Sema::OpenMPDeclareVariantCtsSelectorData &)>
- Callback) {
+static void
+parseImplementationSelector(Parser &P, SourceLocation Loc,
+ llvm::StringMap<SourceLocation> &UsedCtx,
+ SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
const Token &Tok = P.getCurToken();
// Parse inner context selector set name, if any.
if (!Tok.is(tok::identifier)) {
@@ -836,7 +848,7 @@ static void parseImplementationSelector(
;
return;
}
- SmallString<16> Buffer;
+ Sema::OMPCtxStringType Buffer;
StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
if (!Res.second) {
@@ -847,19 +859,16 @@ static void parseImplementationSelector(
P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
<< CtxSelectorName;
}
- OMPDeclareVariantAttr::CtxSelectorType CSKind =
- OMPDeclareVariantAttr::CtxUnknown;
- (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorType(CtxSelectorName,
- CSKind);
+ OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
(void)P.ConsumeToken();
switch (CSKind) {
- case OMPDeclareVariantAttr::CtxVendor: {
+ case OMP_CTX_vendor: {
// Parse '('.
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
(void)T.expectAndConsume(diag::err_expected_lparen_after,
CtxSelectorName.data());
- const ExprResult Score = parseContextScore(P);
- llvm::UniqueVector<llvm::SmallString<16>> Vendors;
+ ExprResult Score = parseContextScore(P);
+ llvm::UniqueVector<Sema::OMPCtxStringType> Vendors;
do {
// Parse <vendor>.
StringRef VendorName;
@@ -882,18 +891,12 @@ static void parseImplementationSelector(
} while (Tok.is(tok::identifier));
// Parse ')'.
(void)T.consumeClose();
- if (!Vendors.empty()) {
- SmallVector<StringRef, 4> ImplVendors(Vendors.size());
- llvm::copy(Vendors, ImplVendors.begin());
- Sema::OpenMPDeclareVariantCtsSelectorData Data(
- OMPDeclareVariantAttr::CtxSetImplementation, CSKind,
- llvm::makeMutableArrayRef(ImplVendors.begin(), ImplVendors.size()),
- Score);
- Callback(SourceRange(Loc, Tok.getLocation()), Data);
- }
+ if (!Vendors.empty())
+ Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors);
break;
}
- case OMPDeclareVariantAttr::CtxUnknown:
+ case OMP_CTX_kind:
+ case OMP_CTX_unknown:
P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
<< "implementation";
// Skip until either '}', ')', or end of directive.
@@ -904,15 +907,97 @@ static void parseImplementationSelector(
}
}
+/// Parse context selector for 'device' selector set:
+/// 'kind' '(' <kind> { ',' <kind> } ')'
+static void
+parseDeviceSelector(Parser &P, SourceLocation Loc,
+ llvm::StringMap<SourceLocation> &UsedCtx,
+ SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
+ const Token &Tok = P.getCurToken();
+ // Parse inner context selector set name, if any.
+ if (!Tok.is(tok::identifier)) {
+ P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
+ << "device";
+ // Skip until either '}', ')', or end of directive.
+ while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ return;
+ }
+ Sema::OMPCtxStringType Buffer;
+ StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
+ auto Res = UsedCtx.try_emplace(CtxSelectorName, Tok.getLocation());
+ if (!Res.second) {
+ // OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
+ // Each trait-selector-name can only be specified once.
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_mutiple_use)
+ << CtxSelectorName << "device";
+ P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
+ << CtxSelectorName;
+ }
+ OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
+ (void)P.ConsumeToken();
+ switch (CSKind) {
+ case OMP_CTX_kind: {
+ // Parse '('.
+ BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
+ (void)T.expectAndConsume(diag::err_expected_lparen_after,
+ CtxSelectorName.data());
+ llvm::UniqueVector<Sema::OMPCtxStringType> Kinds;
+ do {
+ // Parse <kind>.
+ StringRef KindName;
+ if (Tok.is(tok::identifier)) {
+ Buffer.clear();
+ KindName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
+ SourceLocation SLoc = P.getCurToken().getLocation();
+ (void)P.ConsumeToken();
+ if (llvm::StringSwitch<bool>(KindName)
+ .Case("host", false)
+ .Case("nohost", false)
+ .Case("cpu", false)
+ .Case("gpu", false)
+ .Case("fpga", false)
+ .Default(true)) {
+ P.Diag(SLoc, diag::err_omp_wrong_device_kind_trait) << KindName;
+ } else {
+ Kinds.insert(KindName);
+ }
+ } else {
+ P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
+ << "'host', 'nohost', 'cpu', 'gpu', or 'fpga'"
+ << "kind"
+ << "device";
+ }
+ if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
+ P.Diag(Tok, diag::err_expected_punc)
+ << (KindName.empty() ? "kind of device" : KindName);
+ }
+ } while (Tok.is(tok::identifier));
+ // Parse ')'.
+ (void)T.consumeClose();
+ if (!Kinds.empty())
+ Data.emplace_back(OMP_CTX_SET_device, CSKind, ExprResult(), Kinds);
+ break;
+ }
+ case OMP_CTX_vendor:
+ case OMP_CTX_unknown:
+ P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
+ << "device";
+ // Skip until either '}', ')', or end of directive.
+ while (!P.SkipUntil(tok::r_brace, tok::r_paren,
+ tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
+ ;
+ return;
+ }
+}
+
/// Parses clauses for 'declare variant' directive.
/// clause:
/// <selector_set_name> '=' '{' <context_selectors> '}'
/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
bool Parser::parseOpenMPContextSelectors(
- SourceLocation Loc,
- llvm::function_ref<void(SourceRange,
- const Sema::OpenMPDeclareVariantCtsSelectorData &)>
- Callback) {
+ SourceLocation Loc, SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
llvm::StringMap<SourceLocation> UsedCtxSets;
do {
// Parse inner context selector set name.
@@ -921,7 +1006,7 @@ bool Parser::parseOpenMPContextSelectors(
<< getOpenMPClauseName(OMPC_match);
return true;
}
- SmallString<16> Buffer;
+ Sema::OMPCtxStringType Buffer;
StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation());
if (!Res.second) {
@@ -949,17 +1034,18 @@ bool Parser::parseOpenMPContextSelectors(
tok::annot_pragma_openmp_end);
if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
return true;
- OMPDeclareVariantAttr::CtxSelectorSetType CSSKind =
- OMPDeclareVariantAttr::CtxSetUnknown;
- (void)OMPDeclareVariantAttr::ConvertStrToCtxSelectorSetType(
- CtxSelectorSetName, CSSKind);
+ OpenMPContextSelectorSetKind CSSKind =
+ getOpenMPContextSelectorSet(CtxSelectorSetName);
llvm::StringMap<SourceLocation> UsedCtx;
do {
switch (CSSKind) {
- case OMPDeclareVariantAttr::CtxSetImplementation:
- parseImplementationSelector(*this, Loc, UsedCtx, Callback);
+ case OMP_CTX_SET_implementation:
+ parseImplementationSelector(*this, Loc, UsedCtx, Data);
break;
- case OMPDeclareVariantAttr::CtxSetUnknown:
+ case OMP_CTX_SET_device:
+ parseDeviceSelector(*this, Loc, UsedCtx, Data);
+ break;
+ case OMP_CTX_SET_unknown:
// Skip until either '}', ')', or end of directive.
while (!SkipUntil(tok::r_brace, tok::r_paren,
tok::annot_pragma_openmp_end, StopBeforeMatch))
@@ -998,9 +1084,16 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
SourceLocation RLoc;
// Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
// instead of MemberExprs.
- ExprResult AssociatedFunction =
- ParseOpenMPParensExpr(getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
- /*IsAddressOfOperand=*/true);
+ ExprResult AssociatedFunction;
+ {
+ // Do not mark function as is used to prevent its emission if this is the
+ // only place where it is used.
+ EnterExpressionEvaluationContext Unevaluated(
+ Actions, Sema::ExpressionEvaluationContext::Unevaluated);
+ AssociatedFunction = ParseOpenMPParensExpr(
+ getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
+ /*IsAddressOfOperand=*/true);
+ }
if (!AssociatedFunction.isUsable()) {
if (!Tok.is(tok::annot_pragma_openmp_end))
while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
@@ -1039,15 +1132,8 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
}
// Parse inner context selectors.
- if (!parseOpenMPContextSelectors(
- Loc, [this, &DeclVarData](
- SourceRange SR,
- const Sema::OpenMPDeclareVariantCtsSelectorData &Data) {
- if (DeclVarData.hasValue())
- Actions.ActOnOpenMPDeclareVariantDirective(
- DeclVarData.getValue().first, DeclVarData.getValue().second,
- SR, Data);
- })) {
+ SmallVector<Sema::OMPCtxSelectorData, 4> Data;
+ if (!parseOpenMPContextSelectors(Loc, Data)) {
// Parse ')'.
(void)T.consumeClose();
// Need to check for extra tokens.
@@ -1060,6 +1146,10 @@ void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
// Skip last tokens.
while (Tok.isNot(tok::annot_pragma_openmp_end))
ConsumeAnyToken();
+ if (DeclVarData.hasValue())
+ Actions.ActOnOpenMPDeclareVariantDirective(
+ DeclVarData.getValue().first, DeclVarData.getValue().second,
+ SourceRange(Loc, Tok.getLocation()), Data);
// Skip the last annot_pragma_openmp_end.
(void)ConsumeAnnotationToken();
}
@@ -1245,13 +1335,45 @@ void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
/// annot_pragma_openmp_end
///
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
- AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
+ AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, bool Delayed,
DeclSpec::TST TagType, Decl *Tag) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
+ ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
- SourceLocation Loc = ConsumeAnnotationToken();
- OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
+ SourceLocation Loc;
+ OpenMPDirectiveKind DKind;
+ if (Delayed) {
+ TentativeParsingAction TPA(*this);
+ Loc = ConsumeAnnotationToken();
+ DKind = parseOpenMPDirectiveKind(*this);
+ if (DKind == OMPD_declare_reduction || DKind == OMPD_declare_mapper) {
+ // Need to delay parsing until completion of the parent class.
+ TPA.Revert();
+ CachedTokens Toks;
+ unsigned Cnt = 1;
+ Toks.push_back(Tok);
+ while (Cnt && Tok.isNot(tok::eof)) {
+ (void)ConsumeAnyToken();
+ if (Tok.is(tok::annot_pragma_openmp))
+ ++Cnt;
+ else if (Tok.is(tok::annot_pragma_openmp_end))
+ --Cnt;
+ Toks.push_back(Tok);
+ }
+ // Skip last annot_pragma_openmp_end.
+ if (Cnt == 0)
+ (void)ConsumeAnyToken();
+ auto *LP = new LateParsedPragma(this, AS);
+ LP->takeToks(Toks);
+ getCurrentClass().LateParsedDeclarations.push_back(LP);
+ return nullptr;
+ }
+ TPA.Commit();
+ } else {
+ Loc = ConsumeAnnotationToken();
+ DKind = parseOpenMPDirectiveKind(*this);
+ }
switch (DKind) {
case OMPD_threadprivate: {
@@ -1403,7 +1525,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
DeclGroupPtrTy Ptr;
if (Tok.is(tok::annot_pragma_openmp)) {
- Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
+ Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, Delayed,
+ TagType, Tag);
} else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
// Here we expect to see some function declaration.
if (AS == AS_none) {
@@ -1496,6 +1619,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
case OMPD_parallel_sections:
+ case OMPD_parallel_master:
case OMPD_atomic:
case OMPD_target:
case OMPD_teams:
@@ -1511,6 +1635,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
case OMPD_master_taskloop:
case OMPD_master_taskloop_simd:
case OMPD_parallel_master_taskloop:
+ case OMPD_parallel_master_taskloop_simd:
case OMPD_distribute:
case OMPD_end_declare_target:
case OMPD_target_update:
@@ -1562,24 +1687,26 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
/// executable-directive:
/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
-/// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' |
-/// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' |
-/// 'for simd' | 'parallel for simd' | 'target' | 'target data' |
-/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' | 'master
-/// taskloop' | 'master taskloop simd' | 'parallel master taskloop' |
-/// 'distribute' | 'target enter data' | 'target exit data' | 'target
-/// parallel' | 'target parallel for' | 'target update' | 'distribute
-/// parallel for' | 'distribute paralle for simd' | 'distribute simd' |
-/// 'target parallel for simd' | 'target simd' | 'teams distribute' |
-/// 'teams distribute simd' | 'teams distribute parallel for simd' |
-/// 'teams distribute parallel for' | 'target teams' | 'target teams
-/// distribute' | 'target teams distribute parallel for' | 'target teams
-/// distribute parallel for simd' | 'target teams distribute simd'
-/// {clause} annot_pragma_openmp_end
+/// 'parallel for' | 'parallel sections' | 'parallel master' | 'task' |
+/// 'taskyield' | 'barrier' | 'taskwait' | 'flush' | 'ordered' |
+/// 'atomic' | 'for simd' | 'parallel for simd' | 'target' | 'target
+/// data' | 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' |
+/// 'master taskloop' | 'master taskloop simd' | 'parallel master
+/// taskloop' | 'parallel master taskloop simd' | 'distribute' | 'target
+/// enter data' | 'target exit data' | 'target parallel' | 'target
+/// parallel for' | 'target update' | 'distribute parallel for' |
+/// 'distribute paralle for simd' | 'distribute simd' | 'target parallel
+/// for simd' | 'target simd' | 'teams distribute' | 'teams distribute
+/// simd' | 'teams distribute parallel for simd' | 'teams distribute
+/// parallel for' | 'target teams' | 'target teams distribute' | 'target
+/// teams distribute parallel for' | 'target teams distribute parallel
+/// for simd' | 'target teams distribute simd' {clause}
+/// annot_pragma_openmp_end
///
StmtResult
Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
+ ParsingOpenMPDirectiveRAII DirScope(*this);
ParenBraceBracketBalancer BalancerRAIIObj(*this);
SmallVector<OMPClause *, 5> Clauses;
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
@@ -1739,6 +1866,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_parallel_for:
case OMPD_parallel_for_simd:
case OMPD_parallel_sections:
+ case OMPD_parallel_master:
case OMPD_task:
case OMPD_ordered:
case OMPD_atomic:
@@ -1753,6 +1881,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
case OMPD_master_taskloop:
case OMPD_master_taskloop_simd:
case OMPD_parallel_master_taskloop:
+ case OMPD_parallel_master_taskloop_simd:
case OMPD_distribute:
case OMPD_distribute_parallel_for:
case OMPD_distribute_parallel_for_simd:
@@ -1890,7 +2019,7 @@ bool Parser::ParseOpenMPSimpleVarList(
// Parse '('.
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
if (T.expectAndConsume(diag::err_expected_lparen_after,
- getOpenMPDirectiveName(Kind)))
+ getOpenMPDirectiveName(Kind).data()))
return true;
bool IsCorrect = true;
bool NoIdentIsFound = true;
@@ -1963,7 +2092,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
bool ErrorFound = false;
bool WrongDirective = false;
// Check if clause is allowed for the given directive.
- if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) {
+ if (CKind != OMPC_unknown &&
+ !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
<< getOpenMPDirectiveName(DKind);
ErrorFound = true;
@@ -2042,15 +2172,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_defaultmap:
// OpenMP [2.7.1, Restrictions, p. 3]
// Only one schedule clause can appear on a loop directive.
- // OpenMP [2.10.4, Restrictions, p. 106]
+ // OpenMP 4.5 [2.10.4, Restrictions, p. 106]
// At most one defaultmap clause can appear on the directive.
- if (!FirstClause) {
+ if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
+ !FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
ErrorFound = true;
}
LLVM_FALLTHROUGH;
-
case OMPC_if:
Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
break;
@@ -2102,6 +2232,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_use_device_ptr:
case OMPC_is_device_ptr:
case OMPC_allocate:
+ case OMPC_nontemporal:
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
break;
case OMPC_device_type:
@@ -2133,8 +2264,8 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
return ExprError();
SourceLocation ELoc = Tok.getLocation();
- ExprResult LHS(ParseCastExpression(
- /*isUnaryExpression=*/false, IsAddressOfOperand, NotTypeCast));
+ ExprResult LHS(ParseCastExpression(AnyCastExpr, IsAddressOfOperand,
+ NotTypeCast));
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
@@ -2334,8 +2465,13 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
DelimLoc = ConsumeAnyToken();
} else if (Kind == OMPC_defaultmap) {
// Get a defaultmap modifier
- Arg.push_back(getOpenMPSimpleClauseType(
- Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
+ unsigned Modifier = getOpenMPSimpleClauseType(
+ Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
+ // Set defaultmap modifier to unknown if it is either scalar, aggregate, or
+ // pointer
+ if (Modifier < OMPC_DEFAULTMAP_MODIFIER_unknown)
+ Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown;
+ Arg.push_back(Modifier);
KLoc.push_back(Tok.getLocation());
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
Tok.isNot(tok::annot_pragma_openmp_end))
@@ -2356,15 +2492,16 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
assert(Kind == OMPC_if);
KLoc.push_back(Tok.getLocation());
TentativeParsingAction TPA(*this);
- Arg.push_back(parseOpenMPDirectiveKind(*this));
- if (Arg.back() != OMPD_unknown) {
+ auto DK = parseOpenMPDirectiveKind(*this);
+ Arg.push_back(DK);
+ if (DK != OMPD_unknown) {
ConsumeToken();
if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
TPA.Commit();
DelimLoc = ConsumeToken();
} else {
TPA.Revert();
- Arg.back() = OMPD_unknown;
+ Arg.back() = unsigned(OMPD_unknown);
}
} else {
TPA.Revert();
@@ -2376,7 +2513,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
Kind == OMPC_if;
if (NeedAnExpression) {
SourceLocation ELoc = Tok.getLocation();
- ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
+ ExprResult LHS(ParseCastExpression(AnyCastExpr, false, NotTypeCast));
Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
Val =
Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
@@ -2541,8 +2678,8 @@ static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
P.Diag(Tok, diag::err_omp_map_type_missing);
return;
}
- Data.MapType = isMapType(P);
- if (Data.MapType == OMPC_MAP_unknown)
+ Data.ExtraModifier = isMapType(P);
+ if (Data.ExtraModifier == OMPC_MAP_unknown)
P.Diag(Tok, diag::err_omp_unknown_map_type);
P.ConsumeToken();
}
@@ -2587,20 +2724,18 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.ReductionOrMapperId =
Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
} else if (Kind == OMPC_depend) {
- // Handle dependency type for depend clause.
+ // Handle dependency type for depend clause.
ColonProtectionRAIIObject ColonRAII(*this);
- Data.DepKind =
- static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
- Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
- Data.DepLinMapLoc = Tok.getLocation();
-
- if (Data.DepKind == OMPC_DEPEND_unknown) {
+ Data.ExtraModifier = getOpenMPSimpleClauseType(
+ Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "");
+ Data.DepLinMapLastLoc = Tok.getLocation();
+ if (Data.ExtraModifier == OMPC_DEPEND_unknown) {
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
} else {
ConsumeToken();
// Special processing for depend(source) clause.
- if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
+ if (DKind == OMPD_ordered && Data.ExtraModifier == OMPC_DEPEND_source) {
// Parse ')'.
T.consumeClose();
return false;
@@ -2615,13 +2750,32 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
}
} else if (Kind == OMPC_linear) {
// Try to parse modifier if any.
+ Data.ExtraModifier = OMPC_LINEAR_val;
if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
- Data.LinKind = static_cast<OpenMPLinearClauseKind>(
- getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
- Data.DepLinMapLoc = ConsumeToken();
+ Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
+ Data.DepLinMapLastLoc = ConsumeToken();
LinearT.consumeOpen();
NeedRParenForLinear = true;
}
+ } else if (Kind == OMPC_lastprivate) {
+ // Try to parse modifier if any.
+ Data.ExtraModifier = OMPC_LASTPRIVATE_unknown;
+ // Conditional modifier allowed only in OpenMP 5.0 and not supported in
+ // distribute and taskloop based directives.
+ if ((getLangOpts().OpenMP >= 50 && !isOpenMPDistributeDirective(DKind) &&
+ !isOpenMPTaskLoopDirective(DKind)) &&
+ Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::colon)) {
+ Data.ExtraModifier = getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok));
+ Data.DepLinMapLastLoc = Tok.getLocation();
+ if (Data.ExtraModifier == OMPC_LASTPRIVATE_unknown) {
+ SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ } else {
+ ConsumeToken();
+ }
+ assert(Tok.is(tok::colon) && "Expected colon.");
+ Data.ColonLoc = ConsumeToken();
+ }
} else if (Kind == OMPC_map) {
// Handle map type for map clause.
ColonProtectionRAIIObject ColonRAII(*this);
@@ -2629,7 +2783,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
// The first identifier may be a list item, a map-type or a
// map-type-modifier. The map-type can also be delete which has the same
// spelling of the C++ delete keyword.
- Data.DepLinMapLoc = Tok.getLocation();
+ Data.ExtraModifier = OMPC_MAP_unknown;
+ Data.DepLinMapLastLoc = Tok.getLocation();
// Check for presence of a colon in the map clause.
TentativeParsingAction TPA(*this);
@@ -2649,8 +2804,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
else
SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
}
- if (Data.MapType == OMPC_MAP_unknown) {
- Data.MapType = OMPC_MAP_tofrom;
+ if (Data.ExtraModifier == OMPC_MAP_unknown) {
+ Data.ExtraModifier = OMPC_MAP_tofrom;
Data.IsMapTypeImplicit = true;
}
@@ -2716,8 +2871,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
(Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
(Kind == OMPC_reduction && !InvalidReductionId) ||
- (Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) ||
- (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
+ (Kind == OMPC_map && Data.ExtraModifier != OMPC_MAP_unknown) ||
+ (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown);
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
@@ -2767,7 +2922,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.RLoc = Tok.getLocation();
if (!T.consumeClose())
Data.RLoc = T.getCloseLocation();
- return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
+ return (Kind == OMPC_depend && Data.ExtraModifier != OMPC_DEPEND_unknown &&
Vars.empty()) ||
(Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
(MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
@@ -2837,8 +2992,8 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
return Actions.ActOnOpenMPVarListClause(
Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
- Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId, Data.DepKind,
- Data.LinKind, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
- Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc);
+ Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
+ Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
+ Data.IsMapTypeImplicit, Data.DepLinMapLastLoc);
}