2013-03-22 14:34:35 +08:00
|
|
|
//===--- ParseOpenMP.cpp - OpenMP directives parsing ----------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2013-03-22 14:34:35 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \file
|
2018-05-09 09:00:01 +08:00
|
|
|
/// This file implements parsing of all OpenMP directives and clauses.
|
2013-03-22 14:34:35 +08:00
|
|
|
///
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2014-05-06 18:08:46 +08:00
|
|
|
#include "clang/AST/ASTContext.h"
|
2013-07-19 11:13:43 +08:00
|
|
|
#include "clang/AST/StmtOpenMP.h"
|
2013-03-22 14:34:35 +08:00
|
|
|
#include "clang/Parse/ParseDiagnostic.h"
|
2013-05-13 12:18:18 +08:00
|
|
|
#include "clang/Parse/Parser.h"
|
2017-03-23 23:11:07 +08:00
|
|
|
#include "clang/Parse/RAIIObjectsForParser.h"
|
2013-05-13 12:18:18 +08:00
|
|
|
#include "clang/Sema/Scope.h"
|
|
|
|
#include "llvm/ADT/PointerIntPair.h"
|
2019-10-10 23:15:26 +08:00
|
|
|
#include "llvm/ADT/UniqueVector.h"
|
2015-07-21 21:44:28 +08:00
|
|
|
|
2013-03-22 14:34:35 +08:00
|
|
|
using namespace clang;
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
using namespace llvm::omp;
|
2013-03-22 14:34:35 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// OpenMP declarative directives.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2016-02-13 14:53:38 +08:00
|
|
|
namespace {
|
|
|
|
enum OpenMPDirectiveKindEx {
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
OMPD_cancellation = unsigned(OMPD_unknown) + 1,
|
2016-02-13 14:53:38 +08:00
|
|
|
OMPD_data,
|
2016-03-03 13:21:39 +08:00
|
|
|
OMPD_declare,
|
2016-04-06 19:38:59 +08:00
|
|
|
OMPD_end,
|
|
|
|
OMPD_end_declare,
|
2016-02-13 14:53:38 +08:00
|
|
|
OMPD_enter,
|
|
|
|
OMPD_exit,
|
|
|
|
OMPD_point,
|
2016-03-03 13:21:39 +08:00
|
|
|
OMPD_reduction,
|
2016-02-13 14:53:38 +08:00
|
|
|
OMPD_target_enter,
|
2016-05-27 01:30:50 +08:00
|
|
|
OMPD_target_exit,
|
|
|
|
OMPD_update,
|
2016-12-01 07:51:03 +08:00
|
|
|
OMPD_distribute_parallel,
|
2016-12-30 06:16:30 +08:00
|
|
|
OMPD_teams_distribute_parallel,
|
2019-02-02 04:25:04 +08:00
|
|
|
OMPD_target_teams_distribute_parallel,
|
|
|
|
OMPD_mapper,
|
2019-09-14 04:18:17 +08:00
|
|
|
OMPD_variant,
|
2016-02-13 14:53:38 +08:00
|
|
|
};
|
2016-05-09 22:59:13 +08:00
|
|
|
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
// 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;
|
|
|
|
};
|
|
|
|
|
2019-03-08 01:54:44 +08:00
|
|
|
class DeclDirectiveListParserHelper final {
|
2016-05-09 22:59:13 +08:00
|
|
|
SmallVector<Expr *, 4> Identifiers;
|
|
|
|
Parser *P;
|
2019-03-08 01:54:44 +08:00
|
|
|
OpenMPDirectiveKind Kind;
|
2016-05-09 22:59:13 +08:00
|
|
|
|
|
|
|
public:
|
2019-03-08 01:54:44 +08:00
|
|
|
DeclDirectiveListParserHelper(Parser *P, OpenMPDirectiveKind Kind)
|
|
|
|
: P(P), Kind(Kind) {}
|
2016-05-09 22:59:13 +08:00
|
|
|
void operator()(CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
|
2019-03-08 01:54:44 +08:00
|
|
|
ExprResult Res = P->getActions().ActOnOpenMPIdExpression(
|
|
|
|
P->getCurScope(), SS, NameInfo, Kind);
|
2016-05-09 22:59:13 +08:00
|
|
|
if (Res.isUsable())
|
|
|
|
Identifiers.push_back(Res.get());
|
|
|
|
}
|
|
|
|
llvm::ArrayRef<Expr *> getIdentifiers() const { return Identifiers; }
|
|
|
|
};
|
2016-02-13 14:53:38 +08:00
|
|
|
} // namespace
|
|
|
|
|
|
|
|
// Map token string to extended OMP token kind that are
|
|
|
|
// OpenMPDirectiveKind + OpenMPDirectiveKindEx.
|
|
|
|
static unsigned getOpenMPDirectiveKindEx(StringRef S) {
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
OpenMPDirectiveKindExWrapper DKind = getOpenMPDirectiveKind(S);
|
2016-02-13 14:53:38 +08:00
|
|
|
if (DKind != OMPD_unknown)
|
|
|
|
return DKind;
|
|
|
|
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
return llvm::StringSwitch<OpenMPDirectiveKindExWrapper>(S)
|
2016-02-13 14:53:38 +08:00
|
|
|
.Case("cancellation", OMPD_cancellation)
|
|
|
|
.Case("data", OMPD_data)
|
2016-03-03 13:21:39 +08:00
|
|
|
.Case("declare", OMPD_declare)
|
2016-04-06 19:38:59 +08:00
|
|
|
.Case("end", OMPD_end)
|
2016-02-13 14:53:38 +08:00
|
|
|
.Case("enter", OMPD_enter)
|
|
|
|
.Case("exit", OMPD_exit)
|
|
|
|
.Case("point", OMPD_point)
|
2016-03-03 13:21:39 +08:00
|
|
|
.Case("reduction", OMPD_reduction)
|
2016-05-27 01:30:50 +08:00
|
|
|
.Case("update", OMPD_update)
|
2019-02-02 04:25:04 +08:00
|
|
|
.Case("mapper", OMPD_mapper)
|
2019-09-14 04:18:17 +08:00
|
|
|
.Case("variant", OMPD_variant)
|
2016-02-13 14:53:38 +08:00
|
|
|
.Default(OMPD_unknown);
|
|
|
|
}
|
|
|
|
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
static OpenMPDirectiveKindExWrapper parseOpenMPDirectiveKind(Parser &P) {
|
2014-09-18 13:12:34 +08:00
|
|
|
// 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.
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
static const OpenMPDirectiveKindExWrapper F[][3] = {
|
2018-04-24 03:53:05 +08:00
|
|
|
{OMPD_cancellation, OMPD_point, OMPD_cancellation_point},
|
|
|
|
{OMPD_declare, OMPD_reduction, OMPD_declare_reduction},
|
2019-02-02 04:25:04 +08:00
|
|
|
{OMPD_declare, OMPD_mapper, OMPD_declare_mapper},
|
2018-04-24 03:53:05 +08:00
|
|
|
{OMPD_declare, OMPD_simd, OMPD_declare_simd},
|
|
|
|
{OMPD_declare, OMPD_target, OMPD_declare_target},
|
2019-09-14 04:18:17 +08:00
|
|
|
{OMPD_declare, OMPD_variant, OMPD_declare_variant},
|
2018-04-24 03:53:05 +08:00
|
|
|
{OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel},
|
|
|
|
{OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for},
|
|
|
|
{OMPD_distribute_parallel_for, OMPD_simd,
|
|
|
|
OMPD_distribute_parallel_for_simd},
|
|
|
|
{OMPD_distribute, OMPD_simd, OMPD_distribute_simd},
|
|
|
|
{OMPD_end, OMPD_declare, OMPD_end_declare},
|
|
|
|
{OMPD_end_declare, OMPD_target, OMPD_end_declare_target},
|
|
|
|
{OMPD_target, OMPD_data, OMPD_target_data},
|
|
|
|
{OMPD_target, OMPD_enter, OMPD_target_enter},
|
|
|
|
{OMPD_target, OMPD_exit, OMPD_target_exit},
|
|
|
|
{OMPD_target, OMPD_update, OMPD_target_update},
|
|
|
|
{OMPD_target_enter, OMPD_data, OMPD_target_enter_data},
|
|
|
|
{OMPD_target_exit, OMPD_data, OMPD_target_exit_data},
|
|
|
|
{OMPD_for, OMPD_simd, OMPD_for_simd},
|
|
|
|
{OMPD_parallel, OMPD_for, OMPD_parallel_for},
|
|
|
|
{OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd},
|
|
|
|
{OMPD_parallel, OMPD_sections, OMPD_parallel_sections},
|
|
|
|
{OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd},
|
|
|
|
{OMPD_target, OMPD_parallel, OMPD_target_parallel},
|
|
|
|
{OMPD_target, OMPD_simd, OMPD_target_simd},
|
|
|
|
{OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for},
|
|
|
|
{OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd},
|
|
|
|
{OMPD_teams, OMPD_distribute, OMPD_teams_distribute},
|
|
|
|
{OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd},
|
|
|
|
{OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel},
|
|
|
|
{OMPD_teams_distribute_parallel, OMPD_for,
|
|
|
|
OMPD_teams_distribute_parallel_for},
|
|
|
|
{OMPD_teams_distribute_parallel_for, OMPD_simd,
|
|
|
|
OMPD_teams_distribute_parallel_for_simd},
|
|
|
|
{OMPD_target, OMPD_teams, OMPD_target_teams},
|
|
|
|
{OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute},
|
|
|
|
{OMPD_target_teams_distribute, OMPD_parallel,
|
|
|
|
OMPD_target_teams_distribute_parallel},
|
|
|
|
{OMPD_target_teams_distribute, OMPD_simd,
|
|
|
|
OMPD_target_teams_distribute_simd},
|
|
|
|
{OMPD_target_teams_distribute_parallel, OMPD_for,
|
|
|
|
OMPD_target_teams_distribute_parallel_for},
|
|
|
|
{OMPD_target_teams_distribute_parallel_for, OMPD_simd,
|
2019-10-11 04:13:02 +08:00
|
|
|
OMPD_target_teams_distribute_parallel_for_simd},
|
2019-10-15 01:17:41 +08:00
|
|
|
{OMPD_master, OMPD_taskloop, OMPD_master_taskloop},
|
2019-10-19 00:47:35 +08:00
|
|
|
{OMPD_master_taskloop, OMPD_simd, OMPD_master_taskloop_simd},
|
2019-10-15 01:17:41 +08:00
|
|
|
{OMPD_parallel, OMPD_master, OMPD_parallel_master},
|
2019-10-25 22:27:13 +08:00
|
|
|
{OMPD_parallel_master, OMPD_taskloop, OMPD_parallel_master_taskloop},
|
|
|
|
{OMPD_parallel_master_taskloop, OMPD_simd,
|
|
|
|
OMPD_parallel_master_taskloop_simd}};
|
2016-03-03 13:21:39 +08:00
|
|
|
enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 };
|
2018-04-24 03:53:05 +08:00
|
|
|
Token Tok = P.getCurToken();
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
OpenMPDirectiveKindExWrapper DKind =
|
2014-07-07 21:01:15 +08:00
|
|
|
Tok.isAnnotation()
|
2016-02-13 14:53:38 +08:00
|
|
|
? static_cast<unsigned>(OMPD_unknown)
|
|
|
|
: getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
|
|
|
|
if (DKind == OMPD_unknown)
|
|
|
|
return OMPD_unknown;
|
2015-07-21 21:44:28 +08:00
|
|
|
|
2018-04-24 03:53:05 +08:00
|
|
|
for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) {
|
|
|
|
if (DKind != F[I][0])
|
2016-02-13 14:53:38 +08:00
|
|
|
continue;
|
2015-07-21 21:44:28 +08:00
|
|
|
|
2016-02-13 14:53:38 +08:00
|
|
|
Tok = P.getPreprocessor().LookAhead(0);
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
OpenMPDirectiveKindExWrapper SDKind =
|
2016-02-13 14:53:38 +08:00
|
|
|
Tok.isAnnotation()
|
|
|
|
? static_cast<unsigned>(OMPD_unknown)
|
|
|
|
: getOpenMPDirectiveKindEx(P.getPreprocessor().getSpelling(Tok));
|
|
|
|
if (SDKind == OMPD_unknown)
|
|
|
|
continue;
|
2015-07-21 21:44:28 +08:00
|
|
|
|
2018-04-24 03:53:05 +08:00
|
|
|
if (SDKind == F[I][1]) {
|
2016-02-13 14:53:38 +08:00
|
|
|
P.ConsumeToken();
|
2018-04-24 03:53:05 +08:00
|
|
|
DKind = F[I][2];
|
2014-07-07 21:01:15 +08:00
|
|
|
}
|
|
|
|
}
|
2016-03-03 13:21:39 +08:00
|
|
|
return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind)
|
|
|
|
: OMPD_unknown;
|
|
|
|
}
|
|
|
|
|
|
|
|
static DeclarationName parseOpenMPReductionId(Parser &P) {
|
2016-03-17 18:19:46 +08:00
|
|
|
Token Tok = P.getCurToken();
|
2016-03-03 13:21:39 +08:00
|
|
|
Sema &Actions = P.getActions();
|
|
|
|
OverloadedOperatorKind OOK = OO_None;
|
2016-03-17 18:19:46 +08:00
|
|
|
// Allow to use 'operator' keyword for C++ operators
|
|
|
|
bool WithOperator = false;
|
|
|
|
if (Tok.is(tok::kw_operator)) {
|
|
|
|
P.ConsumeToken();
|
|
|
|
Tok = P.getCurToken();
|
|
|
|
WithOperator = true;
|
|
|
|
}
|
2016-03-03 13:21:39 +08:00
|
|
|
switch (Tok.getKind()) {
|
|
|
|
case tok::plus: // '+'
|
|
|
|
OOK = OO_Plus;
|
|
|
|
break;
|
|
|
|
case tok::minus: // '-'
|
|
|
|
OOK = OO_Minus;
|
|
|
|
break;
|
|
|
|
case tok::star: // '*'
|
|
|
|
OOK = OO_Star;
|
|
|
|
break;
|
|
|
|
case tok::amp: // '&'
|
|
|
|
OOK = OO_Amp;
|
|
|
|
break;
|
|
|
|
case tok::pipe: // '|'
|
|
|
|
OOK = OO_Pipe;
|
|
|
|
break;
|
|
|
|
case tok::caret: // '^'
|
|
|
|
OOK = OO_Caret;
|
|
|
|
break;
|
|
|
|
case tok::ampamp: // '&&'
|
|
|
|
OOK = OO_AmpAmp;
|
|
|
|
break;
|
|
|
|
case tok::pipepipe: // '||'
|
|
|
|
OOK = OO_PipePipe;
|
|
|
|
break;
|
|
|
|
case tok::identifier: // identifier
|
2016-03-17 18:19:46 +08:00
|
|
|
if (!WithOperator)
|
|
|
|
break;
|
2017-06-02 05:26:38 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2016-03-03 13:21:39 +08:00
|
|
|
default:
|
|
|
|
P.Diag(Tok.getLocation(), diag::err_omp_expected_reduction_identifier);
|
|
|
|
P.SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
Parser::StopBeforeMatch);
|
|
|
|
return DeclarationName();
|
|
|
|
}
|
|
|
|
P.ConsumeToken();
|
|
|
|
auto &DeclNames = Actions.getASTContext().DeclarationNames;
|
|
|
|
return OOK == OO_None ? DeclNames.getIdentifier(Tok.getIdentifierInfo())
|
|
|
|
: DeclNames.getCXXOperatorName(OOK);
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parse 'omp declare reduction' construct.
|
2016-03-03 13:21:39 +08:00
|
|
|
///
|
|
|
|
/// declare-reduction-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'reduction'
|
|
|
|
/// '(' <reduction_id> ':' <type> {',' <type>} ':' <expression> ')'
|
|
|
|
/// ['initializer' '(' ('omp_priv' '=' <expression>)|<function_call> ')']
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
/// <reduction_id> is either a base language identifier or one of the following
|
|
|
|
/// operators: '+', '-', '*', '&', '|', '^', '&&' and '||'.
|
|
|
|
///
|
|
|
|
Parser::DeclGroupPtrTy
|
|
|
|
Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
if (T.expectAndConsume(
|
|
|
|
diag::err_expected_lparen_after,
|
|
|
|
getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
|
2016-03-03 13:21:39 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
DeclarationName Name = parseOpenMPReductionId(*this);
|
|
|
|
if (Name.isEmpty() && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
|
|
|
// Consume ':'.
|
|
|
|
bool IsCorrect = !ExpectAndConsume(tok::colon);
|
|
|
|
|
|
|
|
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
2016-03-17 18:19:46 +08:00
|
|
|
IsCorrect = IsCorrect && !Name.isEmpty();
|
|
|
|
|
2016-03-03 13:21:39 +08:00
|
|
|
if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_expected_type);
|
|
|
|
IsCorrect = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
|
|
|
SmallVector<std::pair<QualType, SourceLocation>, 8> ReductionTypes;
|
|
|
|
// Parse list of types until ':' token.
|
|
|
|
do {
|
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
|
|
|
SourceRange Range;
|
2017-12-29 13:41:00 +08:00
|
|
|
TypeResult TR =
|
|
|
|
ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS);
|
2016-03-03 13:21:39 +08:00
|
|
|
if (TR.isUsable()) {
|
2018-04-24 03:53:05 +08:00
|
|
|
QualType ReductionType =
|
2016-03-03 13:21:39 +08:00
|
|
|
Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR);
|
|
|
|
if (!ReductionType.isNull()) {
|
|
|
|
ReductionTypes.push_back(
|
|
|
|
std::make_pair(ReductionType, Range.getBegin()));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SkipUntil(tok::comma, tok::colon, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Tok.is(tok::colon) || Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Consume ','.
|
|
|
|
if (ExpectAndConsume(tok::comma)) {
|
|
|
|
IsCorrect = false;
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_expected_type);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} while (Tok.isNot(tok::annot_pragma_openmp_end));
|
|
|
|
|
|
|
|
if (ReductionTypes.empty()) {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
|
|
|
// Consume ':'.
|
|
|
|
if (ExpectAndConsume(tok::colon))
|
|
|
|
IsCorrect = false;
|
|
|
|
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_expected_expression);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
DeclGroupPtrTy DRD = Actions.ActOnOpenMPDeclareReductionDirectiveStart(
|
|
|
|
getCurScope(), Actions.getCurLexicalContext(), Name, ReductionTypes, AS);
|
|
|
|
|
|
|
|
// Parse <combiner> expression and then parse initializer if any for each
|
|
|
|
// correct type.
|
|
|
|
unsigned I = 0, E = ReductionTypes.size();
|
2018-04-24 03:53:05 +08:00
|
|
|
for (Decl *D : DRD.get()) {
|
2016-03-03 13:21:39 +08:00
|
|
|
TentativeParsingAction TPA(*this);
|
|
|
|
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
|
2017-08-10 23:43:06 +08:00
|
|
|
Scope::CompoundStmtScope |
|
2016-03-03 13:21:39 +08:00
|
|
|
Scope::OpenMPDirectiveScope);
|
|
|
|
// Parse <combiner> expression.
|
|
|
|
Actions.ActOnOpenMPDeclareReductionCombinerStart(getCurScope(), D);
|
|
|
|
ExprResult CombinerResult =
|
|
|
|
Actions.ActOnFinishFullExpr(ParseAssignmentExpression().get(),
|
2019-01-05 00:58:14 +08:00
|
|
|
D->getLocation(), /*DiscardedValue*/ false);
|
2016-03-03 13:21:39 +08:00
|
|
|
Actions.ActOnOpenMPDeclareReductionCombinerEnd(D, CombinerResult.get());
|
|
|
|
|
|
|
|
if (CombinerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
TPA.Commit();
|
|
|
|
IsCorrect = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
IsCorrect = !T.consumeClose() && IsCorrect && CombinerResult.isUsable();
|
|
|
|
ExprResult InitializerResult;
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
// Parse <initializer> expression.
|
|
|
|
if (Tok.is(tok::identifier) &&
|
2018-04-24 03:53:05 +08:00
|
|
|
Tok.getIdentifierInfo()->isStr("initializer")) {
|
2016-03-03 13:21:39 +08:00
|
|
|
ConsumeToken();
|
2018-04-24 03:53:05 +08:00
|
|
|
} else {
|
2016-03-03 13:21:39 +08:00
|
|
|
Diag(Tok.getLocation(), diag::err_expected) << "'initializer'";
|
|
|
|
TPA.Commit();
|
|
|
|
IsCorrect = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
IsCorrect =
|
|
|
|
!T.expectAndConsume(diag::err_expected_lparen_after, "initializer") &&
|
|
|
|
IsCorrect;
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope |
|
2017-08-10 23:43:06 +08:00
|
|
|
Scope::CompoundStmtScope |
|
2016-03-03 13:21:39 +08:00
|
|
|
Scope::OpenMPDirectiveScope);
|
|
|
|
// Parse expression.
|
2017-09-06 22:49:58 +08:00
|
|
|
VarDecl *OmpPrivParm =
|
|
|
|
Actions.ActOnOpenMPDeclareReductionInitializerStart(getCurScope(),
|
|
|
|
D);
|
|
|
|
// Check if initializer is omp_priv <init_expr> or something else.
|
|
|
|
if (Tok.is(tok::identifier) &&
|
|
|
|
Tok.getIdentifierInfo()->isStr("omp_priv")) {
|
2019-11-13 00:19:26 +08:00
|
|
|
ConsumeToken();
|
|
|
|
ParseOpenMPReductionInitializerForDecl(OmpPrivParm);
|
2017-09-06 22:49:58 +08:00
|
|
|
} else {
|
|
|
|
InitializerResult = Actions.ActOnFinishFullExpr(
|
|
|
|
ParseAssignmentExpression().get(), D->getLocation(),
|
2019-01-05 00:58:14 +08:00
|
|
|
/*DiscardedValue*/ false);
|
2017-09-06 22:49:58 +08:00
|
|
|
}
|
2016-03-03 13:21:39 +08:00
|
|
|
Actions.ActOnOpenMPDeclareReductionInitializerEnd(
|
2017-09-06 22:49:58 +08:00
|
|
|
D, InitializerResult.get(), OmpPrivParm);
|
2016-03-03 13:21:39 +08:00
|
|
|
if (InitializerResult.isInvalid() && Tok.isNot(tok::r_paren) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
TPA.Commit();
|
|
|
|
IsCorrect = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
IsCorrect =
|
|
|
|
!T.consumeClose() && IsCorrect && !InitializerResult.isInvalid();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
++I;
|
|
|
|
// Revert parsing if not the last type, otherwise accept it, we're done with
|
|
|
|
// parsing.
|
|
|
|
if (I != E)
|
|
|
|
TPA.Revert();
|
|
|
|
else
|
|
|
|
TPA.Commit();
|
|
|
|
}
|
|
|
|
return Actions.ActOnOpenMPDeclareReductionDirectiveEnd(getCurScope(), DRD,
|
|
|
|
IsCorrect);
|
2014-07-07 21:01:15 +08:00
|
|
|
}
|
|
|
|
|
2017-09-06 22:49:58 +08:00
|
|
|
void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
|
|
|
|
// Parse declarator '=' initializer.
|
|
|
|
// If a '==' or '+=' is found, suggest a fixit to '='.
|
|
|
|
if (isTokenEqualOrEqualTypo()) {
|
|
|
|
ConsumeToken();
|
|
|
|
|
|
|
|
if (Tok.is(tok::code_completion)) {
|
|
|
|
Actions.CodeCompleteInitializer(getCurScope(), OmpPrivParm);
|
|
|
|
Actions.FinalizeDeclaration(OmpPrivParm);
|
|
|
|
cutOffParsing();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-11-13 00:19:26 +08:00
|
|
|
PreferredType.enterVariableInit(Tok.getLocation(), OmpPrivParm);
|
|
|
|
ExprResult Init = ParseAssignmentExpression();
|
2017-09-06 22:49:58 +08:00
|
|
|
|
|
|
|
if (Init.isInvalid()) {
|
|
|
|
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
Actions.ActOnInitializerError(OmpPrivParm);
|
|
|
|
} else {
|
|
|
|
Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
|
|
|
|
/*DirectInit=*/false);
|
|
|
|
}
|
|
|
|
} else if (Tok.is(tok::l_paren)) {
|
|
|
|
// Parse C++ direct initializer: '(' expression-list ')'
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren);
|
|
|
|
T.consumeOpen();
|
|
|
|
|
|
|
|
ExprVector Exprs;
|
|
|
|
CommaLocsTy CommaLocs;
|
|
|
|
|
2018-08-30 21:08:03 +08:00
|
|
|
SourceLocation LParLoc = T.getOpenLocation();
|
2019-02-26 19:01:50 +08:00
|
|
|
auto RunSignatureHelp = [this, OmpPrivParm, LParLoc, &Exprs]() {
|
|
|
|
QualType PreferredType = Actions.ProduceConstructorSignatureHelp(
|
|
|
|
getCurScope(), OmpPrivParm->getType()->getCanonicalTypeInternal(),
|
|
|
|
OmpPrivParm->getLocation(), Exprs, LParLoc);
|
|
|
|
CalledSignatureHelp = true;
|
|
|
|
return PreferredType;
|
|
|
|
};
|
|
|
|
if (ParseExpressionList(Exprs, CommaLocs, [&] {
|
|
|
|
PreferredType.enterFunctionArgument(Tok.getLocation(),
|
|
|
|
RunSignatureHelp);
|
|
|
|
})) {
|
|
|
|
if (PP.isCodeCompletionReached() && !CalledSignatureHelp)
|
|
|
|
RunSignatureHelp();
|
2017-09-06 22:49:58 +08:00
|
|
|
Actions.ActOnInitializerError(OmpPrivParm);
|
|
|
|
SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
} else {
|
|
|
|
// Match the ')'.
|
2018-07-07 03:35:42 +08:00
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
2017-09-06 22:49:58 +08:00
|
|
|
|
|
|
|
assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() &&
|
|
|
|
"Unexpected number of commas!");
|
|
|
|
|
2018-07-07 03:35:42 +08:00
|
|
|
ExprResult Initializer =
|
|
|
|
Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs);
|
2017-09-06 22:49:58 +08:00
|
|
|
Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(),
|
|
|
|
/*DirectInit=*/true);
|
|
|
|
}
|
|
|
|
} else if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) {
|
|
|
|
// Parse C++0x braced-init-list.
|
|
|
|
Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists);
|
|
|
|
|
|
|
|
ExprResult Init(ParseBraceInitializer());
|
|
|
|
|
|
|
|
if (Init.isInvalid()) {
|
|
|
|
Actions.ActOnInitializerError(OmpPrivParm);
|
|
|
|
} else {
|
|
|
|
Actions.AddInitializerToDecl(OmpPrivParm, Init.get(),
|
|
|
|
/*DirectInit=*/true);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Actions.ActOnUninitializedDecl(OmpPrivParm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-02 04:25:04 +08:00
|
|
|
/// Parses 'omp declare mapper' directive.
|
|
|
|
///
|
|
|
|
/// declare-mapper-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifier> ':']
|
|
|
|
/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
/// <mapper-identifier> and <var> are base language identifiers.
|
|
|
|
///
|
|
|
|
Parser::DeclGroupPtrTy
|
|
|
|
Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
|
|
|
|
bool IsCorrect = true;
|
|
|
|
// Parse '('
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
|
2019-02-02 04:25:04 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse <mapper-identifier>
|
|
|
|
auto &DeclNames = Actions.getASTContext().DeclarationNames;
|
|
|
|
DeclarationName MapperId;
|
|
|
|
if (PP.LookAhead(0).is(tok::colon)) {
|
|
|
|
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
|
|
|
|
IsCorrect = false;
|
|
|
|
} else {
|
|
|
|
MapperId = DeclNames.getIdentifier(Tok.getIdentifierInfo());
|
|
|
|
}
|
|
|
|
ConsumeToken();
|
|
|
|
// Consume ':'.
|
|
|
|
ExpectAndConsume(tok::colon);
|
|
|
|
} else {
|
|
|
|
// If no mapper identifier is provided, its name is "default" by default
|
|
|
|
MapperId =
|
|
|
|
DeclNames.getIdentifier(&Actions.getASTContext().Idents.get("default"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsCorrect && Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
|
|
|
// Parse <type> <var>
|
|
|
|
DeclarationName VName;
|
|
|
|
QualType MapperType;
|
|
|
|
SourceRange Range;
|
|
|
|
TypeResult ParsedType = parseOpenMPDeclareMapperVarDecl(Range, VName, AS);
|
|
|
|
if (ParsedType.isUsable())
|
|
|
|
MapperType =
|
|
|
|
Actions.ActOnOpenMPDeclareMapperType(Range.getBegin(), ParsedType);
|
|
|
|
if (MapperType.isNull())
|
|
|
|
IsCorrect = false;
|
|
|
|
if (!IsCorrect) {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Consume ')'.
|
|
|
|
IsCorrect &= !T.consumeClose();
|
|
|
|
if (!IsCorrect) {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch);
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Enter scope.
|
|
|
|
OMPDeclareMapperDecl *DMD = Actions.ActOnOpenMPDeclareMapperDirectiveStart(
|
|
|
|
getCurScope(), Actions.getCurLexicalContext(), MapperId, MapperType,
|
|
|
|
Range.getBegin(), VName, AS);
|
|
|
|
DeclarationNameInfo DirName;
|
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
|
|
|
|
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
|
|
|
|
ParseScope OMPDirectiveScope(this, ScopeFlags);
|
|
|
|
Actions.StartOpenMPDSABlock(OMPD_declare_mapper, DirName, getCurScope(), Loc);
|
|
|
|
|
|
|
|
// Add the mapper variable declaration.
|
|
|
|
Actions.ActOnOpenMPDeclareMapperDirectiveVarDecl(
|
|
|
|
DMD, getCurScope(), MapperType, Range.getBegin(), VName);
|
|
|
|
|
|
|
|
// Parse map clauses.
|
|
|
|
SmallVector<OMPClause *, 6> Clauses;
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
Actions.StartOpenMPClause(CKind);
|
|
|
|
OMPClause *Clause =
|
|
|
|
ParseOpenMPClause(OMPD_declare_mapper, CKind, Clauses.size() == 0);
|
|
|
|
if (Clause)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
else
|
|
|
|
IsCorrect = false;
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
Actions.EndOpenMPClause();
|
|
|
|
}
|
|
|
|
if (Clauses.empty()) {
|
|
|
|
Diag(Tok, diag::err_omp_expected_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_mapper);
|
|
|
|
IsCorrect = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Exit scope.
|
|
|
|
Actions.EndOpenMPDSABlock(nullptr);
|
|
|
|
OMPDirectiveScope.Exit();
|
|
|
|
|
|
|
|
DeclGroupPtrTy DGP =
|
|
|
|
Actions.ActOnOpenMPDeclareMapperDirectiveEnd(DMD, getCurScope(), Clauses);
|
|
|
|
if (!IsCorrect)
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
return DGP;
|
|
|
|
}
|
|
|
|
|
|
|
|
TypeResult Parser::parseOpenMPDeclareMapperVarDecl(SourceRange &Range,
|
|
|
|
DeclarationName &Name,
|
|
|
|
AccessSpecifier AS) {
|
|
|
|
// Parse the common declaration-specifiers piece.
|
|
|
|
Parser::DeclSpecContext DSC = Parser::DeclSpecContext::DSC_type_specifier;
|
|
|
|
DeclSpec DS(AttrFactory);
|
|
|
|
ParseSpecifierQualifierList(DS, AS, DSC);
|
|
|
|
|
|
|
|
// Parse the declarator.
|
|
|
|
DeclaratorContext Context = DeclaratorContext::PrototypeContext;
|
|
|
|
Declarator DeclaratorInfo(DS, Context);
|
|
|
|
ParseDeclarator(DeclaratorInfo);
|
|
|
|
Range = DeclaratorInfo.getSourceRange();
|
|
|
|
if (DeclaratorInfo.getIdentifier() == nullptr) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_mapper_expected_declarator);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
Name = Actions.GetNameForDeclarator(DeclaratorInfo).getName();
|
|
|
|
|
|
|
|
return Actions.ActOnOpenMPDeclareMapperVarDecl(getCurScope(), DeclaratorInfo);
|
|
|
|
}
|
|
|
|
|
2016-04-07 20:45:37 +08:00
|
|
|
namespace {
|
|
|
|
/// RAII that recreates function context for correct parsing of clauses of
|
|
|
|
/// 'declare simd' construct.
|
|
|
|
/// OpenMP, 2.8.2 declare simd Construct
|
|
|
|
/// The expressions appearing in the clauses of this directive are evaluated in
|
|
|
|
/// the scope of the arguments of the function declaration or definition.
|
|
|
|
class FNContextRAII final {
|
|
|
|
Parser &P;
|
|
|
|
Sema::CXXThisScopeRAII *ThisScope;
|
|
|
|
Parser::ParseScope *TempScope;
|
|
|
|
Parser::ParseScope *FnScope;
|
|
|
|
bool HasTemplateScope = false;
|
|
|
|
bool HasFunScope = false;
|
|
|
|
FNContextRAII() = delete;
|
|
|
|
FNContextRAII(const FNContextRAII &) = delete;
|
|
|
|
FNContextRAII &operator=(const FNContextRAII &) = delete;
|
|
|
|
|
|
|
|
public:
|
|
|
|
FNContextRAII(Parser &P, Parser::DeclGroupPtrTy Ptr) : P(P) {
|
|
|
|
Decl *D = *Ptr.get().begin();
|
|
|
|
NamedDecl *ND = dyn_cast<NamedDecl>(D);
|
|
|
|
RecordDecl *RD = dyn_cast_or_null<RecordDecl>(D->getDeclContext());
|
|
|
|
Sema &Actions = P.getActions();
|
|
|
|
|
|
|
|
// Allow 'this' within late-parsed attributes.
|
2018-12-13 18:15:27 +08:00
|
|
|
ThisScope = new Sema::CXXThisScopeRAII(Actions, RD, Qualifiers(),
|
2016-04-07 20:45:37 +08:00
|
|
|
ND && ND->isCXXInstanceMember());
|
|
|
|
|
|
|
|
// If the Decl is templatized, add template parameters to scope.
|
|
|
|
HasTemplateScope = D->isTemplateDecl();
|
|
|
|
TempScope =
|
|
|
|
new Parser::ParseScope(&P, Scope::TemplateParamScope, HasTemplateScope);
|
|
|
|
if (HasTemplateScope)
|
|
|
|
Actions.ActOnReenterTemplateScope(Actions.getCurScope(), D);
|
|
|
|
|
|
|
|
// If the Decl is on a function, add function parameters to the scope.
|
|
|
|
HasFunScope = D->isFunctionOrFunctionTemplate();
|
2017-08-10 23:43:06 +08:00
|
|
|
FnScope = new Parser::ParseScope(
|
|
|
|
&P, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope,
|
|
|
|
HasFunScope);
|
2016-04-07 20:45:37 +08:00
|
|
|
if (HasFunScope)
|
|
|
|
Actions.ActOnReenterFunctionContext(Actions.getCurScope(), D);
|
|
|
|
}
|
|
|
|
~FNContextRAII() {
|
|
|
|
if (HasFunScope) {
|
|
|
|
P.getActions().ActOnExitFunctionContext();
|
|
|
|
FnScope->Exit(); // Pop scope, and remove Decls from IdResolver
|
|
|
|
}
|
|
|
|
if (HasTemplateScope)
|
|
|
|
TempScope->Exit();
|
|
|
|
delete FnScope;
|
|
|
|
delete TempScope;
|
|
|
|
delete ThisScope;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace
|
|
|
|
|
2016-04-12 17:35:56 +08:00
|
|
|
/// Parses clauses for 'declare simd' directive.
|
|
|
|
/// clause:
|
|
|
|
/// 'inbranch' | 'notinbranch'
|
|
|
|
/// 'simdlen' '(' <expr> ')'
|
|
|
|
/// { 'uniform' '(' <argument_list> ')' }
|
|
|
|
/// { 'aligned '(' <argument_list> [ ':' <alignment> ] ')' }
|
2016-04-12 19:02:11 +08:00
|
|
|
/// { 'linear '(' <argument_list> [ ':' <step> ] ')' }
|
|
|
|
static bool parseDeclareSimdClauses(
|
|
|
|
Parser &P, OMPDeclareSimdDeclAttr::BranchStateTy &BS, ExprResult &SimdLen,
|
|
|
|
SmallVectorImpl<Expr *> &Uniforms, SmallVectorImpl<Expr *> &Aligneds,
|
|
|
|
SmallVectorImpl<Expr *> &Alignments, SmallVectorImpl<Expr *> &Linears,
|
|
|
|
SmallVectorImpl<unsigned> &LinModifiers, SmallVectorImpl<Expr *> &Steps) {
|
2016-04-12 17:35:56 +08:00
|
|
|
SourceRange BSRange;
|
|
|
|
const Token &Tok = P.getCurToken();
|
|
|
|
bool IsError = false;
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
if (Tok.isNot(tok::identifier))
|
|
|
|
break;
|
|
|
|
OMPDeclareSimdDeclAttr::BranchStateTy Out;
|
|
|
|
IdentifierInfo *II = Tok.getIdentifierInfo();
|
|
|
|
StringRef ClauseName = II->getName();
|
|
|
|
// Parse 'inranch|notinbranch' clauses.
|
|
|
|
if (OMPDeclareSimdDeclAttr::ConvertStrToBranchStateTy(ClauseName, Out)) {
|
|
|
|
if (BS != OMPDeclareSimdDeclAttr::BS_Undefined && BS != Out) {
|
|
|
|
P.Diag(Tok, diag::err_omp_declare_simd_inbranch_notinbranch)
|
|
|
|
<< ClauseName
|
|
|
|
<< OMPDeclareSimdDeclAttr::ConvertBranchStateTyToStr(BS) << BSRange;
|
|
|
|
IsError = true;
|
|
|
|
}
|
|
|
|
BS = Out;
|
|
|
|
BSRange = SourceRange(Tok.getLocation(), Tok.getEndLoc());
|
|
|
|
P.ConsumeToken();
|
|
|
|
} else if (ClauseName.equals("simdlen")) {
|
|
|
|
if (SimdLen.isUsable()) {
|
|
|
|
P.Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
|
|
|
|
IsError = true;
|
|
|
|
}
|
|
|
|
P.ConsumeToken();
|
|
|
|
SourceLocation RLoc;
|
|
|
|
SimdLen = P.ParseOpenMPParensExpr(ClauseName, RLoc);
|
|
|
|
if (SimdLen.isInvalid())
|
|
|
|
IsError = true;
|
|
|
|
} else {
|
|
|
|
OpenMPClauseKind CKind = getOpenMPClauseKind(ClauseName);
|
2016-04-12 19:02:11 +08:00
|
|
|
if (CKind == OMPC_uniform || CKind == OMPC_aligned ||
|
|
|
|
CKind == OMPC_linear) {
|
2016-04-12 17:35:56 +08:00
|
|
|
Parser::OpenMPVarListDataTy Data;
|
2018-04-24 03:53:05 +08:00
|
|
|
SmallVectorImpl<Expr *> *Vars = &Uniforms;
|
2016-04-12 19:02:11 +08:00
|
|
|
if (CKind == OMPC_aligned)
|
2016-04-12 17:35:56 +08:00
|
|
|
Vars = &Aligneds;
|
2016-04-12 19:02:11 +08:00
|
|
|
else if (CKind == OMPC_linear)
|
|
|
|
Vars = &Linears;
|
2016-04-12 17:35:56 +08:00
|
|
|
|
|
|
|
P.ConsumeToken();
|
|
|
|
if (P.ParseOpenMPVarList(OMPD_declare_simd,
|
|
|
|
getOpenMPClauseKind(ClauseName), *Vars, Data))
|
|
|
|
IsError = true;
|
2018-04-24 03:53:05 +08:00
|
|
|
if (CKind == OMPC_aligned) {
|
2016-04-12 17:35:56 +08:00
|
|
|
Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
|
2018-04-24 03:53:05 +08:00
|
|
|
} else if (CKind == OMPC_linear) {
|
2016-04-12 19:02:11 +08:00
|
|
|
if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind,
|
|
|
|
Data.DepLinMapLoc))
|
|
|
|
Data.LinKind = OMPC_LINEAR_val;
|
|
|
|
LinModifiers.append(Linears.size() - LinModifiers.size(),
|
|
|
|
Data.LinKind);
|
|
|
|
Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
|
|
|
|
}
|
2016-04-12 17:35:56 +08:00
|
|
|
} else
|
|
|
|
// TODO: add parsing of other clauses.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
P.ConsumeToken();
|
|
|
|
}
|
|
|
|
return IsError;
|
|
|
|
}
|
|
|
|
|
2016-04-07 20:45:37 +08:00
|
|
|
/// Parse clauses for '#pragma omp declare simd'.
|
|
|
|
Parser::DeclGroupPtrTy
|
|
|
|
Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr,
|
|
|
|
CachedTokens &Toks, SourceLocation Loc) {
|
2019-05-17 17:32:05 +08:00
|
|
|
PP.EnterToken(Tok, /*IsReinject*/ true);
|
|
|
|
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
|
|
|
|
/*IsReinject*/ true);
|
2016-04-07 20:45:37 +08:00
|
|
|
// Consume the previously pushed token.
|
|
|
|
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
|
2019-09-14 04:18:17 +08:00
|
|
|
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
|
2016-04-07 20:45:37 +08:00
|
|
|
|
|
|
|
FNContextRAII FnContext(*this, Ptr);
|
|
|
|
OMPDeclareSimdDeclAttr::BranchStateTy BS =
|
|
|
|
OMPDeclareSimdDeclAttr::BS_Undefined;
|
|
|
|
ExprResult Simdlen;
|
2016-04-12 13:28:34 +08:00
|
|
|
SmallVector<Expr *, 4> Uniforms;
|
2016-04-12 17:35:56 +08:00
|
|
|
SmallVector<Expr *, 4> Aligneds;
|
|
|
|
SmallVector<Expr *, 4> Alignments;
|
2016-04-12 19:02:11 +08:00
|
|
|
SmallVector<Expr *, 4> Linears;
|
|
|
|
SmallVector<unsigned, 4> LinModifiers;
|
|
|
|
SmallVector<Expr *, 4> Steps;
|
|
|
|
bool IsError =
|
|
|
|
parseDeclareSimdClauses(*this, BS, Simdlen, Uniforms, Aligneds,
|
|
|
|
Alignments, Linears, LinModifiers, Steps);
|
2016-04-07 20:45:37 +08:00
|
|
|
// Need to check for extra tokens.
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_simd);
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
2017-05-19 03:21:48 +08:00
|
|
|
SourceLocation EndLoc = ConsumeAnnotationToken();
|
2018-04-24 03:53:05 +08:00
|
|
|
if (IsError)
|
|
|
|
return Ptr;
|
|
|
|
return Actions.ActOnOpenMPDeclareSimdDirective(
|
|
|
|
Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears,
|
|
|
|
LinModifiers, Steps, SourceRange(Loc, EndLoc));
|
2016-04-04 18:12:15 +08:00
|
|
|
}
|
|
|
|
|
2019-10-03 02:19:02 +08:00
|
|
|
/// Parse optional 'score' '(' <expr> ')' ':'.
|
|
|
|
static ExprResult parseContextScore(Parser &P) {
|
|
|
|
ExprResult ScoreExpr;
|
2019-11-08 00:03:10 +08:00
|
|
|
Sema::OMPCtxStringType Buffer;
|
2019-10-03 02:19:02 +08:00
|
|
|
StringRef SelectorName =
|
|
|
|
P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
|
2019-11-06 04:33:18 +08:00
|
|
|
if (!SelectorName.equals("score"))
|
2019-10-03 02:19:02 +08:00
|
|
|
return ScoreExpr;
|
|
|
|
(void)P.ConsumeToken();
|
|
|
|
SourceLocation RLoc;
|
|
|
|
ScoreExpr = P.ParseOpenMPParensExpr(SelectorName, RLoc);
|
|
|
|
// Parse ':'
|
|
|
|
if (P.getCurToken().is(tok::colon))
|
|
|
|
(void)P.ConsumeAnyToken();
|
|
|
|
else
|
|
|
|
P.Diag(P.getCurToken(), diag::warn_pragma_expected_colon)
|
|
|
|
<< "context selector score clause";
|
|
|
|
return ScoreExpr;
|
|
|
|
}
|
|
|
|
|
2019-09-26 03:43:37 +08:00
|
|
|
/// Parse context selector for 'implementation' selector set:
|
2019-10-04 23:58:45 +08:00
|
|
|
/// 'vendor' '(' [ 'score' '(' <score _expr> ')' ':' ] <vendor> { ',' <vendor> }
|
|
|
|
/// ')'
|
2019-11-08 00:03:10 +08:00
|
|
|
static void
|
|
|
|
parseImplementationSelector(Parser &P, SourceLocation Loc,
|
|
|
|
llvm::StringMap<SourceLocation> &UsedCtx,
|
|
|
|
SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
|
2019-09-26 03:43:37 +08:00
|
|
|
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)
|
|
|
|
<< "implementation";
|
|
|
|
// Skip until either '}', ')', or end of directive.
|
|
|
|
while (!P.SkipUntil(tok::r_brace, tok::r_paren,
|
|
|
|
tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
|
|
|
|
;
|
|
|
|
return;
|
|
|
|
}
|
2019-11-08 00:03:10 +08:00
|
|
|
Sema::OMPCtxStringType Buffer;
|
2019-09-26 03:43:37 +08:00
|
|
|
StringRef CtxSelectorName = P.getPreprocessor().getSpelling(Tok, Buffer);
|
2019-10-09 01:47:52 +08:00
|
|
|
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 << "implementation";
|
|
|
|
P.Diag(Res.first->getValue(), diag::note_omp_declare_variant_ctx_used_here)
|
|
|
|
<< CtxSelectorName;
|
|
|
|
}
|
2019-11-08 00:03:10 +08:00
|
|
|
OpenMPContextSelectorKind CSKind = getOpenMPContextSelector(CtxSelectorName);
|
2019-09-26 03:43:37 +08:00
|
|
|
(void)P.ConsumeToken();
|
|
|
|
switch (CSKind) {
|
2019-11-08 00:03:10 +08:00
|
|
|
case OMP_CTX_vendor: {
|
2019-09-26 03:43:37 +08:00
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
(void)T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
CtxSelectorName.data());
|
2019-11-08 00:03:10 +08:00
|
|
|
ExprResult Score = parseContextScore(P);
|
|
|
|
llvm::UniqueVector<Sema::OMPCtxStringType> Vendors;
|
2019-10-04 23:58:45 +08:00
|
|
|
do {
|
|
|
|
// Parse <vendor>.
|
|
|
|
StringRef VendorName;
|
|
|
|
if (Tok.is(tok::identifier)) {
|
|
|
|
Buffer.clear();
|
|
|
|
VendorName = P.getPreprocessor().getSpelling(P.getCurToken(), Buffer);
|
|
|
|
(void)P.ConsumeToken();
|
2019-10-09 03:44:16 +08:00
|
|
|
if (!VendorName.empty())
|
2019-10-10 23:15:26 +08:00
|
|
|
Vendors.insert(VendorName);
|
2019-10-04 23:58:45 +08:00
|
|
|
} else {
|
|
|
|
P.Diag(Tok.getLocation(), diag::err_omp_declare_variant_item_expected)
|
|
|
|
<< "vendor identifier"
|
|
|
|
<< "vendor"
|
|
|
|
<< "implementation";
|
|
|
|
}
|
|
|
|
if (!P.TryConsumeToken(tok::comma) && Tok.isNot(tok::r_paren)) {
|
|
|
|
P.Diag(Tok, diag::err_expected_punc)
|
|
|
|
<< (VendorName.empty() ? "vendor name" : VendorName);
|
|
|
|
}
|
|
|
|
} while (Tok.is(tok::identifier));
|
2019-09-26 03:43:37 +08:00
|
|
|
// Parse ')'.
|
|
|
|
(void)T.consumeClose();
|
2019-11-08 00:03:10 +08:00
|
|
|
if (!Vendors.empty())
|
|
|
|
Data.emplace_back(OMP_CTX_SET_implementation, CSKind, Score, Vendors);
|
2019-09-26 03:43:37 +08:00
|
|
|
break;
|
|
|
|
}
|
2019-11-06 04:13:30 +08:00
|
|
|
case OMP_CTX_kind:
|
2019-11-08 00:03:10 +08:00
|
|
|
case OMP_CTX_unknown:
|
2019-09-26 03:43:37 +08:00
|
|
|
P.Diag(Tok.getLocation(), diag::warn_omp_declare_variant_cs_name_expected)
|
|
|
|
<< "implementation";
|
|
|
|
// Skip until either '}', ')', or end of directive.
|
|
|
|
while (!P.SkipUntil(tok::r_brace, tok::r_paren,
|
|
|
|
tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
|
|
|
|
;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-06 04:13:30 +08:00
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-14 04:18:17 +08:00
|
|
|
/// Parses clauses for 'declare variant' directive.
|
|
|
|
/// clause:
|
|
|
|
/// <selector_set_name> '=' '{' <context_selectors> '}'
|
2019-09-19 00:24:31 +08:00
|
|
|
/// [ ',' <selector_set_name> '=' '{' <context_selectors> '}' ]
|
|
|
|
bool Parser::parseOpenMPContextSelectors(
|
2019-11-08 00:03:10 +08:00
|
|
|
SourceLocation Loc, SmallVectorImpl<Sema::OMPCtxSelectorData> &Data) {
|
2019-10-08 23:56:43 +08:00
|
|
|
llvm::StringMap<SourceLocation> UsedCtxSets;
|
2019-09-19 00:24:31 +08:00
|
|
|
do {
|
|
|
|
// Parse inner context selector set name.
|
|
|
|
if (!Tok.is(tok::identifier)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_declare_variant_no_ctx_selector)
|
2019-09-24 02:13:31 +08:00
|
|
|
<< getOpenMPClauseName(OMPC_match);
|
2019-09-14 04:18:17 +08:00
|
|
|
return true;
|
2019-09-19 00:24:31 +08:00
|
|
|
}
|
2019-11-08 00:03:10 +08:00
|
|
|
Sema::OMPCtxStringType Buffer;
|
2019-09-26 03:43:37 +08:00
|
|
|
StringRef CtxSelectorSetName = PP.getSpelling(Tok, Buffer);
|
2019-10-08 23:56:43 +08:00
|
|
|
auto Res = UsedCtxSets.try_emplace(CtxSelectorSetName, Tok.getLocation());
|
|
|
|
if (!Res.second) {
|
|
|
|
// OpenMP 5.0, 2.3.2 Context Selectors, Restrictions.
|
|
|
|
// Each trait-set-selector-name can only be specified once.
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_declare_variant_ctx_set_mutiple_use)
|
|
|
|
<< CtxSelectorSetName;
|
|
|
|
Diag(Res.first->getValue(),
|
|
|
|
diag::note_omp_declare_variant_ctx_set_used_here)
|
|
|
|
<< CtxSelectorSetName;
|
|
|
|
}
|
2019-09-19 00:24:31 +08:00
|
|
|
// Parse '='.
|
|
|
|
(void)ConsumeToken();
|
|
|
|
if (Tok.isNot(tok::equal)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_declare_variant_equal_expected)
|
2019-09-26 03:43:37 +08:00
|
|
|
<< CtxSelectorSetName;
|
2019-09-19 00:24:31 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
(void)ConsumeToken();
|
|
|
|
// TBD: add parsing of known context selectors.
|
|
|
|
// Unknown selector - just ignore it completely.
|
|
|
|
{
|
|
|
|
// Parse '{'.
|
|
|
|
BalancedDelimiterTracker TBr(*this, tok::l_brace,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
if (TBr.expectAndConsume(diag::err_expected_lbrace_after, "="))
|
|
|
|
return true;
|
2019-11-08 00:03:10 +08:00
|
|
|
OpenMPContextSelectorSetKind CSSKind =
|
|
|
|
getOpenMPContextSelectorSet(CtxSelectorSetName);
|
2019-10-09 01:47:52 +08:00
|
|
|
llvm::StringMap<SourceLocation> UsedCtx;
|
|
|
|
do {
|
|
|
|
switch (CSSKind) {
|
2019-11-08 00:03:10 +08:00
|
|
|
case OMP_CTX_SET_implementation:
|
|
|
|
parseImplementationSelector(*this, Loc, UsedCtx, Data);
|
2019-10-09 01:47:52 +08:00
|
|
|
break;
|
2019-11-06 04:13:30 +08:00
|
|
|
case OMP_CTX_SET_device:
|
|
|
|
parseDeviceSelector(*this, Loc, UsedCtx, Data);
|
|
|
|
break;
|
2019-11-08 00:03:10 +08:00
|
|
|
case OMP_CTX_SET_unknown:
|
2019-10-09 01:47:52 +08:00
|
|
|
// Skip until either '}', ')', or end of directive.
|
|
|
|
while (!SkipUntil(tok::r_brace, tok::r_paren,
|
|
|
|
tok::annot_pragma_openmp_end, StopBeforeMatch))
|
|
|
|
;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
const Token PrevTok = Tok;
|
|
|
|
if (!TryConsumeToken(tok::comma) && Tok.isNot(tok::r_brace))
|
|
|
|
Diag(Tok, diag::err_omp_expected_comma_brace)
|
|
|
|
<< (PrevTok.isAnnotation() ? "context selector trait"
|
|
|
|
: PP.getSpelling(PrevTok));
|
|
|
|
} while (Tok.is(tok::identifier));
|
2019-09-19 00:24:31 +08:00
|
|
|
// Parse '}'.
|
|
|
|
(void)TBr.consumeClose();
|
|
|
|
}
|
|
|
|
// Consume ','
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
(void)ExpectAndConsume(tok::comma);
|
|
|
|
} while (Tok.isAnyIdentifier());
|
2019-09-14 04:18:17 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse clauses for '#pragma omp declare variant ( variant-func-id ) clause'.
|
2019-09-19 00:24:31 +08:00
|
|
|
void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
|
|
|
|
CachedTokens &Toks,
|
|
|
|
SourceLocation Loc) {
|
2019-09-14 04:18:17 +08:00
|
|
|
PP.EnterToken(Tok, /*IsReinject*/ true);
|
|
|
|
PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
|
|
|
|
/*IsReinject*/ true);
|
|
|
|
// Consume the previously pushed token.
|
|
|
|
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
|
|
|
|
ConsumeAnyToken(/*ConsumeCodeCompletionTok=*/true);
|
|
|
|
|
|
|
|
FNContextRAII FnContext(*this, Ptr);
|
|
|
|
// Parse function declaration id.
|
|
|
|
SourceLocation RLoc;
|
|
|
|
// Parse with IsAddressOfOperand set to true to parse methods as DeclRefExprs
|
|
|
|
// instead of MemberExprs.
|
2019-12-11 05:12:53 +08:00
|
|
|
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);
|
|
|
|
}
|
2019-09-14 04:18:17 +08:00
|
|
|
if (!AssociatedFunction.isUsable()) {
|
|
|
|
if (!Tok.is(tok::annot_pragma_openmp_end))
|
|
|
|
while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
|
|
|
|
;
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
(void)ConsumeAnnotationToken();
|
2019-09-19 00:24:31 +08:00
|
|
|
return;
|
2019-09-14 04:18:17 +08:00
|
|
|
}
|
2019-09-19 00:24:31 +08:00
|
|
|
Optional<std::pair<FunctionDecl *, Expr *>> DeclVarData =
|
|
|
|
Actions.checkOpenMPDeclareVariantFunction(
|
|
|
|
Ptr, AssociatedFunction.get(), SourceRange(Loc, Tok.getLocation()));
|
2019-09-14 04:18:17 +08:00
|
|
|
|
2019-09-19 00:24:31 +08:00
|
|
|
// Parse 'match'.
|
2019-09-24 02:13:31 +08:00
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
if (CKind != OMPC_match) {
|
2019-09-19 00:24:31 +08:00
|
|
|
Diag(Tok.getLocation(), diag::err_omp_declare_variant_wrong_clause)
|
2019-09-24 02:13:31 +08:00
|
|
|
<< getOpenMPClauseName(OMPC_match);
|
2019-09-19 00:24:31 +08:00
|
|
|
while (!SkipUntil(tok::annot_pragma_openmp_end, Parser::StopBeforeMatch))
|
|
|
|
;
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
(void)ConsumeAnnotationToken();
|
|
|
|
return;
|
2019-09-14 04:18:17 +08:00
|
|
|
}
|
2019-09-19 00:24:31 +08:00
|
|
|
(void)ConsumeToken();
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
2019-09-24 02:13:31 +08:00
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
getOpenMPClauseName(OMPC_match))) {
|
2019-09-19 00:24:31 +08:00
|
|
|
while (!SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch))
|
|
|
|
;
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
(void)ConsumeAnnotationToken();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse inner context selectors.
|
2019-11-08 00:03:10 +08:00
|
|
|
SmallVector<Sema::OMPCtxSelectorData, 4> Data;
|
|
|
|
if (!parseOpenMPContextSelectors(Loc, Data)) {
|
2019-09-19 00:24:31 +08:00
|
|
|
// Parse ')'.
|
|
|
|
(void)T.consumeClose();
|
|
|
|
// Need to check for extra tokens.
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_variant);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip last tokens.
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
2019-11-08 00:03:10 +08:00
|
|
|
if (DeclVarData.hasValue())
|
|
|
|
Actions.ActOnOpenMPDeclareVariantDirective(
|
|
|
|
DeclVarData.getValue().first, DeclVarData.getValue().second,
|
|
|
|
SourceRange(Loc, Tok.getLocation()), Data);
|
2019-09-14 04:18:17 +08:00
|
|
|
// Skip the last annot_pragma_openmp_end.
|
2019-09-19 00:24:31 +08:00
|
|
|
(void)ConsumeAnnotationToken();
|
2019-09-14 04:18:17 +08:00
|
|
|
}
|
|
|
|
|
2019-08-24 00:11:14 +08:00
|
|
|
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
|
|
|
|
///
|
|
|
|
/// default-clause:
|
|
|
|
/// 'default' '(' 'none' | 'shared' ')
|
|
|
|
///
|
|
|
|
/// proc_bind-clause:
|
|
|
|
/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
|
|
|
|
///
|
|
|
|
/// device_type-clause:
|
|
|
|
/// 'device_type' '(' 'host' | 'nohost' | 'any' )'
|
|
|
|
namespace {
|
|
|
|
struct SimpleClauseData {
|
|
|
|
unsigned Type;
|
|
|
|
SourceLocation Loc;
|
|
|
|
SourceLocation LOpen;
|
|
|
|
SourceLocation TypeLoc;
|
|
|
|
SourceLocation RLoc;
|
|
|
|
SimpleClauseData(unsigned Type, SourceLocation Loc, SourceLocation LOpen,
|
|
|
|
SourceLocation TypeLoc, SourceLocation RLoc)
|
|
|
|
: Type(Type), Loc(Loc), LOpen(LOpen), TypeLoc(TypeLoc), RLoc(RLoc) {}
|
|
|
|
};
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
|
|
static Optional<SimpleClauseData>
|
|
|
|
parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
|
|
|
|
const Token &Tok = P.getCurToken();
|
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
SourceLocation LOpen = P.ConsumeToken();
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(P, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
getOpenMPClauseName(Kind)))
|
|
|
|
return llvm::None;
|
|
|
|
|
|
|
|
unsigned Type = getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : P.getPreprocessor().getSpelling(Tok));
|
|
|
|
SourceLocation TypeLoc = Tok.getLocation();
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
P.ConsumeAnyToken();
|
|
|
|
|
|
|
|
// Parse ')'.
|
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
|
|
|
|
|
|
|
return SimpleClauseData(Type, Loc, LOpen, TypeLoc, RLoc);
|
|
|
|
}
|
|
|
|
|
2018-11-22 04:15:57 +08:00
|
|
|
Parser::DeclGroupPtrTy Parser::ParseOMPDeclareTargetClauses() {
|
|
|
|
// OpenMP 4.5 syntax with list of entities.
|
|
|
|
Sema::NamedDeclSetType SameDirectiveDecls;
|
2019-08-24 00:11:14 +08:00
|
|
|
SmallVector<std::tuple<OMPDeclareTargetDeclAttr::MapTypeTy, SourceLocation,
|
|
|
|
NamedDecl *>,
|
|
|
|
4>
|
|
|
|
DeclareTargetDecls;
|
|
|
|
OMPDeclareTargetDeclAttr::DevTypeTy DT = OMPDeclareTargetDeclAttr::DT_Any;
|
|
|
|
SourceLocation DeviceTypeLoc;
|
2018-11-22 04:15:57 +08:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
|
|
|
|
if (Tok.is(tok::identifier)) {
|
|
|
|
IdentifierInfo *II = Tok.getIdentifierInfo();
|
|
|
|
StringRef ClauseName = II->getName();
|
2019-08-24 00:11:14 +08:00
|
|
|
bool IsDeviceTypeClause =
|
|
|
|
getLangOpts().OpenMP >= 50 &&
|
|
|
|
getOpenMPClauseKind(ClauseName) == OMPC_device_type;
|
|
|
|
// Parse 'to|link|device_type' clauses.
|
|
|
|
if (!OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT) &&
|
|
|
|
!IsDeviceTypeClause) {
|
|
|
|
Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
|
|
|
|
<< ClauseName << (getLangOpts().OpenMP >= 50 ? 1 : 0);
|
2018-11-22 04:15:57 +08:00
|
|
|
break;
|
|
|
|
}
|
2019-08-24 00:11:14 +08:00
|
|
|
// Parse 'device_type' clause and go to next clause if any.
|
|
|
|
if (IsDeviceTypeClause) {
|
|
|
|
Optional<SimpleClauseData> DevTypeData =
|
|
|
|
parseOpenMPSimpleClause(*this, OMPC_device_type);
|
|
|
|
if (DevTypeData.hasValue()) {
|
|
|
|
if (DeviceTypeLoc.isValid()) {
|
|
|
|
// We already saw another device_type clause, diagnose it.
|
|
|
|
Diag(DevTypeData.getValue().Loc,
|
|
|
|
diag::warn_omp_more_one_device_type_clause);
|
|
|
|
}
|
|
|
|
switch(static_cast<OpenMPDeviceType>(DevTypeData.getValue().Type)) {
|
|
|
|
case OMPC_DEVICE_TYPE_any:
|
|
|
|
DT = OMPDeclareTargetDeclAttr::DT_Any;
|
|
|
|
break;
|
|
|
|
case OMPC_DEVICE_TYPE_host:
|
|
|
|
DT = OMPDeclareTargetDeclAttr::DT_Host;
|
|
|
|
break;
|
|
|
|
case OMPC_DEVICE_TYPE_nohost:
|
|
|
|
DT = OMPDeclareTargetDeclAttr::DT_NoHost;
|
|
|
|
break;
|
|
|
|
case OMPC_DEVICE_TYPE_unknown:
|
|
|
|
llvm_unreachable("Unexpected device_type");
|
|
|
|
}
|
|
|
|
DeviceTypeLoc = DevTypeData.getValue().Loc;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2018-11-22 04:15:57 +08:00
|
|
|
ConsumeToken();
|
|
|
|
}
|
2019-08-24 00:11:14 +08:00
|
|
|
auto &&Callback = [this, MT, &DeclareTargetDecls, &SameDirectiveDecls](
|
|
|
|
CXXScopeSpec &SS, DeclarationNameInfo NameInfo) {
|
|
|
|
NamedDecl *ND = Actions.lookupOpenMPDeclareTargetName(
|
|
|
|
getCurScope(), SS, NameInfo, SameDirectiveDecls);
|
|
|
|
if (ND)
|
|
|
|
DeclareTargetDecls.emplace_back(MT, NameInfo.getLoc(), ND);
|
2018-11-22 04:15:57 +08:00
|
|
|
};
|
|
|
|
if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback,
|
|
|
|
/*AllowScopeSpecifier=*/true))
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Consume optional ','.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
ConsumeAnyToken();
|
2019-08-24 00:11:14 +08:00
|
|
|
for (auto &MTLocDecl : DeclareTargetDecls) {
|
|
|
|
OMPDeclareTargetDeclAttr::MapTypeTy MT;
|
|
|
|
SourceLocation Loc;
|
|
|
|
NamedDecl *ND;
|
|
|
|
std::tie(MT, Loc, ND) = MTLocDecl;
|
|
|
|
// device_type clause is applied only to functions.
|
|
|
|
Actions.ActOnOpenMPDeclareTargetName(
|
|
|
|
ND, Loc, MT, isa<VarDecl>(ND) ? OMPDeclareTargetDeclAttr::DT_Any : DT);
|
|
|
|
}
|
2018-11-22 04:15:57 +08:00
|
|
|
SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(),
|
|
|
|
SameDirectiveDecls.end());
|
|
|
|
if (Decls.empty())
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
return Actions.BuildDeclaratorGroup(Decls);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Parser::ParseOMPEndDeclareTargetDirective(OpenMPDirectiveKind DKind,
|
|
|
|
SourceLocation DTLoc) {
|
|
|
|
if (DKind != OMPD_end_declare_target) {
|
|
|
|
Diag(Tok, diag::err_expected_end_declare_target);
|
|
|
|
Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'";
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ConsumeAnyToken();
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_end_declare_target);
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
}
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parsing of declarative OpenMP directives.
|
2013-05-13 12:18:18 +08:00
|
|
|
///
|
|
|
|
/// threadprivate-directive:
|
|
|
|
/// annot_pragma_openmp 'threadprivate' simple-variable-list
|
2016-03-03 13:21:39 +08:00
|
|
|
/// annot_pragma_openmp_end
|
2013-03-22 14:34:35 +08:00
|
|
|
///
|
2019-03-08 01:54:44 +08:00
|
|
|
/// allocate-directive:
|
2019-03-13 02:52:33 +08:00
|
|
|
/// annot_pragma_openmp 'allocate' simple-variable-list [<clause>]
|
2019-03-08 01:54:44 +08:00
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2016-03-03 13:21:39 +08:00
|
|
|
/// declare-reduction-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'reduction' [...]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2019-02-02 04:25:04 +08:00
|
|
|
/// declare-mapper-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
|
|
|
|
/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2016-03-30 18:43:55 +08:00
|
|
|
/// declare-simd-directive:
|
|
|
|
/// annot_pragma_openmp 'declare simd' {<clause> [,]}
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
/// <function declaration/definition>
|
|
|
|
///
|
2018-09-26 12:28:39 +08:00
|
|
|
/// requires directive:
|
|
|
|
/// annot_pragma_openmp 'requires' <clause> [[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2016-03-30 18:43:55 +08:00
|
|
|
Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
|
|
|
|
AccessSpecifier &AS, ParsedAttributesWithRange &Attrs,
|
|
|
|
DeclSpec::TST TagType, Decl *Tag) {
|
2013-03-22 14:34:35 +08:00
|
|
|
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
|
2019-12-14 05:05:30 +08:00
|
|
|
ParsingOpenMPDirectiveRAII DirScope(*this);
|
2013-11-18 16:17:37 +08:00
|
|
|
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
2013-03-22 14:34:35 +08:00
|
|
|
|
2017-05-19 03:21:48 +08:00
|
|
|
SourceLocation Loc = ConsumeAnnotationToken();
|
2018-04-24 03:53:05 +08:00
|
|
|
OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
|
2013-05-13 12:18:18 +08:00
|
|
|
|
|
|
|
switch (DKind) {
|
2016-05-09 22:59:13 +08:00
|
|
|
case OMPD_threadprivate: {
|
2013-03-22 14:34:35 +08:00
|
|
|
ConsumeToken();
|
2019-03-08 01:54:44 +08:00
|
|
|
DeclDirectiveListParserHelper Helper(this, DKind);
|
|
|
|
if (!ParseOpenMPSimpleVarList(DKind, Helper,
|
|
|
|
/*AllowScopeSpecifier=*/true)) {
|
2013-03-22 14:34:35 +08:00
|
|
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
|
|
|
// extra tokens.
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
2019-03-08 01:54:44 +08:00
|
|
|
<< getOpenMPDirectiveName(DKind);
|
2013-12-19 03:10:49 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
2013-03-22 14:34:35 +08:00
|
|
|
}
|
2013-05-13 12:18:18 +08:00
|
|
|
// Skip the last annot_pragma_openmp_end.
|
2017-05-19 03:21:48 +08:00
|
|
|
ConsumeAnnotationToken();
|
2016-05-09 22:59:13 +08:00
|
|
|
return Actions.ActOnOpenMPThreadprivateDirective(Loc,
|
|
|
|
Helper.getIdentifiers());
|
2013-03-22 14:34:35 +08:00
|
|
|
}
|
|
|
|
break;
|
2016-05-09 22:59:13 +08:00
|
|
|
}
|
2019-03-08 01:54:44 +08:00
|
|
|
case OMPD_allocate: {
|
|
|
|
ConsumeToken();
|
|
|
|
DeclDirectiveListParserHelper Helper(this, DKind);
|
|
|
|
if (!ParseOpenMPSimpleVarList(DKind, Helper,
|
|
|
|
/*AllowScopeSpecifier=*/true)) {
|
2019-03-13 02:52:33 +08:00
|
|
|
SmallVector<OMPClause *, 1> Clauses;
|
2019-03-08 01:54:44 +08:00
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2019-03-13 02:52:33 +08:00
|
|
|
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
|
|
|
|
OMPC_unknown + 1>
|
|
|
|
FirstClauses(OMPC_unknown + 1);
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind =
|
|
|
|
Tok.isAnnotation() ? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
Actions.StartOpenMPClause(CKind);
|
|
|
|
OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
|
|
|
|
!FirstClauses[CKind].getInt());
|
|
|
|
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
FirstClauses[CKind].setInt(true);
|
|
|
|
if (Clause != nullptr)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Actions.EndOpenMPClause();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
Actions.EndOpenMPClause();
|
|
|
|
}
|
|
|
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
|
|
|
// extra tokens.
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
|
|
|
<< getOpenMPDirectiveName(DKind);
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
}
|
2019-03-08 01:54:44 +08:00
|
|
|
}
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnnotationToken();
|
2019-03-13 02:52:33 +08:00
|
|
|
return Actions.ActOnOpenMPAllocateDirective(Loc, Helper.getIdentifiers(),
|
|
|
|
Clauses);
|
2019-03-08 01:54:44 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2018-09-26 12:28:39 +08:00
|
|
|
case OMPD_requires: {
|
|
|
|
SourceLocation StartLoc = ConsumeToken();
|
|
|
|
SmallVector<OMPClause *, 5> Clauses;
|
|
|
|
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
|
|
|
|
FirstClauses(OMPC_unknown + 1);
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
2019-02-26 19:01:50 +08:00
|
|
|
Diag(Tok, diag::err_omp_expected_clause)
|
2018-09-26 12:28:39 +08:00
|
|
|
<< getOpenMPDirectiveName(OMPD_requires);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind = Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
Actions.StartOpenMPClause(CKind);
|
2019-03-13 02:52:33 +08:00
|
|
|
OMPClause *Clause = ParseOpenMPClause(OMPD_requires, CKind,
|
|
|
|
!FirstClauses[CKind].getInt());
|
|
|
|
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
2018-09-26 12:28:39 +08:00
|
|
|
FirstClauses[CKind].setInt(true);
|
|
|
|
if (Clause != nullptr)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Actions.EndOpenMPClause();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
Actions.EndOpenMPClause();
|
|
|
|
}
|
|
|
|
// Consume final annot_pragma_openmp_end
|
|
|
|
if (Clauses.size() == 0) {
|
|
|
|
Diag(Tok, diag::err_omp_expected_clause)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_requires);
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
return Actions.ActOnOpenMPRequiresDirective(StartLoc, Clauses);
|
|
|
|
}
|
2016-03-03 13:21:39 +08:00
|
|
|
case OMPD_declare_reduction:
|
|
|
|
ConsumeToken();
|
2018-04-24 03:53:05 +08:00
|
|
|
if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) {
|
2016-03-03 13:21:39 +08:00
|
|
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
|
|
|
// extra tokens.
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_reduction);
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
2017-05-19 03:21:48 +08:00
|
|
|
ConsumeAnnotationToken();
|
2016-03-03 13:21:39 +08:00
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
break;
|
2019-02-02 04:25:04 +08:00
|
|
|
case OMPD_declare_mapper: {
|
|
|
|
ConsumeToken();
|
|
|
|
if (DeclGroupPtrTy Res = ParseOpenMPDeclareMapperDirective(AS)) {
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2019-09-14 04:18:17 +08:00
|
|
|
case OMPD_declare_variant:
|
2016-03-30 18:43:55 +08:00
|
|
|
case OMPD_declare_simd: {
|
|
|
|
// The syntax is:
|
2019-09-14 04:18:17 +08:00
|
|
|
// { #pragma omp declare {simd|variant} }
|
2016-03-30 18:43:55 +08:00
|
|
|
// <function-declaration-or-definition>
|
|
|
|
//
|
2016-04-07 20:45:37 +08:00
|
|
|
CachedTokens Toks;
|
2019-09-14 04:18:17 +08:00
|
|
|
Toks.push_back(Tok);
|
|
|
|
ConsumeToken();
|
2016-04-12 13:28:34 +08:00
|
|
|
while(Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Toks.push_back(Tok);
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
Toks.push_back(Tok);
|
|
|
|
ConsumeAnyToken();
|
2016-03-30 18:43:55 +08:00
|
|
|
|
|
|
|
DeclGroupPtrTy Ptr;
|
2018-04-24 03:53:05 +08:00
|
|
|
if (Tok.is(tok::annot_pragma_openmp)) {
|
2016-03-30 18:43:55 +08:00
|
|
|
Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag);
|
2018-04-24 03:53:05 +08:00
|
|
|
} else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) {
|
2016-03-30 18:43:55 +08:00
|
|
|
// Here we expect to see some function declaration.
|
|
|
|
if (AS == AS_none) {
|
|
|
|
assert(TagType == DeclSpec::TST_unspecified);
|
|
|
|
MaybeParseCXX11Attributes(Attrs);
|
|
|
|
ParsingDeclSpec PDS(*this);
|
|
|
|
Ptr = ParseExternalDeclaration(Attrs, &PDS);
|
|
|
|
} else {
|
|
|
|
Ptr =
|
|
|
|
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!Ptr) {
|
2019-09-14 04:18:17 +08:00
|
|
|
Diag(Loc, diag::err_omp_decl_in_declare_simd_variant)
|
|
|
|
<< (DKind == OMPD_declare_simd ? 0 : 1);
|
2016-03-30 18:43:55 +08:00
|
|
|
return DeclGroupPtrTy();
|
|
|
|
}
|
2019-09-14 04:18:17 +08:00
|
|
|
if (DKind == OMPD_declare_simd)
|
|
|
|
return ParseOMPDeclareSimdClauses(Ptr, Toks, Loc);
|
|
|
|
assert(DKind == OMPD_declare_variant &&
|
|
|
|
"Expected declare variant directive only");
|
2019-09-19 00:24:31 +08:00
|
|
|
ParseOMPDeclareVariantClauses(Ptr, Toks, Loc);
|
|
|
|
return Ptr;
|
2016-03-30 18:43:55 +08:00
|
|
|
}
|
2016-04-06 19:38:59 +08:00
|
|
|
case OMPD_declare_target: {
|
|
|
|
SourceLocation DTLoc = ConsumeAnyToken();
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2018-11-22 04:15:57 +08:00
|
|
|
return ParseOMPDeclareTargetClauses();
|
2016-04-06 19:38:59 +08:00
|
|
|
}
|
2016-05-09 22:59:13 +08:00
|
|
|
|
2016-04-06 19:38:59 +08:00
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnyToken();
|
|
|
|
|
|
|
|
if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc))
|
|
|
|
return DeclGroupPtrTy();
|
|
|
|
|
2018-03-15 23:47:20 +08:00
|
|
|
llvm::SmallVector<Decl *, 4> Decls;
|
2018-04-24 03:53:05 +08:00
|
|
|
DKind = parseOpenMPDirectiveKind(*this);
|
2018-09-10 10:07:09 +08:00
|
|
|
while (DKind != OMPD_end_declare_target && Tok.isNot(tok::eof) &&
|
|
|
|
Tok.isNot(tok::r_brace)) {
|
2017-10-04 04:00:00 +08:00
|
|
|
DeclGroupPtrTy Ptr;
|
|
|
|
// Here we expect to see some function declaration.
|
|
|
|
if (AS == AS_none) {
|
|
|
|
assert(TagType == DeclSpec::TST_unspecified);
|
|
|
|
MaybeParseCXX11Attributes(Attrs);
|
|
|
|
ParsingDeclSpec PDS(*this);
|
|
|
|
Ptr = ParseExternalDeclaration(Attrs, &PDS);
|
|
|
|
} else {
|
|
|
|
Ptr =
|
|
|
|
ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag);
|
|
|
|
}
|
2018-03-15 23:47:20 +08:00
|
|
|
if (Ptr) {
|
|
|
|
DeclGroupRef Ref = Ptr.get();
|
|
|
|
Decls.append(Ref.begin(), Ref.end());
|
|
|
|
}
|
2016-04-06 19:38:59 +08:00
|
|
|
if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) {
|
|
|
|
TentativeParsingAction TPA(*this);
|
2017-05-19 03:21:48 +08:00
|
|
|
ConsumeAnnotationToken();
|
2018-04-24 03:53:05 +08:00
|
|
|
DKind = parseOpenMPDirectiveKind(*this);
|
2016-04-06 19:38:59 +08:00
|
|
|
if (DKind != OMPD_end_declare_target)
|
|
|
|
TPA.Revert();
|
|
|
|
else
|
|
|
|
TPA.Commit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-22 04:15:57 +08:00
|
|
|
ParseOMPEndDeclareTargetDirective(DKind, DTLoc);
|
2016-04-06 19:38:59 +08:00
|
|
|
Actions.ActOnFinishOpenMPDeclareTargetDirective();
|
2018-03-28 22:28:54 +08:00
|
|
|
return Actions.BuildDeclaratorGroup(Decls);
|
2016-04-06 19:38:59 +08:00
|
|
|
}
|
2013-03-22 14:34:35 +08:00
|
|
|
case OMPD_unknown:
|
|
|
|
Diag(Tok, diag::err_omp_unknown_directive);
|
|
|
|
break;
|
2013-07-19 11:13:43 +08:00
|
|
|
case OMPD_parallel:
|
2014-02-27 16:29:12 +08:00
|
|
|
case OMPD_simd:
|
2013-07-19 11:13:43 +08:00
|
|
|
case OMPD_task:
|
2014-07-18 15:47:19 +08:00
|
|
|
case OMPD_taskyield:
|
2014-07-18 17:11:51 +08:00
|
|
|
case OMPD_barrier:
|
2014-07-18 18:17:07 +08:00
|
|
|
case OMPD_taskwait:
|
2015-06-18 20:14:09 +08:00
|
|
|
case OMPD_taskgroup:
|
2014-07-21 19:26:11 +08:00
|
|
|
case OMPD_flush:
|
2014-06-18 12:14:57 +08:00
|
|
|
case OMPD_for:
|
2014-09-18 13:12:34 +08:00
|
|
|
case OMPD_for_simd:
|
2014-06-25 19:44:49 +08:00
|
|
|
case OMPD_sections:
|
2014-06-26 16:21:58 +08:00
|
|
|
case OMPD_section:
|
2014-06-26 20:05:45 +08:00
|
|
|
case OMPD_single:
|
2014-07-17 16:54:58 +08:00
|
|
|
case OMPD_master:
|
2014-07-22 14:45:04 +08:00
|
|
|
case OMPD_ordered:
|
2014-07-21 17:42:05 +08:00
|
|
|
case OMPD_critical:
|
2014-07-07 21:01:15 +08:00
|
|
|
case OMPD_parallel_for:
|
2014-09-23 17:33:00 +08:00
|
|
|
case OMPD_parallel_for_simd:
|
2014-07-08 16:12:03 +08:00
|
|
|
case OMPD_parallel_sections:
|
2019-12-06 02:43:48 +08:00
|
|
|
case OMPD_parallel_master:
|
2014-07-22 18:10:35 +08:00
|
|
|
case OMPD_atomic:
|
2014-09-19 16:19:49 +08:00
|
|
|
case OMPD_target:
|
2014-10-09 12:18:56 +08:00
|
|
|
case OMPD_teams:
|
2015-07-01 14:57:41 +08:00
|
|
|
case OMPD_cancellation_point:
|
2015-07-02 19:25:17 +08:00
|
|
|
case OMPD_cancel:
|
2015-07-23 00:02:46 +08:00
|
|
|
case OMPD_target_data:
|
2016-01-20 03:15:56 +08:00
|
|
|
case OMPD_target_enter_data:
|
2016-01-20 04:04:50 +08:00
|
|
|
case OMPD_target_exit_data:
|
2016-01-27 02:48:41 +08:00
|
|
|
case OMPD_target_parallel:
|
2016-02-03 23:46:42 +08:00
|
|
|
case OMPD_target_parallel_for:
|
2015-12-01 12:18:41 +08:00
|
|
|
case OMPD_taskloop:
|
2015-12-03 17:40:15 +08:00
|
|
|
case OMPD_taskloop_simd:
|
2019-10-11 04:13:02 +08:00
|
|
|
case OMPD_master_taskloop:
|
2019-10-19 00:47:35 +08:00
|
|
|
case OMPD_master_taskloop_simd:
|
2019-10-15 01:17:41 +08:00
|
|
|
case OMPD_parallel_master_taskloop:
|
2019-10-25 22:27:13 +08:00
|
|
|
case OMPD_parallel_master_taskloop_simd:
|
2015-12-14 22:51:25 +08:00
|
|
|
case OMPD_distribute:
|
2016-04-06 19:38:59 +08:00
|
|
|
case OMPD_end_declare_target:
|
2016-05-27 01:30:50 +08:00
|
|
|
case OMPD_target_update:
|
2016-06-27 22:55:37 +08:00
|
|
|
case OMPD_distribute_parallel_for:
|
2016-07-05 13:00:15 +08:00
|
|
|
case OMPD_distribute_parallel_for_simd:
|
2016-07-06 12:45:38 +08:00
|
|
|
case OMPD_distribute_simd:
|
2016-07-14 10:54:56 +08:00
|
|
|
case OMPD_target_parallel_for_simd:
|
2016-07-21 06:57:10 +08:00
|
|
|
case OMPD_target_simd:
|
2016-08-05 22:37:37 +08:00
|
|
|
case OMPD_teams_distribute:
|
2016-10-25 20:50:55 +08:00
|
|
|
case OMPD_teams_distribute_simd:
|
2016-12-01 07:51:03 +08:00
|
|
|
case OMPD_teams_distribute_parallel_for_simd:
|
2016-12-09 11:24:30 +08:00
|
|
|
case OMPD_teams_distribute_parallel_for:
|
2016-12-17 13:48:59 +08:00
|
|
|
case OMPD_target_teams:
|
2016-12-25 12:52:54 +08:00
|
|
|
case OMPD_target_teams_distribute:
|
2016-12-30 06:16:30 +08:00
|
|
|
case OMPD_target_teams_distribute_parallel_for:
|
2017-01-03 13:23:48 +08:00
|
|
|
case OMPD_target_teams_distribute_parallel_for_simd:
|
2017-01-11 02:08:18 +08:00
|
|
|
case OMPD_target_teams_distribute_simd:
|
2013-03-22 14:34:35 +08:00
|
|
|
Diag(Tok, diag::err_omp_unexpected_directive)
|
2018-02-17 02:36:44 +08:00
|
|
|
<< 1 << getOpenMPDirectiveName(DKind);
|
2013-03-22 14:34:35 +08:00
|
|
|
break;
|
|
|
|
}
|
2016-03-03 13:21:39 +08:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
ConsumeAnyToken();
|
2016-01-16 07:43:25 +08:00
|
|
|
return nullptr;
|
2013-03-22 14:34:35 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parsing of declarative or executable OpenMP directives.
|
2013-07-19 11:13:43 +08:00
|
|
|
///
|
|
|
|
/// threadprivate-directive:
|
|
|
|
/// annot_pragma_openmp 'threadprivate' simple-variable-list
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2019-03-08 01:54:44 +08:00
|
|
|
/// allocate-directive:
|
|
|
|
/// annot_pragma_openmp 'allocate' simple-variable-list
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2016-03-03 13:21:39 +08:00
|
|
|
/// declare-reduction-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'reduction' '(' <reduction_id> ':'
|
|
|
|
/// <type> {',' <type>} ':' <expression> ')' ['initializer' '('
|
|
|
|
/// ('omp_priv' '=' <expression>|<function_call>) ')']
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2019-02-02 04:25:04 +08:00
|
|
|
/// declare-mapper-directive:
|
|
|
|
/// annot_pragma_openmp 'declare' 'mapper' '(' [<mapper-identifer> ':']
|
|
|
|
/// <type> <var> ')' [<clause>[[,] <clause>] ... ]
|
|
|
|
/// annot_pragma_openmp_end
|
|
|
|
///
|
2014-06-25 19:44:49 +08:00
|
|
|
/// executable-directive:
|
2014-06-26 20:05:45 +08:00
|
|
|
/// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' |
|
2014-07-21 17:42:05 +08:00
|
|
|
/// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] |
|
2019-12-06 02:43:48 +08:00
|
|
|
/// '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}
|
2019-10-25 22:27:13 +08:00
|
|
|
/// annot_pragma_openmp_end
|
2013-07-19 11:13:43 +08:00
|
|
|
///
|
2019-02-15 08:27:53 +08:00
|
|
|
StmtResult
|
|
|
|
Parser::ParseOpenMPDeclarativeOrExecutableDirective(ParsedStmtContext StmtCtx) {
|
2013-07-19 11:13:43 +08:00
|
|
|
assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!");
|
2019-12-14 05:05:30 +08:00
|
|
|
ParsingOpenMPDirectiveRAII DirScope(*this);
|
2013-11-18 16:17:37 +08:00
|
|
|
ParenBraceBracketBalancer BalancerRAIIObj(*this);
|
2013-07-19 11:13:43 +08:00
|
|
|
SmallVector<OMPClause *, 5> Clauses;
|
2014-05-12 12:23:46 +08:00
|
|
|
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>, OMPC_unknown + 1>
|
2014-05-28 14:15:33 +08:00
|
|
|
FirstClauses(OMPC_unknown + 1);
|
2017-08-10 23:43:06 +08:00
|
|
|
unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
|
|
|
|
Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
|
2017-05-19 03:21:48 +08:00
|
|
|
SourceLocation Loc = ConsumeAnnotationToken(), EndLoc;
|
2018-04-24 03:53:05 +08:00
|
|
|
OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
|
2015-07-01 14:57:41 +08:00
|
|
|
OpenMPDirectiveKind CancelRegion = OMPD_unknown;
|
2013-09-07 02:03:48 +08:00
|
|
|
// Name of critical directive.
|
|
|
|
DeclarationNameInfo DirName;
|
2013-07-19 11:13:43 +08:00
|
|
|
StmtResult Directive = StmtError();
|
2014-07-18 15:47:19 +08:00
|
|
|
bool HasAssociatedStatement = true;
|
2014-07-21 19:26:11 +08:00
|
|
|
bool FlushHasClause = false;
|
2013-07-19 11:13:43 +08:00
|
|
|
|
|
|
|
switch (DKind) {
|
2016-05-09 22:59:13 +08:00
|
|
|
case OMPD_threadprivate: {
|
2019-02-15 08:27:53 +08:00
|
|
|
// FIXME: Should this be permitted in C++?
|
|
|
|
if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
|
|
|
|
ParsedStmtContext()) {
|
2016-01-13 19:18:54 +08:00
|
|
|
Diag(Tok, diag::err_omp_immediate_directive)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << 0;
|
|
|
|
}
|
2013-07-19 11:13:43 +08:00
|
|
|
ConsumeToken();
|
2019-03-08 01:54:44 +08:00
|
|
|
DeclDirectiveListParserHelper Helper(this, DKind);
|
|
|
|
if (!ParseOpenMPSimpleVarList(DKind, Helper,
|
|
|
|
/*AllowScopeSpecifier=*/false)) {
|
2013-07-19 11:13:43 +08:00
|
|
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
|
|
|
// extra tokens.
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
2019-03-08 01:54:44 +08:00
|
|
|
<< getOpenMPDirectiveName(DKind);
|
2013-12-19 03:10:49 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
2016-05-09 22:59:13 +08:00
|
|
|
DeclGroupPtrTy Res = Actions.ActOnOpenMPThreadprivateDirective(
|
|
|
|
Loc, Helper.getIdentifiers());
|
2013-07-19 11:13:43 +08:00
|
|
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
|
|
|
}
|
2013-12-19 03:10:49 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
2013-07-19 11:13:43 +08:00
|
|
|
break;
|
2016-05-09 22:59:13 +08:00
|
|
|
}
|
2019-03-08 01:54:44 +08:00
|
|
|
case OMPD_allocate: {
|
|
|
|
// FIXME: Should this be permitted in C++?
|
|
|
|
if ((StmtCtx & ParsedStmtContext::AllowDeclarationsInC) ==
|
|
|
|
ParsedStmtContext()) {
|
|
|
|
Diag(Tok, diag::err_omp_immediate_directive)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << 0;
|
|
|
|
}
|
|
|
|
ConsumeToken();
|
|
|
|
DeclDirectiveListParserHelper Helper(this, DKind);
|
|
|
|
if (!ParseOpenMPSimpleVarList(DKind, Helper,
|
|
|
|
/*AllowScopeSpecifier=*/false)) {
|
2019-03-13 02:52:33 +08:00
|
|
|
SmallVector<OMPClause *, 1> Clauses;
|
2019-03-08 01:54:44 +08:00
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2019-03-13 02:52:33 +08:00
|
|
|
SmallVector<llvm::PointerIntPair<OMPClause *, 1, bool>,
|
|
|
|
OMPC_unknown + 1>
|
|
|
|
FirstClauses(OMPC_unknown + 1);
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
OpenMPClauseKind CKind =
|
|
|
|
Tok.isAnnotation() ? OMPC_unknown
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
|
|
|
Actions.StartOpenMPClause(CKind);
|
|
|
|
OMPClause *Clause = ParseOpenMPClause(OMPD_allocate, CKind,
|
|
|
|
!FirstClauses[CKind].getInt());
|
|
|
|
SkipUntil(tok::comma, tok::identifier, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
FirstClauses[CKind].setInt(true);
|
|
|
|
if (Clause != nullptr)
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
if (Tok.is(tok::annot_pragma_openmp_end)) {
|
|
|
|
Actions.EndOpenMPClause();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
|
|
|
Actions.EndOpenMPClause();
|
|
|
|
}
|
|
|
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
|
|
|
// extra tokens.
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
|
|
|
<< getOpenMPDirectiveName(DKind);
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
|
|
|
}
|
2019-03-08 01:54:44 +08:00
|
|
|
}
|
2019-03-13 02:52:33 +08:00
|
|
|
DeclGroupPtrTy Res = Actions.ActOnOpenMPAllocateDirective(
|
|
|
|
Loc, Helper.getIdentifiers(), Clauses);
|
2019-03-08 01:54:44 +08:00
|
|
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
|
|
|
}
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
break;
|
|
|
|
}
|
2016-03-03 13:21:39 +08:00
|
|
|
case OMPD_declare_reduction:
|
|
|
|
ConsumeToken();
|
2018-04-24 03:53:05 +08:00
|
|
|
if (DeclGroupPtrTy Res =
|
|
|
|
ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) {
|
2016-03-03 13:21:39 +08:00
|
|
|
// The last seen token is annot_pragma_openmp_end - need to check for
|
|
|
|
// extra tokens.
|
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
|
|
|
<< getOpenMPDirectiveName(OMPD_declare_reduction);
|
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
ConsumeAnyToken();
|
|
|
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
2018-04-24 03:53:05 +08:00
|
|
|
} else {
|
2016-03-03 13:21:39 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
2018-04-24 03:53:05 +08:00
|
|
|
}
|
2016-03-03 13:21:39 +08:00
|
|
|
break;
|
2019-02-02 04:25:04 +08:00
|
|
|
case OMPD_declare_mapper: {
|
|
|
|
ConsumeToken();
|
|
|
|
if (DeclGroupPtrTy Res =
|
|
|
|
ParseOpenMPDeclareMapperDirective(/*AS=*/AS_none)) {
|
|
|
|
// Skip the last annot_pragma_openmp_end.
|
|
|
|
ConsumeAnnotationToken();
|
|
|
|
Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation());
|
|
|
|
} else {
|
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2014-07-21 19:26:11 +08:00
|
|
|
case OMPD_flush:
|
|
|
|
if (PP.LookAhead(0).is(tok::l_paren)) {
|
|
|
|
FlushHasClause = true;
|
|
|
|
// Push copy of the current token back to stream to properly parse
|
|
|
|
// pseudo-clause OMPFlushClause.
|
2019-05-17 17:32:05 +08:00
|
|
|
PP.EnterToken(Tok, /*IsReinject*/ true);
|
2014-07-21 19:26:11 +08:00
|
|
|
}
|
2017-06-02 05:26:38 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2014-07-18 15:47:19 +08:00
|
|
|
case OMPD_taskyield:
|
2014-07-18 17:11:51 +08:00
|
|
|
case OMPD_barrier:
|
2014-07-18 18:17:07 +08:00
|
|
|
case OMPD_taskwait:
|
2015-07-01 14:57:41 +08:00
|
|
|
case OMPD_cancellation_point:
|
2015-07-02 19:25:17 +08:00
|
|
|
case OMPD_cancel:
|
2016-01-20 03:15:56 +08:00
|
|
|
case OMPD_target_enter_data:
|
2016-01-20 04:04:50 +08:00
|
|
|
case OMPD_target_exit_data:
|
2016-05-27 01:30:50 +08:00
|
|
|
case OMPD_target_update:
|
2019-02-15 08:27:53 +08:00
|
|
|
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
|
|
|
|
ParsedStmtContext()) {
|
2014-07-18 15:47:19 +08:00
|
|
|
Diag(Tok, diag::err_omp_immediate_directive)
|
2015-12-18 13:05:56 +08:00
|
|
|
<< getOpenMPDirectiveName(DKind) << 0;
|
2014-07-18 15:47:19 +08:00
|
|
|
}
|
|
|
|
HasAssociatedStatement = false;
|
2014-07-21 19:26:11 +08:00
|
|
|
// Fall through for further analysis.
|
2017-06-02 05:26:38 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2014-02-27 16:29:12 +08:00
|
|
|
case OMPD_parallel:
|
2014-06-18 12:14:57 +08:00
|
|
|
case OMPD_simd:
|
2014-06-25 19:44:49 +08:00
|
|
|
case OMPD_for:
|
2014-09-18 13:12:34 +08:00
|
|
|
case OMPD_for_simd:
|
2014-06-26 16:21:58 +08:00
|
|
|
case OMPD_sections:
|
2014-06-26 20:05:45 +08:00
|
|
|
case OMPD_single:
|
2014-07-07 21:01:15 +08:00
|
|
|
case OMPD_section:
|
2014-07-17 16:54:58 +08:00
|
|
|
case OMPD_master:
|
2014-07-21 17:42:05 +08:00
|
|
|
case OMPD_critical:
|
2014-07-08 16:12:03 +08:00
|
|
|
case OMPD_parallel_for:
|
2014-09-23 17:33:00 +08:00
|
|
|
case OMPD_parallel_for_simd:
|
2014-07-11 19:25:16 +08:00
|
|
|
case OMPD_parallel_sections:
|
2019-12-06 02:43:48 +08:00
|
|
|
case OMPD_parallel_master:
|
2014-07-22 14:45:04 +08:00
|
|
|
case OMPD_task:
|
2014-07-22 18:10:35 +08:00
|
|
|
case OMPD_ordered:
|
2014-09-19 16:19:49 +08:00
|
|
|
case OMPD_atomic:
|
2014-10-09 12:18:56 +08:00
|
|
|
case OMPD_target:
|
2015-06-18 20:14:09 +08:00
|
|
|
case OMPD_teams:
|
2015-07-21 21:44:28 +08:00
|
|
|
case OMPD_taskgroup:
|
2015-12-01 12:18:41 +08:00
|
|
|
case OMPD_target_data:
|
2016-01-27 02:48:41 +08:00
|
|
|
case OMPD_target_parallel:
|
2016-02-03 23:46:42 +08:00
|
|
|
case OMPD_target_parallel_for:
|
2015-12-03 17:40:15 +08:00
|
|
|
case OMPD_taskloop:
|
2015-12-14 22:51:25 +08:00
|
|
|
case OMPD_taskloop_simd:
|
2019-10-11 04:13:02 +08:00
|
|
|
case OMPD_master_taskloop:
|
2019-10-19 00:47:35 +08:00
|
|
|
case OMPD_master_taskloop_simd:
|
2019-10-15 01:17:41 +08:00
|
|
|
case OMPD_parallel_master_taskloop:
|
2019-10-25 22:27:13 +08:00
|
|
|
case OMPD_parallel_master_taskloop_simd:
|
2016-06-27 22:55:37 +08:00
|
|
|
case OMPD_distribute:
|
2016-07-05 13:00:15 +08:00
|
|
|
case OMPD_distribute_parallel_for:
|
2016-07-06 12:45:38 +08:00
|
|
|
case OMPD_distribute_parallel_for_simd:
|
2016-07-14 10:54:56 +08:00
|
|
|
case OMPD_distribute_simd:
|
2016-07-21 06:57:10 +08:00
|
|
|
case OMPD_target_parallel_for_simd:
|
2016-08-05 22:37:37 +08:00
|
|
|
case OMPD_target_simd:
|
2016-10-25 20:50:55 +08:00
|
|
|
case OMPD_teams_distribute:
|
2016-12-01 07:51:03 +08:00
|
|
|
case OMPD_teams_distribute_simd:
|
2016-12-09 11:24:30 +08:00
|
|
|
case OMPD_teams_distribute_parallel_for_simd:
|
2016-12-17 13:48:59 +08:00
|
|
|
case OMPD_teams_distribute_parallel_for:
|
2016-12-25 12:52:54 +08:00
|
|
|
case OMPD_target_teams:
|
2016-12-30 06:16:30 +08:00
|
|
|
case OMPD_target_teams_distribute:
|
2017-01-03 13:23:48 +08:00
|
|
|
case OMPD_target_teams_distribute_parallel_for:
|
2017-01-11 02:08:18 +08:00
|
|
|
case OMPD_target_teams_distribute_parallel_for_simd:
|
|
|
|
case OMPD_target_teams_distribute_simd: {
|
2013-07-19 11:13:43 +08:00
|
|
|
ConsumeToken();
|
2014-07-21 17:42:05 +08:00
|
|
|
// Parse directive name of the 'critical' directive if any.
|
|
|
|
if (DKind == OMPD_critical) {
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
|
|
|
if (!T.consumeOpen()) {
|
|
|
|
if (Tok.isAnyIdentifier()) {
|
|
|
|
DirName =
|
|
|
|
DeclarationNameInfo(Tok.getIdentifierInfo(), Tok.getLocation());
|
|
|
|
ConsumeAnyToken();
|
|
|
|
} else {
|
|
|
|
Diag(Tok, diag::err_omp_expected_identifier_for_critical);
|
|
|
|
}
|
|
|
|
T.consumeClose();
|
|
|
|
}
|
2015-07-02 19:25:17 +08:00
|
|
|
} else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) {
|
2018-04-24 03:53:05 +08:00
|
|
|
CancelRegion = parseOpenMPDirectiveKind(*this);
|
2015-07-01 14:57:41 +08:00
|
|
|
if (Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeToken();
|
2014-07-21 17:42:05 +08:00
|
|
|
}
|
2013-09-07 02:03:48 +08:00
|
|
|
|
2014-06-18 12:14:57 +08:00
|
|
|
if (isOpenMPLoopDirective(DKind))
|
|
|
|
ScopeFlags |= Scope::OpenMPLoopDirectiveScope;
|
|
|
|
if (isOpenMPSimdDirective(DKind))
|
|
|
|
ScopeFlags |= Scope::OpenMPSimdDirectiveScope;
|
|
|
|
ParseScope OMPDirectiveScope(this, ScopeFlags);
|
2014-06-27 18:37:06 +08:00
|
|
|
Actions.StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(), Loc);
|
2013-09-07 02:03:48 +08:00
|
|
|
|
2013-07-19 11:13:43 +08:00
|
|
|
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2014-07-21 19:26:11 +08:00
|
|
|
OpenMPClauseKind CKind =
|
|
|
|
Tok.isAnnotation()
|
|
|
|
? OMPC_unknown
|
|
|
|
: FlushHasClause ? OMPC_flush
|
|
|
|
: getOpenMPClauseKind(PP.getSpelling(Tok));
|
2015-06-23 12:51:00 +08:00
|
|
|
Actions.StartOpenMPClause(CKind);
|
2014-07-21 19:26:11 +08:00
|
|
|
FlushHasClause = false;
|
2014-05-28 14:15:33 +08:00
|
|
|
OMPClause *Clause =
|
|
|
|
ParseOpenMPClause(DKind, CKind, !FirstClauses[CKind].getInt());
|
2013-07-19 11:13:43 +08:00
|
|
|
FirstClauses[CKind].setInt(true);
|
|
|
|
if (Clause) {
|
|
|
|
FirstClauses[CKind].setPointer(Clause);
|
|
|
|
Clauses.push_back(Clause);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Skip ',' if any.
|
|
|
|
if (Tok.is(tok::comma))
|
|
|
|
ConsumeToken();
|
2015-06-23 12:51:00 +08:00
|
|
|
Actions.EndOpenMPClause();
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
|
|
|
// End location of the directive.
|
|
|
|
EndLoc = Tok.getLocation();
|
|
|
|
// Consume final annot_pragma_openmp_end.
|
2017-05-19 03:21:48 +08:00
|
|
|
ConsumeAnnotationToken();
|
2013-07-19 11:13:43 +08:00
|
|
|
|
2015-12-18 13:05:56 +08:00
|
|
|
// OpenMP [2.13.8, ordered Construct, Syntax]
|
|
|
|
// If the depend clause is specified, the ordered construct is a stand-alone
|
|
|
|
// directive.
|
|
|
|
if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) {
|
2019-02-15 08:27:53 +08:00
|
|
|
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
|
|
|
|
ParsedStmtContext()) {
|
2015-12-18 13:05:56 +08:00
|
|
|
Diag(Loc, diag::err_omp_immediate_directive)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << 1
|
|
|
|
<< getOpenMPClauseName(OMPC_depend);
|
|
|
|
}
|
|
|
|
HasAssociatedStatement = false;
|
|
|
|
}
|
|
|
|
|
2013-07-19 11:13:43 +08:00
|
|
|
StmtResult AssociatedStmt;
|
2014-07-18 15:47:19 +08:00
|
|
|
if (HasAssociatedStatement) {
|
2013-07-19 11:13:43 +08:00
|
|
|
// The body is a block scope like in Lambdas and Blocks.
|
2014-06-27 18:37:06 +08:00
|
|
|
Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
|
2018-02-03 08:44:57 +08:00
|
|
|
// FIXME: We create a bogus CompoundStmt scope to hold the contents of
|
|
|
|
// the captured region. Code elsewhere assumes that any FunctionScopeInfo
|
|
|
|
// should have at least one compound statement scope within it.
|
|
|
|
AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());
|
2015-04-02 15:48:16 +08:00
|
|
|
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
|
2017-11-22 01:08:48 +08:00
|
|
|
} else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data ||
|
|
|
|
DKind == OMPD_target_exit_data) {
|
|
|
|
Actions.ActOnOpenMPRegionStart(DKind, getCurScope());
|
2018-02-03 08:44:57 +08:00
|
|
|
AssociatedStmt = (Sema::CompoundScopeRAII(Actions),
|
|
|
|
Actions.ActOnCompoundStmt(Loc, Loc, llvm::None,
|
|
|
|
/*isStmtExpr=*/false));
|
2017-11-22 01:08:48 +08:00
|
|
|
AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
2015-09-03 15:23:48 +08:00
|
|
|
Directive = Actions.ActOnOpenMPExecutableDirective(
|
|
|
|
DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc,
|
|
|
|
EndLoc);
|
2013-07-19 11:13:43 +08:00
|
|
|
|
|
|
|
// Exit scope.
|
2013-09-07 02:03:48 +08:00
|
|
|
Actions.EndOpenMPDSABlock(Directive.get());
|
2013-07-19 11:13:43 +08:00
|
|
|
OMPDirectiveScope.Exit();
|
|
|
|
break;
|
2014-05-28 14:15:33 +08:00
|
|
|
}
|
2016-03-30 18:43:55 +08:00
|
|
|
case OMPD_declare_simd:
|
2016-04-06 19:38:59 +08:00
|
|
|
case OMPD_declare_target:
|
|
|
|
case OMPD_end_declare_target:
|
2018-09-26 12:28:39 +08:00
|
|
|
case OMPD_requires:
|
2019-09-14 04:18:17 +08:00
|
|
|
case OMPD_declare_variant:
|
2016-03-30 18:43:55 +08:00
|
|
|
Diag(Tok, diag::err_omp_unexpected_directive)
|
2018-02-17 02:36:44 +08:00
|
|
|
<< 1 << getOpenMPDirectiveName(DKind);
|
2016-03-30 18:43:55 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
|
|
|
break;
|
2013-07-19 11:13:43 +08:00
|
|
|
case OMPD_unknown:
|
|
|
|
Diag(Tok, diag::err_omp_unknown_directive);
|
2013-12-19 03:10:49 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end);
|
2013-07-19 11:13:43 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return Directive;
|
|
|
|
}
|
|
|
|
|
2016-05-09 22:59:13 +08:00
|
|
|
// Parses simple list:
|
|
|
|
// simple-variable-list:
|
|
|
|
// '(' id-expression {, id-expression} ')'
|
|
|
|
//
|
|
|
|
bool Parser::ParseOpenMPSimpleVarList(
|
|
|
|
OpenMPDirectiveKind Kind,
|
|
|
|
const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> &
|
|
|
|
Callback,
|
|
|
|
bool AllowScopeSpecifier) {
|
2013-03-22 14:34:35 +08:00
|
|
|
// Parse '('.
|
2013-12-19 03:10:49 +08:00
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
2013-07-19 11:13:43 +08:00
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
getOpenMPDirectiveName(Kind).data()))
|
2013-07-19 11:13:43 +08:00
|
|
|
return true;
|
|
|
|
bool IsCorrect = true;
|
2013-05-13 12:18:18 +08:00
|
|
|
bool NoIdentIsFound = true;
|
2013-03-22 14:34:35 +08:00
|
|
|
|
|
|
|
// Read tokens while ')' or annot_pragma_openmp_end is not found.
|
2013-05-13 12:18:18 +08:00
|
|
|
while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2013-03-22 14:34:35 +08:00
|
|
|
CXXScopeSpec SS;
|
|
|
|
UnqualifiedId Name;
|
|
|
|
// Read var name.
|
|
|
|
Token PrevTok = Tok;
|
2013-05-13 12:18:18 +08:00
|
|
|
NoIdentIsFound = false;
|
2013-03-22 14:34:35 +08:00
|
|
|
|
2013-05-13 12:18:18 +08:00
|
|
|
if (AllowScopeSpecifier && getLangOpts().CPlusPlus &&
|
2016-01-16 07:43:34 +08:00
|
|
|
ParseOptionalCXXScopeSpecifier(SS, nullptr, false)) {
|
2013-03-22 14:34:35 +08:00
|
|
|
IsCorrect = false;
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
2013-12-19 03:10:49 +08:00
|
|
|
StopBeforeMatch);
|
2017-02-07 09:37:30 +08:00
|
|
|
} else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr,
|
2018-04-27 10:00:13 +08:00
|
|
|
nullptr, Name)) {
|
2013-05-13 12:18:18 +08:00
|
|
|
IsCorrect = false;
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
2013-12-19 03:10:49 +08:00
|
|
|
StopBeforeMatch);
|
2013-05-13 12:18:18 +08:00
|
|
|
} else if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end)) {
|
2013-03-22 14:34:35 +08:00
|
|
|
IsCorrect = false;
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
2013-12-19 03:10:49 +08:00
|
|
|
StopBeforeMatch);
|
2013-12-24 17:48:30 +08:00
|
|
|
Diag(PrevTok.getLocation(), diag::err_expected)
|
|
|
|
<< tok::identifier
|
|
|
|
<< SourceRange(PrevTok.getLocation(), PrevTokLocation);
|
2013-03-22 14:34:35 +08:00
|
|
|
} else {
|
2016-05-09 22:59:13 +08:00
|
|
|
Callback(SS, Actions.GetNameFromUnqualifiedId(Name));
|
2013-03-22 14:34:35 +08:00
|
|
|
}
|
|
|
|
// Consume ','.
|
|
|
|
if (Tok.is(tok::comma)) {
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
2013-05-13 12:18:18 +08:00
|
|
|
}
|
2013-03-22 14:34:35 +08:00
|
|
|
|
2013-05-13 12:18:18 +08:00
|
|
|
if (NoIdentIsFound) {
|
2013-12-24 17:48:30 +08:00
|
|
|
Diag(Tok, diag::err_expected) << tok::identifier;
|
2013-05-13 12:18:18 +08:00
|
|
|
IsCorrect = false;
|
2013-03-22 14:34:35 +08:00
|
|
|
}
|
|
|
|
|
2013-05-13 12:18:18 +08:00
|
|
|
// Parse ')'.
|
2013-07-19 11:13:43 +08:00
|
|
|
IsCorrect = !T.consumeClose() && IsCorrect;
|
2013-05-13 12:18:18 +08:00
|
|
|
|
2016-05-09 22:59:13 +08:00
|
|
|
return !IsCorrect;
|
2013-03-22 14:34:35 +08:00
|
|
|
}
|
2013-07-19 11:13:43 +08:00
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parsing of OpenMP clauses.
|
2013-07-19 11:13:43 +08:00
|
|
|
///
|
|
|
|
/// clause:
|
2014-07-17 15:32:53 +08:00
|
|
|
/// if-clause | final-clause | num_threads-clause | safelen-clause |
|
|
|
|
/// default-clause | private-clause | firstprivate-clause | shared-clause
|
|
|
|
/// | linear-clause | aligned-clause | collapse-clause |
|
|
|
|
/// lastprivate-clause | reduction-clause | proc_bind-clause |
|
2014-07-17 20:47:03 +08:00
|
|
|
/// schedule-clause | copyin-clause | copyprivate-clause | untied-clause |
|
2014-07-23 18:25:33 +08:00
|
|
|
/// mergeable-clause | flush-clause | read-clause | write-clause |
|
2015-08-21 19:14:16 +08:00
|
|
|
/// update-clause | capture-clause | seq_cst-clause | device-clause |
|
2015-11-28 02:47:36 +08:00
|
|
|
/// simdlen-clause | threads-clause | simd-clause | num_teams-clause |
|
2015-12-07 20:52:51 +08:00
|
|
|
/// thread_limit-clause | priority-clause | grainsize-clause |
|
2016-05-27 01:49:04 +08:00
|
|
|
/// nogroup-clause | num_tasks-clause | hint-clause | to-clause |
|
2017-07-22 02:48:21 +08:00
|
|
|
/// from-clause | is_device_ptr-clause | task_reduction-clause |
|
2019-03-27 22:14:31 +08:00
|
|
|
/// in_reduction-clause | allocator-clause | allocate-clause
|
2013-07-19 11:13:43 +08:00
|
|
|
///
|
|
|
|
OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
|
|
|
OpenMPClauseKind CKind, bool FirstClause) {
|
2014-05-21 14:02:52 +08:00
|
|
|
OMPClause *Clause = nullptr;
|
2013-07-19 11:13:43 +08:00
|
|
|
bool ErrorFound = false;
|
2018-01-10 03:21:04 +08:00
|
|
|
bool WrongDirective = false;
|
2013-07-19 11:13:43 +08:00
|
|
|
// Check if clause is allowed for the given directive.
|
2019-11-20 01:07:54 +08:00
|
|
|
if (CKind != OMPC_unknown &&
|
|
|
|
!isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
|
2014-05-28 14:15:33 +08:00
|
|
|
Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind)
|
|
|
|
<< getOpenMPDirectiveName(DKind);
|
2013-07-19 11:13:43 +08:00
|
|
|
ErrorFound = true;
|
2018-01-10 03:21:04 +08:00
|
|
|
WrongDirective = true;
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (CKind) {
|
2014-07-17 15:32:53 +08:00
|
|
|
case OMPC_final:
|
2014-03-06 14:15:19 +08:00
|
|
|
case OMPC_num_threads:
|
2014-03-21 12:51:18 +08:00
|
|
|
case OMPC_safelen:
|
2015-08-21 19:14:16 +08:00
|
|
|
case OMPC_simdlen:
|
2014-05-27 23:12:19 +08:00
|
|
|
case OMPC_collapse:
|
2015-07-30 19:36:16 +08:00
|
|
|
case OMPC_ordered:
|
2015-08-08 00:16:36 +08:00
|
|
|
case OMPC_device:
|
2015-11-25 04:50:12 +08:00
|
|
|
case OMPC_num_teams:
|
2015-11-28 02:47:36 +08:00
|
|
|
case OMPC_thread_limit:
|
2015-12-01 18:17:31 +08:00
|
|
|
case OMPC_priority:
|
2015-12-07 20:52:51 +08:00
|
|
|
case OMPC_grainsize:
|
2015-12-08 20:06:20 +08:00
|
|
|
case OMPC_num_tasks:
|
2015-12-15 16:19:24 +08:00
|
|
|
case OMPC_hint:
|
2019-03-13 02:52:33 +08:00
|
|
|
case OMPC_allocator:
|
2014-02-13 13:29:23 +08:00
|
|
|
// OpenMP [2.5, Restrictions]
|
2014-03-06 14:15:19 +08:00
|
|
|
// At most one num_threads clause can appear on the directive.
|
2014-03-21 12:51:18 +08:00
|
|
|
// OpenMP [2.8.1, simd construct, Restrictions]
|
2014-05-27 23:12:19 +08:00
|
|
|
// Only one safelen clause can appear on a simd directive.
|
2015-08-21 19:14:16 +08:00
|
|
|
// Only one simdlen clause can appear on a simd directive.
|
2014-05-27 23:12:19 +08:00
|
|
|
// Only one collapse clause can appear on a simd directive.
|
2015-08-08 00:16:36 +08:00
|
|
|
// OpenMP [2.9.1, target data construct, Restrictions]
|
|
|
|
// At most one device clause can appear on the directive.
|
2014-07-17 15:32:53 +08:00
|
|
|
// OpenMP [2.11.1, task Construct, Restrictions]
|
|
|
|
// At most one if clause can appear on the directive.
|
|
|
|
// At most one final clause can appear on the directive.
|
2015-11-25 04:50:12 +08:00
|
|
|
// OpenMP [teams Construct, Restrictions]
|
|
|
|
// At most one num_teams clause can appear on the directive.
|
2015-11-28 02:47:36 +08:00
|
|
|
// At most one thread_limit clause can appear on the directive.
|
2015-12-01 18:17:31 +08:00
|
|
|
// OpenMP [2.9.1, task Construct, Restrictions]
|
|
|
|
// At most one priority clause can appear on the directive.
|
2015-12-07 20:52:51 +08:00
|
|
|
// OpenMP [2.9.2, taskloop Construct, Restrictions]
|
|
|
|
// At most one grainsize clause can appear on the directive.
|
2015-12-08 20:06:20 +08:00
|
|
|
// OpenMP [2.9.2, taskloop Construct, Restrictions]
|
|
|
|
// At most one num_tasks clause can appear on the directive.
|
2019-03-13 02:52:33 +08:00
|
|
|
// OpenMP [2.11.3, allocate Directive, Restrictions]
|
|
|
|
// At most one allocator clause can appear on the directive.
|
2014-02-13 13:29:23 +08:00
|
|
|
if (!FirstClause) {
|
2015-09-03 15:23:48 +08:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
2014-07-23 15:46:59 +08:00
|
|
|
ErrorFound = true;
|
2014-02-13 13:29:23 +08:00
|
|
|
}
|
|
|
|
|
2015-07-30 19:36:16 +08:00
|
|
|
if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren))
|
2018-01-10 03:21:04 +08:00
|
|
|
Clause = ParseOpenMPClause(CKind, WrongDirective);
|
2015-07-30 19:36:16 +08:00
|
|
|
else
|
2018-01-10 03:21:04 +08:00
|
|
|
Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
|
2014-02-13 13:29:23 +08:00
|
|
|
break;
|
2013-07-19 11:13:43 +08:00
|
|
|
case OMPC_default:
|
2014-05-06 14:04:14 +08:00
|
|
|
case OMPC_proc_bind:
|
2018-11-02 20:18:11 +08:00
|
|
|
case OMPC_atomic_default_mem_order:
|
2014-02-13 13:29:23 +08:00
|
|
|
// OpenMP [2.14.3.1, Restrictions]
|
|
|
|
// Only a single default clause may be specified on a parallel, task or
|
|
|
|
// teams directive.
|
2014-05-06 14:04:14 +08:00
|
|
|
// OpenMP [2.5, parallel Construct, Restrictions]
|
|
|
|
// At most one proc_bind clause can appear on the directive.
|
2018-11-02 20:18:11 +08:00
|
|
|
// OpenMP [5.0, Requires directive, Restrictions]
|
|
|
|
// At most one atomic_default_mem_order clause can appear
|
|
|
|
// on the directive
|
2013-07-19 11:13:43 +08:00
|
|
|
if (!FirstClause) {
|
2015-09-03 15:23:48 +08:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
2014-07-23 15:46:59 +08:00
|
|
|
ErrorFound = true;
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
|
|
|
|
2018-01-10 03:21:04 +08:00
|
|
|
Clause = ParseOpenMPSimpleClause(CKind, WrongDirective);
|
2013-07-19 11:13:43 +08:00
|
|
|
break;
|
2014-06-20 15:16:17 +08:00
|
|
|
case OMPC_schedule:
|
2016-01-16 02:50:31 +08:00
|
|
|
case OMPC_dist_schedule:
|
2016-01-27 00:37:23 +08:00
|
|
|
case OMPC_defaultmap:
|
2014-06-20 15:16:17 +08:00
|
|
|
// OpenMP [2.7.1, Restrictions, p. 3]
|
|
|
|
// Only one schedule clause can appear on a loop directive.
|
2019-11-16 02:02:06 +08:00
|
|
|
// OpenMP 4.5 [2.10.4, Restrictions, p. 106]
|
2016-01-27 00:37:23 +08:00
|
|
|
// At most one defaultmap clause can appear on the directive.
|
2019-11-16 02:02:06 +08:00
|
|
|
if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
|
|
|
|
!FirstClause) {
|
2015-09-03 15:23:48 +08:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
2014-07-23 15:46:59 +08:00
|
|
|
ErrorFound = true;
|
2014-06-20 15:16:17 +08:00
|
|
|
}
|
2017-06-02 05:26:38 +08:00
|
|
|
LLVM_FALLTHROUGH;
|
2015-09-03 15:23:48 +08:00
|
|
|
case OMPC_if:
|
2018-01-10 03:21:04 +08:00
|
|
|
Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective);
|
2014-06-20 15:16:17 +08:00
|
|
|
break;
|
2014-06-20 19:19:47 +08:00
|
|
|
case OMPC_nowait:
|
2014-07-17 20:19:31 +08:00
|
|
|
case OMPC_untied:
|
2014-07-17 20:47:03 +08:00
|
|
|
case OMPC_mergeable:
|
2014-07-23 10:27:21 +08:00
|
|
|
case OMPC_read:
|
2014-07-23 15:46:59 +08:00
|
|
|
case OMPC_write:
|
2014-07-23 18:25:33 +08:00
|
|
|
case OMPC_update:
|
2014-07-24 14:46:57 +08:00
|
|
|
case OMPC_capture:
|
2014-07-24 16:55:34 +08:00
|
|
|
case OMPC_seq_cst:
|
2015-09-25 18:37:12 +08:00
|
|
|
case OMPC_threads:
|
2015-09-28 14:39:35 +08:00
|
|
|
case OMPC_simd:
|
2015-12-07 18:51:44 +08:00
|
|
|
case OMPC_nogroup:
|
2018-09-26 12:28:39 +08:00
|
|
|
case OMPC_unified_address:
|
2018-10-01 21:47:43 +08:00
|
|
|
case OMPC_unified_shared_memory:
|
2018-10-04 04:07:58 +08:00
|
|
|
case OMPC_reverse_offload:
|
2018-10-11 22:41:10 +08:00
|
|
|
case OMPC_dynamic_allocators:
|
2014-06-20 17:44:06 +08:00
|
|
|
// OpenMP [2.7.1, Restrictions, p. 9]
|
|
|
|
// Only one ordered clause can appear on a loop directive.
|
2014-06-20 19:19:47 +08:00
|
|
|
// OpenMP [2.7.1, Restrictions, C/C++, p. 4]
|
|
|
|
// Only one nowait clause can appear on a for directive.
|
2018-09-26 12:28:39 +08:00
|
|
|
// OpenMP [5.0, Requires directive, Restrictions]
|
|
|
|
// Each of the requires clauses can appear at most once on the directive.
|
2014-06-20 17:44:06 +08:00
|
|
|
if (!FirstClause) {
|
2015-09-03 15:23:48 +08:00
|
|
|
Diag(Tok, diag::err_omp_more_one_clause)
|
|
|
|
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
|
2014-07-23 15:46:59 +08:00
|
|
|
ErrorFound = true;
|
2014-06-20 17:44:06 +08:00
|
|
|
}
|
|
|
|
|
2018-01-10 03:21:04 +08:00
|
|
|
Clause = ParseOpenMPClause(CKind, WrongDirective);
|
2014-06-20 17:44:06 +08:00
|
|
|
break;
|
2013-07-19 11:13:43 +08:00
|
|
|
case OMPC_private:
|
2013-10-01 13:32:34 +08:00
|
|
|
case OMPC_firstprivate:
|
2014-06-04 21:06:39 +08:00
|
|
|
case OMPC_lastprivate:
|
2013-09-07 02:03:48 +08:00
|
|
|
case OMPC_shared:
|
2014-06-16 15:08:35 +08:00
|
|
|
case OMPC_reduction:
|
2017-07-19 04:17:46 +08:00
|
|
|
case OMPC_task_reduction:
|
2017-07-22 02:48:21 +08:00
|
|
|
case OMPC_in_reduction:
|
2014-04-22 21:09:42 +08:00
|
|
|
case OMPC_linear:
|
2014-05-29 22:36:25 +08:00
|
|
|
case OMPC_aligned:
|
2014-03-31 11:36:38 +08:00
|
|
|
case OMPC_copyin:
|
2014-06-27 18:37:06 +08:00
|
|
|
case OMPC_copyprivate:
|
2014-07-21 19:26:11 +08:00
|
|
|
case OMPC_flush:
|
2015-06-23 22:25:19 +08:00
|
|
|
case OMPC_depend:
|
2015-11-23 13:32:03 +08:00
|
|
|
case OMPC_map:
|
2016-05-27 01:39:58 +08:00
|
|
|
case OMPC_to:
|
2016-05-27 01:49:04 +08:00
|
|
|
case OMPC_from:
|
2016-07-13 23:37:16 +08:00
|
|
|
case OMPC_use_device_ptr:
|
2016-07-14 01:16:49 +08:00
|
|
|
case OMPC_is_device_ptr:
|
2019-03-27 22:14:31 +08:00
|
|
|
case OMPC_allocate:
|
2019-12-17 04:54:17 +08:00
|
|
|
case OMPC_nontemporal:
|
2018-01-10 03:21:04 +08:00
|
|
|
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
|
2013-07-19 11:13:43 +08:00
|
|
|
break;
|
2019-08-24 00:11:14 +08:00
|
|
|
case OMPC_device_type:
|
2013-07-19 11:13:43 +08:00
|
|
|
case OMPC_unknown:
|
|
|
|
Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
|
2014-05-28 14:15:33 +08:00
|
|
|
<< getOpenMPDirectiveName(DKind);
|
2013-12-19 03:10:49 +08:00
|
|
|
SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
|
2013-07-19 11:13:43 +08:00
|
|
|
break;
|
|
|
|
case OMPC_threadprivate:
|
2016-04-12 13:28:34 +08:00
|
|
|
case OMPC_uniform:
|
2019-09-24 02:13:31 +08:00
|
|
|
case OMPC_match:
|
2018-01-10 03:21:04 +08:00
|
|
|
if (!WrongDirective)
|
|
|
|
Diag(Tok, diag::err_omp_unexpected_clause)
|
|
|
|
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
|
2013-12-19 03:10:49 +08:00
|
|
|
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
2013-07-19 11:13:43 +08:00
|
|
|
break;
|
|
|
|
}
|
2014-05-21 14:02:52 +08:00
|
|
|
return ErrorFound ? nullptr : Clause;
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
|
|
|
|
2016-04-07 20:45:37 +08:00
|
|
|
/// Parses simple expression in parens for single-expression clauses of OpenMP
|
|
|
|
/// constructs.
|
|
|
|
/// \param RLoc Returned location of right paren.
|
|
|
|
ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
|
2019-09-14 04:18:17 +08:00
|
|
|
SourceLocation &RLoc,
|
|
|
|
bool IsAddressOfOperand) {
|
2016-04-07 20:45:37 +08:00
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after, ClauseName.data()))
|
|
|
|
return ExprError();
|
|
|
|
|
|
|
|
SourceLocation ELoc = Tok.getLocation();
|
|
|
|
ExprResult LHS(ParseCastExpression(
|
2019-09-14 04:18:17 +08:00
|
|
|
/*isUnaryExpression=*/false, IsAddressOfOperand, NotTypeCast));
|
2016-04-07 20:45:37 +08:00
|
|
|
ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional));
|
2019-01-05 00:58:14 +08:00
|
|
|
Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
|
2016-04-07 20:45:37 +08:00
|
|
|
|
|
|
|
// Parse ')'.
|
2018-07-07 03:35:42 +08:00
|
|
|
RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
2016-04-07 20:45:37 +08:00
|
|
|
|
|
|
|
return Val;
|
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parsing of OpenMP clauses with single expressions like 'final',
|
2015-12-01 18:17:31 +08:00
|
|
|
/// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams',
|
2015-12-15 16:19:24 +08:00
|
|
|
/// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'.
|
2014-02-13 13:29:23 +08:00
|
|
|
///
|
2014-07-17 15:32:53 +08:00
|
|
|
/// final-clause:
|
|
|
|
/// 'final' '(' expression ')'
|
|
|
|
///
|
2014-03-21 12:51:18 +08:00
|
|
|
/// num_threads-clause:
|
|
|
|
/// 'num_threads' '(' expression ')'
|
|
|
|
///
|
|
|
|
/// safelen-clause:
|
|
|
|
/// 'safelen' '(' expression ')'
|
|
|
|
///
|
2015-08-21 19:14:16 +08:00
|
|
|
/// simdlen-clause:
|
|
|
|
/// 'simdlen' '(' expression ')'
|
|
|
|
///
|
2014-05-27 23:12:19 +08:00
|
|
|
/// collapse-clause:
|
|
|
|
/// 'collapse' '(' expression ')'
|
|
|
|
///
|
2015-12-01 18:17:31 +08:00
|
|
|
/// priority-clause:
|
|
|
|
/// 'priority' '(' expression ')'
|
|
|
|
///
|
2015-12-07 20:52:51 +08:00
|
|
|
/// grainsize-clause:
|
|
|
|
/// 'grainsize' '(' expression ')'
|
|
|
|
///
|
2015-12-08 20:06:20 +08:00
|
|
|
/// num_tasks-clause:
|
|
|
|
/// 'num_tasks' '(' expression ')'
|
|
|
|
///
|
2015-12-15 16:19:24 +08:00
|
|
|
/// hint-clause:
|
|
|
|
/// 'hint' '(' expression ')'
|
|
|
|
///
|
2019-03-13 02:52:33 +08:00
|
|
|
/// allocator-clause:
|
|
|
|
/// 'allocator' '(' expression ')'
|
|
|
|
///
|
2018-01-10 03:21:04 +08:00
|
|
|
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
|
|
|
|
bool ParseOnly) {
|
2014-02-13 13:29:23 +08:00
|
|
|
SourceLocation Loc = ConsumeToken();
|
2016-04-07 20:45:37 +08:00
|
|
|
SourceLocation LLoc = Tok.getLocation();
|
|
|
|
SourceLocation RLoc;
|
2014-02-13 13:29:23 +08:00
|
|
|
|
2016-04-07 20:45:37 +08:00
|
|
|
ExprResult Val = ParseOpenMPParensExpr(getOpenMPClauseName(Kind), RLoc);
|
2014-02-13 13:29:23 +08:00
|
|
|
|
|
|
|
if (Val.isInvalid())
|
2014-05-21 14:02:52 +08:00
|
|
|
return nullptr;
|
2014-02-13 13:29:23 +08:00
|
|
|
|
2018-01-10 03:21:04 +08:00
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
2016-04-07 20:45:37 +08:00
|
|
|
return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc);
|
2014-02-13 13:29:23 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'.
|
2013-07-19 11:13:43 +08:00
|
|
|
///
|
|
|
|
/// default-clause:
|
|
|
|
/// 'default' '(' 'none' | 'shared' ')
|
|
|
|
///
|
2014-05-06 14:04:14 +08:00
|
|
|
/// proc_bind-clause:
|
|
|
|
/// 'proc_bind' '(' 'master' | 'close' | 'spread' ')
|
|
|
|
///
|
2018-01-10 03:21:04 +08:00
|
|
|
OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind,
|
|
|
|
bool ParseOnly) {
|
2019-08-24 00:11:14 +08:00
|
|
|
llvm::Optional<SimpleClauseData> Val = parseOpenMPSimpleClause(*this, Kind);
|
|
|
|
if (!Val || ParseOnly)
|
2018-01-10 03:21:04 +08:00
|
|
|
return nullptr;
|
2019-08-24 00:11:14 +08:00
|
|
|
return Actions.ActOnOpenMPSimpleClause(
|
|
|
|
Kind, Val.getValue().Type, Val.getValue().TypeLoc, Val.getValue().LOpen,
|
|
|
|
Val.getValue().Loc, Val.getValue().RLoc);
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parsing of OpenMP clauses like 'ordered'.
|
2014-06-20 17:44:06 +08:00
|
|
|
///
|
|
|
|
/// ordered-clause:
|
|
|
|
/// 'ordered'
|
|
|
|
///
|
2014-06-20 19:19:47 +08:00
|
|
|
/// nowait-clause:
|
|
|
|
/// 'nowait'
|
|
|
|
///
|
2014-07-17 20:19:31 +08:00
|
|
|
/// untied-clause:
|
|
|
|
/// 'untied'
|
|
|
|
///
|
2014-07-17 20:47:03 +08:00
|
|
|
/// mergeable-clause:
|
|
|
|
/// 'mergeable'
|
|
|
|
///
|
2014-07-23 10:27:21 +08:00
|
|
|
/// read-clause:
|
|
|
|
/// 'read'
|
|
|
|
///
|
2015-09-25 18:37:12 +08:00
|
|
|
/// threads-clause:
|
|
|
|
/// 'threads'
|
|
|
|
///
|
2015-09-28 14:39:35 +08:00
|
|
|
/// simd-clause:
|
|
|
|
/// 'simd'
|
|
|
|
///
|
2015-12-07 18:51:44 +08:00
|
|
|
/// nogroup-clause:
|
|
|
|
/// 'nogroup'
|
|
|
|
///
|
2018-01-10 03:21:04 +08:00
|
|
|
OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) {
|
2014-06-20 17:44:06 +08:00
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
ConsumeAnyToken();
|
|
|
|
|
2018-01-10 03:21:04 +08:00
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
2014-06-20 17:44:06 +08:00
|
|
|
return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parsing of OpenMP clauses with single expressions and some additional
|
2014-06-20 15:16:17 +08:00
|
|
|
/// argument like 'schedule' or 'dist_schedule'.
|
|
|
|
///
|
|
|
|
/// schedule-clause:
|
2015-12-28 15:25:51 +08:00
|
|
|
/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ]
|
|
|
|
/// ')'
|
2014-06-20 15:16:17 +08:00
|
|
|
///
|
2015-09-03 15:23:48 +08:00
|
|
|
/// if-clause:
|
|
|
|
/// 'if' '(' [ directive-name-modifier ':' ] expression ')'
|
|
|
|
///
|
2016-01-27 00:37:23 +08:00
|
|
|
/// defaultmap:
|
|
|
|
/// 'defaultmap' '(' modifier ':' kind ')'
|
|
|
|
///
|
2018-01-10 03:21:04 +08:00
|
|
|
OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind,
|
|
|
|
bool ParseOnly) {
|
2014-06-20 15:16:17 +08:00
|
|
|
SourceLocation Loc = ConsumeToken();
|
2015-09-03 15:23:48 +08:00
|
|
|
SourceLocation DelimLoc;
|
2014-06-20 15:16:17 +08:00
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
getOpenMPClauseName(Kind)))
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
ExprResult Val;
|
2015-12-28 15:25:51 +08:00
|
|
|
SmallVector<unsigned, 4> Arg;
|
|
|
|
SmallVector<SourceLocation, 4> KLoc;
|
2015-09-03 15:23:48 +08:00
|
|
|
if (Kind == OMPC_schedule) {
|
2015-12-28 15:25:51 +08:00
|
|
|
enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements };
|
|
|
|
Arg.resize(NumberOfElements);
|
|
|
|
KLoc.resize(NumberOfElements);
|
|
|
|
Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown;
|
|
|
|
Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown;
|
|
|
|
Arg[ScheduleKind] = OMPC_SCHEDULE_unknown;
|
2018-04-24 03:53:05 +08:00
|
|
|
unsigned KindModifier = getOpenMPSimpleClauseType(
|
2015-09-03 15:23:48 +08:00
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
|
2015-12-28 15:25:51 +08:00
|
|
|
if (KindModifier > OMPC_SCHEDULE_unknown) {
|
|
|
|
// Parse 'modifier'
|
|
|
|
Arg[Modifier1] = KindModifier;
|
|
|
|
KLoc[Modifier1] = Tok.getLocation();
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
if (Tok.is(tok::comma)) {
|
|
|
|
// Parse ',' 'modifier'
|
|
|
|
ConsumeAnyToken();
|
|
|
|
KindModifier = getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
|
|
|
|
Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown
|
|
|
|
? KindModifier
|
2015-12-28 23:52:46 +08:00
|
|
|
: (unsigned)OMPC_SCHEDULE_unknown;
|
2015-12-28 15:25:51 +08:00
|
|
|
KLoc[Modifier2] = Tok.getLocation();
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
}
|
|
|
|
// Parse ':'
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
else
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier";
|
|
|
|
KindModifier = getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok));
|
|
|
|
}
|
|
|
|
Arg[ScheduleKind] = KindModifier;
|
|
|
|
KLoc[ScheduleKind] = Tok.getLocation();
|
2015-09-03 15:23:48 +08:00
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
2015-12-28 15:25:51 +08:00
|
|
|
if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static ||
|
|
|
|
Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic ||
|
|
|
|
Arg[ScheduleKind] == OMPC_SCHEDULE_guided) &&
|
2015-09-03 15:23:48 +08:00
|
|
|
Tok.is(tok::comma))
|
|
|
|
DelimLoc = ConsumeAnyToken();
|
2016-01-16 02:50:31 +08:00
|
|
|
} else if (Kind == OMPC_dist_schedule) {
|
|
|
|
Arg.push_back(getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
|
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
if (Arg.back() == OMPC_DIST_SCHEDULE_static && Tok.is(tok::comma))
|
|
|
|
DelimLoc = ConsumeAnyToken();
|
2016-01-27 00:37:23 +08:00
|
|
|
} else if (Kind == OMPC_defaultmap) {
|
|
|
|
// Get a defaultmap modifier
|
2019-11-16 02:02:06 +08:00
|
|
|
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);
|
2016-01-27 00:37:23 +08:00
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
// Parse ':'
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ConsumeAnyToken();
|
|
|
|
else if (Arg.back() != OMPC_DEFAULTMAP_MODIFIER_unknown)
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "defaultmap modifier";
|
|
|
|
// Get a defaultmap kind
|
|
|
|
Arg.push_back(getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)));
|
|
|
|
KLoc.push_back(Tok.getLocation());
|
|
|
|
if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) &&
|
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))
|
|
|
|
ConsumeAnyToken();
|
2015-09-03 15:23:48 +08:00
|
|
|
} else {
|
|
|
|
assert(Kind == OMPC_if);
|
2015-12-28 15:25:51 +08:00
|
|
|
KLoc.push_back(Tok.getLocation());
|
2016-12-20 20:10:05 +08:00
|
|
|
TentativeParsingAction TPA(*this);
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
auto DK = parseOpenMPDirectiveKind(*this);
|
|
|
|
Arg.push_back(DK);
|
|
|
|
if (DK != OMPD_unknown) {
|
2015-09-03 15:23:48 +08:00
|
|
|
ConsumeToken();
|
2016-12-20 20:10:05 +08:00
|
|
|
if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) {
|
|
|
|
TPA.Commit();
|
2015-09-03 15:23:48 +08:00
|
|
|
DelimLoc = ConsumeToken();
|
2016-12-20 20:10:05 +08:00
|
|
|
} else {
|
|
|
|
TPA.Revert();
|
[OpenMP][NFCI] Introduce llvm/IR/OpenMPConstants.h
Summary:
The new OpenMPConstants.h is a location for all OpenMP related constants
(and helpers) to live.
This patch moves the directives there (the enum OpenMPDirectiveKind) and
rewires Clang to use the new location.
Initially part of D69785.
Reviewers: kiranchandramohan, ABataev, RaviNarayanaswamy, gtbercea, grokos, sdmitriev, JonChesterfield, hfinkel, fghanim
Subscribers: jholewinski, ppenzin, penzn, llvm-commits, cfe-commits, jfb, guansong, bollu, hiraditya, mgorny
Tags: #clang, #llvm
Differential Revision: https://reviews.llvm.org/D69853
2019-11-05 12:00:49 +08:00
|
|
|
Arg.back() = unsigned(OMPD_unknown);
|
2016-12-20 20:10:05 +08:00
|
|
|
}
|
2018-04-24 03:53:05 +08:00
|
|
|
} else {
|
2016-12-20 20:10:05 +08:00
|
|
|
TPA.Revert();
|
2018-04-24 03:53:05 +08:00
|
|
|
}
|
2015-09-03 15:23:48 +08:00
|
|
|
}
|
2014-06-20 15:16:17 +08:00
|
|
|
|
2016-01-16 02:50:31 +08:00
|
|
|
bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) ||
|
|
|
|
(Kind == OMPC_dist_schedule && DelimLoc.isValid()) ||
|
|
|
|
Kind == OMPC_if;
|
2015-09-03 15:23:48 +08:00
|
|
|
if (NeedAnExpression) {
|
|
|
|
SourceLocation ELoc = Tok.getLocation();
|
2014-06-20 15:16:17 +08:00
|
|
|
ExprResult LHS(ParseCastExpression(false, false, NotTypeCast));
|
|
|
|
Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional);
|
2019-01-05 00:58:14 +08:00
|
|
|
Val =
|
|
|
|
Actions.ActOnFinishFullExpr(Val.get(), ELoc, /*DiscardedValue*/ false);
|
2014-06-20 15:16:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parse ')'.
|
2018-07-07 03:35:42 +08:00
|
|
|
SourceLocation RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
RLoc = T.getCloseLocation();
|
2014-06-20 15:16:17 +08:00
|
|
|
|
2015-09-03 15:23:48 +08:00
|
|
|
if (NeedAnExpression && Val.isInvalid())
|
|
|
|
return nullptr;
|
|
|
|
|
2018-01-10 03:21:04 +08:00
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
2014-06-20 15:16:17 +08:00
|
|
|
return Actions.ActOnOpenMPSingleExprWithArgClause(
|
2018-07-07 03:35:42 +08:00
|
|
|
Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc);
|
2014-06-20 15:16:17 +08:00
|
|
|
}
|
|
|
|
|
2014-06-16 15:08:35 +08:00
|
|
|
static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec,
|
|
|
|
UnqualifiedId &ReductionId) {
|
|
|
|
if (ReductionIdScopeSpec.isEmpty()) {
|
|
|
|
auto OOK = OO_None;
|
|
|
|
switch (P.getCurToken().getKind()) {
|
|
|
|
case tok::plus:
|
|
|
|
OOK = OO_Plus;
|
|
|
|
break;
|
|
|
|
case tok::minus:
|
|
|
|
OOK = OO_Minus;
|
|
|
|
break;
|
|
|
|
case tok::star:
|
|
|
|
OOK = OO_Star;
|
|
|
|
break;
|
|
|
|
case tok::amp:
|
|
|
|
OOK = OO_Amp;
|
|
|
|
break;
|
|
|
|
case tok::pipe:
|
|
|
|
OOK = OO_Pipe;
|
|
|
|
break;
|
|
|
|
case tok::caret:
|
|
|
|
OOK = OO_Caret;
|
|
|
|
break;
|
|
|
|
case tok::ampamp:
|
|
|
|
OOK = OO_AmpAmp;
|
|
|
|
break;
|
|
|
|
case tok::pipepipe:
|
|
|
|
OOK = OO_PipePipe;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (OOK != OO_None) {
|
|
|
|
SourceLocation OpLoc = P.ConsumeToken();
|
2014-06-18 15:08:49 +08:00
|
|
|
SourceLocation SymbolLocations[] = {OpLoc, OpLoc, SourceLocation()};
|
2014-06-16 15:08:35 +08:00
|
|
|
ReductionId.setOperatorFunctionId(OpLoc, OOK, SymbolLocations);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return P.ParseUnqualifiedId(ReductionIdScopeSpec, /*EnteringContext*/ false,
|
|
|
|
/*AllowDestructorName*/ false,
|
2017-02-07 09:37:30 +08:00
|
|
|
/*AllowConstructorName*/ false,
|
|
|
|
/*AllowDeductionGuide*/ false,
|
2018-04-27 10:00:13 +08:00
|
|
|
nullptr, nullptr, ReductionId);
|
2014-06-16 15:08:35 +08:00
|
|
|
}
|
|
|
|
|
2018-12-19 06:18:41 +08:00
|
|
|
/// Checks if the token is a valid map-type-modifier.
|
|
|
|
static OpenMPMapModifierKind isMapModifier(Parser &P) {
|
|
|
|
Token Tok = P.getCurToken();
|
|
|
|
if (!Tok.is(tok::identifier))
|
|
|
|
return OMPC_MAP_MODIFIER_unknown;
|
|
|
|
|
|
|
|
Preprocessor &PP = P.getPreprocessor();
|
|
|
|
OpenMPMapModifierKind TypeModifier = static_cast<OpenMPMapModifierKind>(
|
|
|
|
getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
|
|
|
|
return TypeModifier;
|
|
|
|
}
|
|
|
|
|
2019-02-23 06:29:42 +08:00
|
|
|
/// Parse the mapper modifier in map, to, and from clauses.
|
|
|
|
bool Parser::parseMapperModifier(OpenMPVarListDataTy &Data) {
|
|
|
|
// Parse '('.
|
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::colon);
|
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after, "mapper")) {
|
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// Parse mapper-identifier
|
|
|
|
if (getLangOpts().CPlusPlus)
|
|
|
|
ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
|
|
|
|
/*ObjectType=*/nullptr,
|
|
|
|
/*EnteringContext=*/false);
|
|
|
|
if (Tok.isNot(tok::identifier) && Tok.isNot(tok::kw_default)) {
|
|
|
|
Diag(Tok.getLocation(), diag::err_omp_mapper_illegal_identifier);
|
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
auto &DeclNames = Actions.getASTContext().DeclarationNames;
|
|
|
|
Data.ReductionOrMapperId = DeclarationNameInfo(
|
|
|
|
DeclNames.getIdentifier(Tok.getIdentifierInfo()), Tok.getLocation());
|
|
|
|
ConsumeToken();
|
|
|
|
// Parse ')'.
|
|
|
|
return T.consumeClose();
|
|
|
|
}
|
|
|
|
|
2018-12-19 06:18:41 +08:00
|
|
|
/// Parse map-type-modifiers in map clause.
|
|
|
|
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
|
2019-02-20 00:38:20 +08:00
|
|
|
/// where, map-type-modifier ::= always | close | mapper(mapper-identifier)
|
|
|
|
bool Parser::parseMapTypeModifiers(OpenMPVarListDataTy &Data) {
|
|
|
|
while (getCurToken().isNot(tok::colon)) {
|
|
|
|
OpenMPMapModifierKind TypeModifier = isMapModifier(*this);
|
2018-12-19 06:18:41 +08:00
|
|
|
if (TypeModifier == OMPC_MAP_MODIFIER_always ||
|
|
|
|
TypeModifier == OMPC_MAP_MODIFIER_close) {
|
|
|
|
Data.MapTypeModifiers.push_back(TypeModifier);
|
|
|
|
Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
|
2019-02-20 00:38:20 +08:00
|
|
|
ConsumeToken();
|
|
|
|
} else if (TypeModifier == OMPC_MAP_MODIFIER_mapper) {
|
|
|
|
Data.MapTypeModifiers.push_back(TypeModifier);
|
|
|
|
Data.MapTypeModifiersLoc.push_back(Tok.getLocation());
|
|
|
|
ConsumeToken();
|
2019-02-23 06:29:42 +08:00
|
|
|
if (parseMapperModifier(Data))
|
2019-02-20 00:38:20 +08:00
|
|
|
return true;
|
2018-12-19 06:18:41 +08:00
|
|
|
} else {
|
|
|
|
// For the case of unknown map-type-modifier or a map-type.
|
|
|
|
// Map-type is followed by a colon; the function returns when it
|
|
|
|
// encounters a token followed by a colon.
|
|
|
|
if (Tok.is(tok::comma)) {
|
2019-02-20 00:38:20 +08:00
|
|
|
Diag(Tok, diag::err_omp_map_type_modifier_missing);
|
|
|
|
ConsumeToken();
|
2018-12-19 06:18:41 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Potential map-type token as it is followed by a colon.
|
|
|
|
if (PP.LookAhead(0).is(tok::colon))
|
2019-02-20 00:38:20 +08:00
|
|
|
return false;
|
|
|
|
Diag(Tok, diag::err_omp_unknown_map_type_modifier);
|
|
|
|
ConsumeToken();
|
2018-12-19 06:18:41 +08:00
|
|
|
}
|
2019-02-20 00:38:20 +08:00
|
|
|
if (getCurToken().is(tok::comma))
|
|
|
|
ConsumeToken();
|
2018-12-19 06:18:41 +08:00
|
|
|
}
|
2019-02-20 00:38:20 +08:00
|
|
|
return false;
|
2018-12-19 06:18:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Checks if the token is a valid map-type.
|
|
|
|
static OpenMPMapClauseKind isMapType(Parser &P) {
|
|
|
|
Token Tok = P.getCurToken();
|
|
|
|
// The map-type token can be either an identifier or the C++ delete keyword.
|
|
|
|
if (!Tok.isOneOf(tok::identifier, tok::kw_delete))
|
|
|
|
return OMPC_MAP_unknown;
|
|
|
|
Preprocessor &PP = P.getPreprocessor();
|
|
|
|
OpenMPMapClauseKind MapType = static_cast<OpenMPMapClauseKind>(
|
|
|
|
getOpenMPSimpleClauseType(OMPC_map, PP.getSpelling(Tok)));
|
|
|
|
return MapType;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Parse map-type in map clause.
|
|
|
|
/// map([ [map-type-modifier[,] [map-type-modifier[,] ...] map-type : ] list)
|
2019-02-26 19:01:50 +08:00
|
|
|
/// where, map-type ::= to | from | tofrom | alloc | release | delete
|
2018-12-19 06:18:41 +08:00
|
|
|
static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
|
|
|
|
Token Tok = P.getCurToken();
|
|
|
|
if (Tok.is(tok::colon)) {
|
|
|
|
P.Diag(Tok, diag::err_omp_map_type_missing);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Data.MapType = isMapType(P);
|
|
|
|
if (Data.MapType == OMPC_MAP_unknown)
|
|
|
|
P.Diag(Tok, diag::err_omp_unknown_map_type);
|
|
|
|
P.ConsumeToken();
|
|
|
|
}
|
|
|
|
|
2016-04-12 13:28:34 +08:00
|
|
|
/// Parses clauses with list.
|
|
|
|
bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
|
|
|
|
OpenMPClauseKind Kind,
|
|
|
|
SmallVectorImpl<Expr *> &Vars,
|
|
|
|
OpenMPVarListDataTy &Data) {
|
|
|
|
UnqualifiedId UnqualifiedReductionId;
|
2014-06-16 15:08:35 +08:00
|
|
|
bool InvalidReductionId = false;
|
2019-02-23 06:29:42 +08:00
|
|
|
bool IsInvalidMapperModifier = false;
|
2015-06-23 22:25:19 +08:00
|
|
|
|
2013-07-19 11:13:43 +08:00
|
|
|
// Parse '('.
|
2013-12-19 03:10:49 +08:00
|
|
|
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
2013-07-19 11:13:43 +08:00
|
|
|
if (T.expectAndConsume(diag::err_expected_lparen_after,
|
|
|
|
getOpenMPClauseName(Kind)))
|
2016-04-12 13:28:34 +08:00
|
|
|
return true;
|
2013-07-19 11:13:43 +08:00
|
|
|
|
2015-08-20 18:54:39 +08:00
|
|
|
bool NeedRParenForLinear = false;
|
|
|
|
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
|
|
|
|
tok::annot_pragma_openmp_end);
|
2014-06-16 15:08:35 +08:00
|
|
|
// Handle reduction-identifier for reduction clause.
|
2017-07-22 02:48:21 +08:00
|
|
|
if (Kind == OMPC_reduction || Kind == OMPC_task_reduction ||
|
|
|
|
Kind == OMPC_in_reduction) {
|
2014-06-16 15:08:35 +08:00
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
2016-03-17 18:19:46 +08:00
|
|
|
if (getLangOpts().CPlusPlus)
|
2019-02-20 00:38:20 +08:00
|
|
|
ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,
|
2016-03-17 18:19:46 +08:00
|
|
|
/*ObjectType=*/nullptr,
|
|
|
|
/*EnteringContext=*/false);
|
2019-02-20 00:38:20 +08:00
|
|
|
InvalidReductionId = ParseReductionId(
|
|
|
|
*this, Data.ReductionOrMapperIdScopeSpec, UnqualifiedReductionId);
|
2014-06-16 15:08:35 +08:00
|
|
|
if (InvalidReductionId) {
|
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
2016-04-12 13:28:34 +08:00
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
Data.ColonLoc = ConsumeToken();
|
|
|
|
else
|
2014-06-16 15:08:35 +08:00
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << "reduction identifier";
|
2016-04-12 13:28:34 +08:00
|
|
|
if (!InvalidReductionId)
|
2019-02-20 00:38:20 +08:00
|
|
|
Data.ReductionOrMapperId =
|
2016-04-12 13:28:34 +08:00
|
|
|
Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
|
2015-06-23 22:25:19 +08:00
|
|
|
} else if (Kind == OMPC_depend) {
|
|
|
|
// Handle dependency type for depend clause.
|
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
2016-04-12 13:28:34 +08:00
|
|
|
Data.DepKind =
|
|
|
|
static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType(
|
|
|
|
Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : ""));
|
|
|
|
Data.DepLinMapLoc = Tok.getLocation();
|
2015-06-23 22:25:19 +08:00
|
|
|
|
2016-04-12 13:28:34 +08:00
|
|
|
if (Data.DepKind == OMPC_DEPEND_unknown) {
|
2015-06-23 22:25:19 +08:00
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
} else {
|
|
|
|
ConsumeToken();
|
2015-12-18 13:05:56 +08:00
|
|
|
// Special processing for depend(source) clause.
|
2016-04-12 13:28:34 +08:00
|
|
|
if (DKind == OMPD_ordered && Data.DepKind == OMPC_DEPEND_source) {
|
2015-12-18 13:05:56 +08:00
|
|
|
// Parse ')'.
|
|
|
|
T.consumeClose();
|
2016-04-12 13:28:34 +08:00
|
|
|
return false;
|
2015-12-18 13:05:56 +08:00
|
|
|
}
|
2015-06-23 22:25:19 +08:00
|
|
|
}
|
2018-04-24 03:53:05 +08:00
|
|
|
if (Tok.is(tok::colon)) {
|
2016-04-12 13:28:34 +08:00
|
|
|
Data.ColonLoc = ConsumeToken();
|
2018-04-24 03:53:05 +08:00
|
|
|
} else {
|
2015-12-18 13:05:56 +08:00
|
|
|
Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
|
|
|
|
: diag::warn_pragma_expected_colon)
|
|
|
|
<< "dependency type";
|
2015-06-23 22:25:19 +08:00
|
|
|
}
|
2015-08-20 18:54:39 +08:00
|
|
|
} else if (Kind == OMPC_linear) {
|
|
|
|
// Try to parse modifier if any.
|
|
|
|
if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) {
|
2016-04-12 13:28:34 +08:00
|
|
|
Data.LinKind = static_cast<OpenMPLinearClauseKind>(
|
2015-08-20 20:15:57 +08:00
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
|
2016-04-12 13:28:34 +08:00
|
|
|
Data.DepLinMapLoc = ConsumeToken();
|
2015-08-20 18:54:39 +08:00
|
|
|
LinearT.consumeOpen();
|
|
|
|
NeedRParenForLinear = true;
|
|
|
|
}
|
2015-11-23 13:32:03 +08:00
|
|
|
} else if (Kind == OMPC_map) {
|
|
|
|
// Handle map type for map clause.
|
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
|
|
|
|
2016-02-27 08:01:58 +08:00
|
|
|
// The first identifier may be a list item, a map-type or a
|
2018-12-19 06:18:41 +08:00
|
|
|
// map-type-modifier. The map-type can also be delete which has the same
|
2016-02-27 08:01:58 +08:00
|
|
|
// spelling of the C++ delete keyword.
|
2016-04-12 13:28:34 +08:00
|
|
|
Data.DepLinMapLoc = Tok.getLocation();
|
2015-11-23 13:32:03 +08:00
|
|
|
|
2018-12-19 06:18:41 +08:00
|
|
|
// Check for presence of a colon in the map clause.
|
|
|
|
TentativeParsingAction TPA(*this);
|
|
|
|
bool ColonPresent = false;
|
|
|
|
if (SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch)) {
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ColonPresent = true;
|
|
|
|
}
|
|
|
|
TPA.Revert();
|
|
|
|
// Only parse map-type-modifier[s] and map-type if a colon is present in
|
|
|
|
// the map clause.
|
|
|
|
if (ColonPresent) {
|
2019-02-23 06:29:42 +08:00
|
|
|
IsInvalidMapperModifier = parseMapTypeModifiers(Data);
|
|
|
|
if (!IsInvalidMapperModifier)
|
2019-02-20 00:38:20 +08:00
|
|
|
parseMapType(*this, Data);
|
2019-02-23 06:29:42 +08:00
|
|
|
else
|
|
|
|
SkipUntil(tok::colon, tok::annot_pragma_openmp_end, StopBeforeMatch);
|
2018-12-19 06:18:41 +08:00
|
|
|
}
|
|
|
|
if (Data.MapType == OMPC_MAP_unknown) {
|
2016-04-12 13:28:34 +08:00
|
|
|
Data.MapType = OMPC_MAP_tofrom;
|
|
|
|
Data.IsMapTypeImplicit = true;
|
2015-11-23 13:32:03 +08:00
|
|
|
}
|
|
|
|
|
2016-04-12 13:28:34 +08:00
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
Data.ColonLoc = ConsumeToken();
|
2019-02-26 04:34:15 +08:00
|
|
|
} else if (Kind == OMPC_to || Kind == OMPC_from) {
|
2019-02-23 06:29:42 +08:00
|
|
|
if (Tok.is(tok::identifier)) {
|
|
|
|
bool IsMapperModifier = false;
|
2019-02-26 04:34:15 +08:00
|
|
|
if (Kind == OMPC_to) {
|
|
|
|
auto Modifier = static_cast<OpenMPToModifierKind>(
|
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
|
|
|
|
if (Modifier == OMPC_TO_MODIFIER_mapper)
|
|
|
|
IsMapperModifier = true;
|
|
|
|
} else {
|
|
|
|
auto Modifier = static_cast<OpenMPFromModifierKind>(
|
|
|
|
getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok)));
|
|
|
|
if (Modifier == OMPC_FROM_MODIFIER_mapper)
|
|
|
|
IsMapperModifier = true;
|
|
|
|
}
|
2019-02-23 06:29:42 +08:00
|
|
|
if (IsMapperModifier) {
|
|
|
|
// Parse the mapper modifier.
|
|
|
|
ConsumeToken();
|
|
|
|
IsInvalidMapperModifier = parseMapperModifier(Data);
|
|
|
|
if (Tok.isNot(tok::colon)) {
|
|
|
|
if (!IsInvalidMapperModifier)
|
|
|
|
Diag(Tok, diag::warn_pragma_expected_colon) << ")";
|
|
|
|
SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
|
|
|
// Consume ':'.
|
|
|
|
if (Tok.is(tok::colon))
|
|
|
|
ConsumeToken();
|
|
|
|
}
|
|
|
|
}
|
2019-03-27 22:14:31 +08:00
|
|
|
} else if (Kind == OMPC_allocate) {
|
|
|
|
// Handle optional allocator expression followed by colon delimiter.
|
|
|
|
ColonProtectionRAIIObject ColonRAII(*this);
|
|
|
|
TentativeParsingAction TPA(*this);
|
|
|
|
ExprResult Tail =
|
|
|
|
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
|
|
|
|
Tail = Actions.ActOnFinishFullExpr(Tail.get(), T.getOpenLocation(),
|
|
|
|
/*DiscardedValue=*/false);
|
|
|
|
if (Tail.isUsable()) {
|
|
|
|
if (Tok.is(tok::colon)) {
|
|
|
|
Data.TailExpr = Tail.get();
|
|
|
|
Data.ColonLoc = ConsumeToken();
|
|
|
|
TPA.Commit();
|
|
|
|
} else {
|
|
|
|
// colon not found, no allocator specified, parse only list of
|
|
|
|
// variables.
|
|
|
|
TPA.Revert();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Parsing was unsuccessfull, revert and skip to the end of clause or
|
|
|
|
// directive.
|
|
|
|
TPA.Revert();
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
|
|
|
}
|
2014-06-16 15:08:35 +08:00
|
|
|
}
|
|
|
|
|
2017-07-22 02:48:21 +08:00
|
|
|
bool IsComma =
|
|
|
|
(Kind != OMPC_reduction && Kind != OMPC_task_reduction &&
|
|
|
|
Kind != OMPC_in_reduction && Kind != OMPC_depend && Kind != OMPC_map) ||
|
|
|
|
(Kind == OMPC_reduction && !InvalidReductionId) ||
|
2018-11-22 03:38:53 +08:00
|
|
|
(Kind == OMPC_map && Data.MapType != OMPC_MAP_unknown) ||
|
2017-07-22 02:48:21 +08:00
|
|
|
(Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown);
|
2014-05-29 22:36:25 +08:00
|
|
|
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
|
2014-04-22 21:09:42 +08:00
|
|
|
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
|
2013-07-19 11:13:43 +08:00
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end))) {
|
2014-04-22 21:09:42 +08:00
|
|
|
ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
|
2013-07-19 11:13:43 +08:00
|
|
|
// Parse variable
|
2014-11-22 02:48:04 +08:00
|
|
|
ExprResult VarExpr =
|
|
|
|
Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression());
|
2018-04-24 03:53:05 +08:00
|
|
|
if (VarExpr.isUsable()) {
|
2014-05-29 18:55:11 +08:00
|
|
|
Vars.push_back(VarExpr.get());
|
2018-04-24 03:53:05 +08:00
|
|
|
} else {
|
2013-07-19 11:13:43 +08:00
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
2013-12-19 03:10:49 +08:00
|
|
|
StopBeforeMatch);
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
|
|
|
// Skip ',' if any
|
|
|
|
IsComma = Tok.is(tok::comma);
|
2016-04-01 16:43:42 +08:00
|
|
|
if (IsComma)
|
2013-07-19 11:13:43 +08:00
|
|
|
ConsumeToken();
|
2016-04-01 16:43:42 +08:00
|
|
|
else if (Tok.isNot(tok::r_paren) &&
|
2014-04-22 21:09:42 +08:00
|
|
|
Tok.isNot(tok::annot_pragma_openmp_end) &&
|
|
|
|
(!MayHaveTail || Tok.isNot(tok::colon)))
|
2014-07-21 19:26:11 +08:00
|
|
|
Diag(Tok, diag::err_omp_expected_punc)
|
|
|
|
<< ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
|
|
|
|
: getOpenMPClauseName(Kind))
|
|
|
|
<< (Kind == OMPC_flush);
|
2014-04-22 21:09:42 +08:00
|
|
|
}
|
|
|
|
|
2015-08-20 18:54:39 +08:00
|
|
|
// Parse ')' for linear clause with modifier.
|
|
|
|
if (NeedRParenForLinear)
|
|
|
|
LinearT.consumeClose();
|
|
|
|
|
2014-05-29 22:36:25 +08:00
|
|
|
// Parse ':' linear-step (or ':' alignment).
|
2014-04-22 21:09:42 +08:00
|
|
|
const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon);
|
|
|
|
if (MustHaveTail) {
|
2016-04-12 13:28:34 +08:00
|
|
|
Data.ColonLoc = Tok.getLocation();
|
2015-09-03 15:23:48 +08:00
|
|
|
SourceLocation ELoc = ConsumeToken();
|
|
|
|
ExprResult Tail = ParseAssignmentExpression();
|
2019-01-05 00:58:14 +08:00
|
|
|
Tail =
|
|
|
|
Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
|
2014-04-22 21:09:42 +08:00
|
|
|
if (Tail.isUsable())
|
2016-04-12 13:28:34 +08:00
|
|
|
Data.TailExpr = Tail.get();
|
2014-04-22 21:09:42 +08:00
|
|
|
else
|
|
|
|
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
|
|
|
|
StopBeforeMatch);
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Parse ')'.
|
2018-07-07 03:35:42 +08:00
|
|
|
Data.RLoc = Tok.getLocation();
|
|
|
|
if (!T.consumeClose())
|
|
|
|
Data.RLoc = T.getCloseLocation();
|
2018-04-24 03:53:05 +08:00
|
|
|
return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown &&
|
|
|
|
Vars.empty()) ||
|
|
|
|
(Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
|
2019-02-20 00:38:20 +08:00
|
|
|
(MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
|
2019-02-23 06:29:42 +08:00
|
|
|
IsInvalidMapperModifier;
|
2016-04-12 13:28:34 +08:00
|
|
|
}
|
|
|
|
|
2018-05-09 09:00:01 +08:00
|
|
|
/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate',
|
2017-07-22 02:48:21 +08:00
|
|
|
/// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or
|
|
|
|
/// 'in_reduction'.
|
2016-04-12 13:28:34 +08:00
|
|
|
///
|
|
|
|
/// private-clause:
|
|
|
|
/// 'private' '(' list ')'
|
|
|
|
/// firstprivate-clause:
|
|
|
|
/// 'firstprivate' '(' list ')'
|
|
|
|
/// lastprivate-clause:
|
|
|
|
/// 'lastprivate' '(' list ')'
|
|
|
|
/// shared-clause:
|
|
|
|
/// 'shared' '(' list ')'
|
|
|
|
/// linear-clause:
|
|
|
|
/// 'linear' '(' linear-list [ ':' linear-step ] ')'
|
|
|
|
/// aligned-clause:
|
|
|
|
/// 'aligned' '(' list [ ':' alignment ] ')'
|
|
|
|
/// reduction-clause:
|
|
|
|
/// 'reduction' '(' reduction-identifier ':' list ')'
|
2017-07-19 04:17:46 +08:00
|
|
|
/// task_reduction-clause:
|
|
|
|
/// 'task_reduction' '(' reduction-identifier ':' list ')'
|
2017-07-22 02:48:21 +08:00
|
|
|
/// in_reduction-clause:
|
|
|
|
/// 'in_reduction' '(' reduction-identifier ':' list ')'
|
2016-04-12 13:28:34 +08:00
|
|
|
/// copyprivate-clause:
|
|
|
|
/// 'copyprivate' '(' list ')'
|
|
|
|
/// flush-clause:
|
|
|
|
/// 'flush' '(' list ')'
|
|
|
|
/// depend-clause:
|
|
|
|
/// 'depend' '(' in | out | inout : list | source ')'
|
|
|
|
/// map-clause:
|
2018-12-19 06:18:41 +08:00
|
|
|
/// 'map' '(' [ [ always [,] ] [ close [,] ]
|
2019-02-23 06:29:42 +08:00
|
|
|
/// [ mapper '(' mapper-identifier ')' [,] ]
|
2016-04-12 13:28:34 +08:00
|
|
|
/// to | from | tofrom | alloc | release | delete ':' ] list ')';
|
2016-05-27 01:39:58 +08:00
|
|
|
/// to-clause:
|
2019-02-23 06:29:42 +08:00
|
|
|
/// 'to' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
|
2016-05-27 01:49:04 +08:00
|
|
|
/// from-clause:
|
2019-02-26 04:34:15 +08:00
|
|
|
/// 'from' '(' [ mapper '(' mapper-identifier ')' ':' ] list ')'
|
2016-07-13 23:37:16 +08:00
|
|
|
/// use_device_ptr-clause:
|
|
|
|
/// 'use_device_ptr' '(' list ')'
|
2016-07-14 01:16:49 +08:00
|
|
|
/// is_device_ptr-clause:
|
|
|
|
/// 'is_device_ptr' '(' list ')'
|
2019-03-27 22:14:31 +08:00
|
|
|
/// allocate-clause:
|
|
|
|
/// 'allocate' '(' [ allocator ':' ] list ')'
|
2016-04-12 13:28:34 +08:00
|
|
|
///
|
|
|
|
/// For 'linear' clause linear-list may have the following forms:
|
|
|
|
/// list
|
|
|
|
/// modifier(list)
|
|
|
|
/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++).
|
|
|
|
OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
|
2018-01-10 03:21:04 +08:00
|
|
|
OpenMPClauseKind Kind,
|
|
|
|
bool ParseOnly) {
|
2016-04-12 13:28:34 +08:00
|
|
|
SourceLocation Loc = Tok.getLocation();
|
|
|
|
SourceLocation LOpen = ConsumeToken();
|
|
|
|
SmallVector<Expr *, 4> Vars;
|
|
|
|
OpenMPVarListDataTy Data;
|
|
|
|
|
|
|
|
if (ParseOpenMPVarList(DKind, Kind, Vars, Data))
|
2014-05-21 14:02:52 +08:00
|
|
|
return nullptr;
|
2013-07-19 11:13:43 +08:00
|
|
|
|
2018-01-10 03:21:04 +08:00
|
|
|
if (ParseOnly)
|
|
|
|
return nullptr;
|
2019-02-20 00:38:20 +08:00
|
|
|
OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
|
2014-06-16 15:08:35 +08:00
|
|
|
return Actions.ActOnOpenMPVarListClause(
|
2019-02-20 00:38:20 +08:00
|
|
|
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);
|
2013-07-19 11:13:43 +08:00
|
|
|
}
|
|
|
|
|