Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions flang/include/flang/Parser/dump-parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,7 @@ class ParseTreeDumper {
NODE(parser, OmpAtomicDefaultMemOrderClause)
NODE(parser, OmpAutomapModifier)
NODE_ENUM(OmpAutomapModifier, Value)
NODE(parser, OmpBaseVariantNames)
NODE(parser, OmpBeginDirective)
NODE(parser, OmpBeginLoopDirective)
NODE(parser, OmpBeginSectionsDirective)
Expand Down
10 changes: 5 additions & 5 deletions flang/include/flang/Parser/openmp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,9 @@ struct ConstructId {
static constexpr llvm::omp::Directive id{Id}; \
}

MAKE_CONSTR_ID(OmpDeclareVariantDirective, D::OMPD_declare_variant);
MAKE_CONSTR_ID(OpenMPDeclarativeAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPDeclarativeAssumes, D::OMPD_assumes);
MAKE_CONSTR_ID(OpenMPDeclareReductionConstruct, D::OMPD_declare_reduction);
MAKE_CONSTR_ID(OpenMPDeclareSimdConstruct, D::OMPD_declare_simd);
MAKE_CONSTR_ID(OpenMPDeclareTargetConstruct, D::OMPD_declare_target);
MAKE_CONSTR_ID(OpenMPExecutableAllocate, D::OMPD_allocate);
MAKE_CONSTR_ID(OpenMPRequiresConstruct, D::OMPD_requires);
Expand All @@ -58,6 +56,10 @@ struct DirectiveNameScope {
return name;
}

static OmpDirectiveName GetOmpDirectiveName(const OmpDirectiveName &x) {
return x;
}

static OmpDirectiveName GetOmpDirectiveName(const OmpBeginLoopDirective &x) {
return x.DirName();
}
Expand Down Expand Up @@ -92,11 +94,9 @@ struct DirectiveNameScope {
} else if constexpr (TupleTrait<T>) {
if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
return std::get<OmpBeginDirective>(x.t).DirName();
} else if constexpr (std::is_same_v<T, OmpDeclareVariantDirective> ||
std::is_same_v<T, OpenMPDeclarativeAllocate> ||
} else if constexpr (std::is_same_v<T, OpenMPDeclarativeAllocate> ||
std::is_same_v<T, OpenMPDeclarativeAssumes> ||
std::is_same_v<T, OpenMPDeclareReductionConstruct> ||
std::is_same_v<T, OpenMPDeclareSimdConstruct> ||
std::is_same_v<T, OpenMPDeclareTargetConstruct> ||
std::is_same_v<T, OpenMPExecutableAllocate> ||
std::is_same_v<T, OpenMPRequiresConstruct>) {
Expand Down
25 changes: 21 additions & 4 deletions flang/include/flang/Parser/parse-tree.h
Original file line number Diff line number Diff line change
Expand Up @@ -3555,6 +3555,18 @@ struct OmpLocator {

WRAPPER_CLASS(OmpLocatorList, std::list<OmpLocator>);

// Ref: [4.5:58-60], [5.0:58-60], [5.1:63-68], [5.2:197-198], [6.0:334-336]
//
// Argument to DECLARE VARIANT with the base-name present. (When only
// variant-name is present, it is a simple OmpObject).
//
// base-name-variant-name -> // since 4.5
// base-name : variant-name
struct OmpBaseVariantNames {
TUPLE_CLASS_BOILERPLATE(OmpBaseVariantNames);
std::tuple<OmpObject, OmpObject> t;
};

// Ref: [5.0:326:10-16], [5.1:359:5-11], [5.2:163:2-7], [6.0:293:16-21]
//
// mapper-specifier ->
Expand Down Expand Up @@ -3584,6 +3596,7 @@ struct OmpArgument {
CharBlock source;
UNION_CLASS_BOILERPLATE(OmpArgument);
std::variant<OmpLocator, // {variable, extended, locator}-list-item
OmpBaseVariantNames, // base-name:variant-name
OmpMapperSpecifier, OmpReductionSpecifier>
u;
};
Expand Down Expand Up @@ -4920,10 +4933,14 @@ struct OpenMPSectionsConstruct {
t;
};

// Ref: [4.5:58-60], [5.0:58-60], [5.1:63-68], [5.2:197-198], [6.0:334-336]
//
// declare-variant-directive ->
// DECLARE_VARIANT([base-name:]variant-name) // since 4.5
struct OmpDeclareVariantDirective {
TUPLE_CLASS_BOILERPLATE(OmpDeclareVariantDirective);
WRAPPER_CLASS_BOILERPLATE(
OmpDeclareVariantDirective, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, std::optional<Name>, Name, OmpClauseList> t;
};

// 2.10.6 declare-target -> DECLARE TARGET (extended-list) |
Expand Down Expand Up @@ -4970,9 +4987,9 @@ struct OpenMPDeclareReductionConstruct {
// 2.8.2 declare-simd -> DECLARE SIMD [(proc-name)] [declare-simd-clause[ [,]
// declare-simd-clause]...]
struct OpenMPDeclareSimdConstruct {
TUPLE_CLASS_BOILERPLATE(OpenMPDeclareSimdConstruct);
WRAPPER_CLASS_BOILERPLATE(
OpenMPDeclareSimdConstruct, OmpDirectiveSpecification);
CharBlock source;
std::tuple<Verbatim, std::optional<Name>, OmpClauseList> t;
};

// ref: [6.0:301-303]
Expand Down
78 changes: 66 additions & 12 deletions flang/lib/Parser/openmp-parsers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,15 +315,56 @@ TYPE_PARSER( //
construct<OmpLocator>(Parser<OmpObject>{}) ||
construct<OmpLocator>(Parser<FunctionReference>{}))

TYPE_PARSER(sourced( //
construct<OmpArgument>(Parser<OmpMapperSpecifier>{}) ||
construct<OmpArgument>(Parser<OmpReductionSpecifier>{}) ||
construct<OmpArgument>(Parser<OmpLocator>{})))
TYPE_PARSER(construct<OmpBaseVariantNames>(
Parser<OmpObject>{} / ":", Parser<OmpObject>{}))

// Make the parsing of OmpArgument directive-sensitive. The issue is that
// name1:name2 can match either OmpBaseVariantNames or OmpReductionSpecifier.
// In the former case, "name2" is a name of a function, in the latter, of a
// type. To resolve the conflict we need information provided by name
// resolution, but by that time we can't modify the AST anymore, and the
// name resolution may have implicitly declared a symbol, or issued a message.
template <llvm::omp::Directive Id = llvm::omp::Directive::OMPD_unknown>
struct OmpArgumentParser {
using resultType = OmpArgument;

std::optional<resultType> Parse(ParseState &state) const {
constexpr auto parser{sourced(first( //
construct<OmpArgument>(Parser<OmpMapperSpecifier>{}),
// By default, prefer OmpReductionSpecifier over OmpBaseVariantNames.
construct<OmpArgument>(Parser<OmpReductionSpecifier>{}),
construct<OmpArgument>(Parser<OmpLocator>{})))};
return parser.Parse(state);
}
};

template <>
struct OmpArgumentParser<llvm::omp::Directive::OMPD_declare_variant> {
using resultType = OmpArgument;

std::optional<resultType> Parse(ParseState &state) const {
constexpr auto parser{sourced(first( //
construct<OmpArgument>(Parser<OmpMapperSpecifier>{}),
// In DECLARE_VARIANT parse OmpBaseVariantNames instead of
// OmpReductionSpecifier.
construct<OmpArgument>(Parser<OmpBaseVariantNames>{}),
construct<OmpArgument>(Parser<OmpLocator>{})))};
return parser.Parse(state);
}
};

TYPE_PARSER(construct<OmpLocatorList>(nonemptyList(Parser<OmpLocator>{})))

TYPE_PARSER(sourced( //
construct<OmpArgumentList>(nonemptyList(Parser<OmpArgument>{}))))
template <llvm::omp::Directive Id = llvm::omp::Directive::OMPD_unknown>
struct OmpArgumentListParser {
using resultType = OmpArgumentList;

std::optional<resultType> Parse(ParseState &state) const {
return sourced(
construct<OmpArgumentList>(nonemptyList(OmpArgumentParser<Id>{})))
.Parse(state);
}
};

TYPE_PARSER( //
construct<OmpTypeSpecifier>(Parser<DeclarationTypeSpec>{}) ||
Expand Down Expand Up @@ -1312,12 +1353,23 @@ TYPE_PARSER(
applyFunction<OmpDirectiveSpecification>(makeFlushFromOldSyntax,
verbatim("FLUSH"_tok) / !lookAhead("("_tok),
maybe(Parser<OmpClauseList>{}),
maybe(parenthesized(Parser<OmpArgumentList>{})),
maybe(parenthesized(
OmpArgumentListParser<llvm::omp::Directive::OMPD_flush>{})),
pure(OmpDirectiveSpecification::Flags::DeprecatedSyntax)))) ||
// Parse DECLARE_VARIANT individually, because the "[base:]variant"
// argument will conflict with DECLARE_REDUCTION's "ident:types...".
predicated(Parser<OmpDirectiveName>{},
IsDirective(llvm::omp::Directive::OMPD_declare_variant)) >=
sourced(construct<OmpDirectiveSpecification>(
sourced(OmpDirectiveNameParser{}),
maybe(parenthesized(OmpArgumentListParser<
llvm::omp::Directive::OMPD_declare_variant>{})),
maybe(Parser<OmpClauseList>{}),
pure(OmpDirectiveSpecification::Flags::None))) ||
// Parse the standard syntax: directive [(arguments)] [clauses]
sourced(construct<OmpDirectiveSpecification>( //
sourced(OmpDirectiveNameParser{}),
maybe(parenthesized(Parser<OmpArgumentList>{})),
maybe(parenthesized(OmpArgumentListParser<>{})),
maybe(Parser<OmpClauseList>{}),
pure(OmpDirectiveSpecification::Flags::None))))

Expand Down Expand Up @@ -1711,8 +1763,9 @@ TYPE_PARSER(construct<OmpInitializerClause>(

// OpenMP 5.2: 7.5.4 Declare Variant directive
TYPE_PARSER(sourced(construct<OmpDeclareVariantDirective>(
verbatim("DECLARE VARIANT"_tok) || verbatim("DECLARE_VARIANT"_tok),
"(" >> maybe(name / ":"), name / ")", Parser<OmpClauseList>{})))
predicated(Parser<OmpDirectiveName>{},
IsDirective(llvm::omp::Directive::OMPD_declare_variant)) >=
Parser<OmpDirectiveSpecification>{})))

// 2.16 Declare Reduction Construct
TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
Expand Down Expand Up @@ -1783,8 +1836,9 @@ TYPE_PARSER(

// 2.8.2 Declare Simd construct
TYPE_PARSER(sourced(construct<OpenMPDeclareSimdConstruct>(
verbatim("DECLARE SIMD"_tok) || verbatim("DECLARE_SIMD"_tok),
maybe(parenthesized(name)), Parser<OmpClauseList>{})))
predicated(Parser<OmpDirectiveName>{},
IsDirective(llvm::omp::Directive::OMPD_declare_simd)) >=
Parser<OmpDirectiveSpecification>{})))

TYPE_PARSER(sourced( //
construct<OpenMPGroupprivate>(
Expand Down
20 changes: 10 additions & 10 deletions flang/lib/Parser/unparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,11 @@ class UnparseVisitor {
// OpenMP Clauses & Directives
void Unparse(const OmpArgumentList &x) { Walk(x.v, ", "); }

void Unparse(const OmpBaseVariantNames &x) {
Walk(std::get<0>(x.t)); // OmpObject
Put(":");
Walk(std::get<1>(x.t)); // OmpObject
}
void Unparse(const OmpTypeNameList &x) { //
Walk(x.v, ",");
}
Expand Down Expand Up @@ -2534,12 +2539,8 @@ class UnparseVisitor {
}
void Unparse(const OmpDeclareVariantDirective &x) {
BeginOpenMP();
Word("!$OMP DECLARE VARIANT ");
Put("(");
Walk(std::get<std::optional<Name>>(x.t), ":");
Walk(std::get<Name>(x.t));
Put(")");
Walk(std::get<OmpClauseList>(x.t));
Word("!$OMP ");
Walk(x.v);
Put("\n");
EndOpenMP();
}
Expand Down Expand Up @@ -2572,11 +2573,10 @@ class UnparseVisitor {
Put("\n");
EndOpenMP();
}
void Unparse(const OpenMPDeclareSimdConstruct &y) {
void Unparse(const OpenMPDeclareSimdConstruct &x) {
BeginOpenMP();
Word("!$OMP DECLARE SIMD ");
Walk("(", std::get<std::optional<Name>>(y.t), ")");
Walk(std::get<OmpClauseList>(y.t));
Word("!$OMP ");
Walk(x.v);
Put("\n");
EndOpenMP();
}
Expand Down
85 changes: 70 additions & 15 deletions flang/lib/Semantics/check-omp-structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -624,21 +624,11 @@ template <typename Checker> struct DirectiveSpellingVisitor {
checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_assumes);
return false;
}
bool Pre(const parser::OpenMPDeclareSimdConstruct &x) {
checker_(
std::get<parser::Verbatim>(x.t).source, Directive::OMPD_declare_simd);
return false;
}
bool Pre(const parser::OpenMPDeclareTargetConstruct &x) {
checker_(
std::get<parser::Verbatim>(x.t).source, Directive::OMPD_declare_target);
return false;
}
bool Pre(const parser::OmpDeclareVariantDirective &x) {
checker_(std::get<parser::Verbatim>(x.t).source,
Directive::OMPD_declare_variant);
return false;
}
bool Pre(const parser::OpenMPGroupprivate &x) {
checker_(x.v.DirName().source, Directive::OMPD_groupprivate);
return false;
Expand Down Expand Up @@ -1361,18 +1351,83 @@ void OmpStructureChecker::Leave(const parser::OpenMPThreadprivate &x) {
}

void OmpStructureChecker::Enter(const parser::OpenMPDeclareSimdConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_declare_simd);
const parser::OmpDirectiveName &dirName{x.v.DirName()};
PushContextAndClauseSets(dirName.source, dirName.v);

const parser::OmpArgumentList &args{x.v.Arguments()};
if (args.v.empty()) {
return;
} else if (args.v.size() > 1) {
context_.Say(args.source,
"DECLARE_SIMD directive should have at most one argument"_err_en_US);
return;
}

const parser::OmpArgument &arg{args.v.front()};
if (auto *sym{GetArgumentSymbol(arg)}) {
if (!IsProcedure(*sym) && !IsFunction(*sym)) {
context_.Say(arg.source,
"The name '%s' should refer to a procedure"_err_en_US, sym->name());
}
if (sym->test(Symbol::Flag::Implicit)) {
context_.Say(arg.source,
"The name '%s' has been implicitly declared"_err_en_US, sym->name());
}
} else {
context_.Say(arg.source,
"The argument to the DECLARE_SIMD directive should be a procedure name"_err_en_US);
}
}

void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) {
dirContext_.pop_back();
}

void OmpStructureChecker::Enter(const parser::OmpDeclareVariantDirective &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContextAndClauseSets(
dir.source, llvm::omp::Directive::OMPD_declare_variant);
const parser::OmpDirectiveName &dirName{x.v.DirName()};
PushContextAndClauseSets(dirName.source, dirName.v);

const parser::OmpArgumentList &args{x.v.Arguments()};
if (args.v.size() != 1) {
context_.Say(args.source,
"DECLARE_VARIANT directive should have a single argument"_err_en_US);
return;
}

auto InvalidArgument{[&](parser::CharBlock source) {
context_.Say(source,
"The argument to the DECLARE_VARIANT directive should be [base-name:]variant-name"_err_en_US);
}};

auto CheckSymbol{[&](const Symbol *sym, parser::CharBlock source) {
if (sym) {
if (!IsProcedure(*sym) && !IsFunction(*sym)) {
context_.Say(source,
"The name '%s' should refer to a procedure"_err_en_US, sym->name());
}
if (sym->test(Symbol::Flag::Implicit)) {
context_.Say(source,
"The name '%s' has been implicitly declared"_err_en_US,
sym->name());
}
} else {
InvalidArgument(source);
}
}};

const parser::OmpArgument &arg{args.v.front()};
common::visit( //
common::visitors{
[&](const parser::OmpBaseVariantNames &y) {
CheckSymbol(GetObjectSymbol(std::get<0>(y.t)), arg.source);
CheckSymbol(GetObjectSymbol(std::get<1>(y.t)), arg.source);
},
[&](const parser::OmpLocator &y) {
CheckSymbol(GetArgumentSymbol(arg), arg.source);
},
[&](auto &&y) { InvalidArgument(arg.source); },
},
arg.u);
}

void OmpStructureChecker::Leave(const parser::OmpDeclareVariantDirective &) {
Expand Down
7 changes: 4 additions & 3 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,9 +473,10 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {

bool Pre(const parser::OpenMPDeclareSimdConstruct &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_declare_simd);
const auto &name{std::get<std::optional<parser::Name>>(x.t)};
if (name) {
ResolveOmpName(*name, Symbol::Flag::OmpDeclareSimd);
for (const parser::OmpArgument &arg : x.v.Arguments().v) {
if (auto *object{omp::GetArgumentObject(arg)}) {
ResolveOmpObject(*object, Symbol::Flag::OmpDeclareSimd);
}
}
return true;
}
Expand Down
Loading