@@ -1486,34 +1486,16 @@ class OmpVisitor : public virtual DeclarationVisitor {
14861486 bool Pre (const parser::OmpBlockConstruct &);
14871487 void Post (const parser::OmpBlockConstruct &);
14881488 bool Pre (const parser::OmpBeginDirective &x) {
1489- AddOmpSourceRange (x.source );
1490- // Manually resolve names in CRITICAL directives. This is because these
1491- // names do not denote Fortran objects, and the CRITICAL directive causes
1492- // them to be "auto-declared", i.e. inserted into the global scope.
1493- // More specifically, they are not expected to have explicit declarations,
1494- // and if they do the behavior is unspeficied.
1495- if (x.DirName ().v == llvm::omp::Directive::OMPD_critical) {
1496- for (const parser::OmpArgument &arg : x.Arguments ().v ) {
1497- ResolveCriticalName (arg);
1498- }
1499- }
1500- return true ;
1489+ return Pre (static_cast <const parser::OmpDirectiveSpecification &>(x));
15011490 }
1502- void Post (const parser::OmpBeginDirective &) {
1503- messageHandler (). set_currStmtSource (std:: nullopt );
1491+ void Post (const parser::OmpBeginDirective &x ) {
1492+ Post ( static_cast < const parser::OmpDirectiveSpecification &>(x) );
15041493 }
15051494 bool Pre (const parser::OmpEndDirective &x) {
1506- AddOmpSourceRange (x.source );
1507- // Manually resolve names in CRITICAL directives.
1508- if (x.DirName ().v == llvm::omp::Directive::OMPD_critical) {
1509- for (const parser::OmpArgument &arg : x.Arguments ().v ) {
1510- ResolveCriticalName (arg);
1511- }
1512- }
1513- return true ;
1495+ return Pre (static_cast <const parser::OmpDirectiveSpecification &>(x));
15141496 }
1515- void Post (const parser::OmpEndDirective &) {
1516- messageHandler (). set_currStmtSource (std:: nullopt );
1497+ void Post (const parser::OmpEndDirective &x ) {
1498+ Post ( static_cast < const parser::OmpDirectiveSpecification &>(x) );
15171499 }
15181500
15191501 bool Pre (const parser::OpenMPLoopConstruct &) {
@@ -1522,8 +1504,16 @@ class OmpVisitor : public virtual DeclarationVisitor {
15221504 }
15231505 void Post (const parser::OpenMPLoopConstruct &) { PopScope (); }
15241506 bool Pre (const parser::OmpBeginLoopDirective &x) {
1525- AddOmpSourceRange (x.source );
1526- return true ;
1507+ return Pre (static_cast <const parser::OmpDirectiveSpecification &>(x));
1508+ }
1509+ void Post (const parser::OmpBeginLoopDirective &x) {
1510+ Post (static_cast <const parser::OmpDirectiveSpecification &>(x));
1511+ }
1512+ bool Pre (const parser::OmpEndLoopDirective &x) {
1513+ return Pre (static_cast <const parser::OmpDirectiveSpecification &>(x));
1514+ }
1515+ void Post (const parser::OmpEndLoopDirective &x) {
1516+ Post (static_cast <const parser::OmpDirectiveSpecification &>(x));
15271517 }
15281518
15291519 bool Pre (const parser::OpenMPDeclareMapperConstruct &x) {
@@ -1580,35 +1570,22 @@ class OmpVisitor : public virtual DeclarationVisitor {
15801570 }
15811571 bool Pre (const parser::OmpMapClause &);
15821572
1583- void Post (const parser::OmpBeginLoopDirective &) {
1584- messageHandler ().set_currStmtSource (std::nullopt );
1585- }
1586- bool Pre (const parser::OmpEndLoopDirective &x) {
1587- AddOmpSourceRange (x.source );
1588- return true ;
1589- }
1590- void Post (const parser::OmpEndLoopDirective &) {
1591- messageHandler ().set_currStmtSource (std::nullopt );
1592- }
1593-
15941573 bool Pre (const parser::OpenMPSectionsConstruct &) {
15951574 PushScope (Scope::Kind::OtherConstruct, nullptr );
15961575 return true ;
15971576 }
15981577 void Post (const parser::OpenMPSectionsConstruct &) { PopScope (); }
15991578 bool Pre (const parser::OmpBeginSectionsDirective &x) {
1600- AddOmpSourceRange (x.source );
1601- return true ;
1579+ return Pre (static_cast <const parser::OmpDirectiveSpecification &>(x));
16021580 }
1603- void Post (const parser::OmpBeginSectionsDirective &) {
1604- messageHandler (). set_currStmtSource (std:: nullopt );
1581+ void Post (const parser::OmpBeginSectionsDirective &x ) {
1582+ Post ( static_cast < const parser::OmpDirectiveSpecification &>(x) );
16051583 }
16061584 bool Pre (const parser::OmpEndSectionsDirective &x) {
1607- AddOmpSourceRange (x.source );
1608- return true ;
1585+ return Pre (static_cast <const parser::OmpDirectiveSpecification &>(x));
16091586 }
1610- void Post (const parser::OmpEndSectionsDirective &) {
1611- messageHandler (). set_currStmtSource (std:: nullopt );
1587+ void Post (const parser::OmpEndSectionsDirective &x ) {
1588+ Post ( static_cast < const parser::OmpDirectiveSpecification &>(x) );
16121589 }
16131590 bool Pre (const parser::OpenMPThreadprivate &) {
16141591 SkipImplicitTyping (true );
@@ -1718,6 +1695,9 @@ class OmpVisitor : public virtual DeclarationVisitor {
17181695 }
17191696 }
17201697 bool Pre (const parser::OmpDirectiveSpecification &x);
1698+ void Post (const parser::OmpDirectiveSpecification &) {
1699+ messageHandler ().set_currStmtSource (std::nullopt );
1700+ }
17211701
17221702 bool Pre (const parser::OmpTypeSpecifier &x) {
17231703 BeginDeclTypeSpec ();
@@ -1727,6 +1707,16 @@ class OmpVisitor : public virtual DeclarationVisitor {
17271707 EndDeclTypeSpec ();
17281708 }
17291709
1710+ bool Pre (const parser::OpenMPConstruct &x) {
1711+ // Indicate that the current directive is not a declarative one.
1712+ declaratives_.push_back (nullptr );
1713+ return true ;
1714+ }
1715+ void Post (const parser::OpenMPConstruct &) {
1716+ // Pop the null pointer.
1717+ declaratives_.pop_back ();
1718+ }
1719+
17301720private:
17311721 void ProcessMapperSpecifier (const parser::OmpMapperSpecifier &spec,
17321722 const parser::OmpClauseList &clauses);
@@ -1994,30 +1984,40 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {
19941984
19951985 const parser::OmpArgumentList &args{x.Arguments ()};
19961986 const parser::OmpClauseList &clauses{x.Clauses ()};
1987+ bool visitClauses{true };
1988+
1989+ for (const parser::OmpArgument &arg : args.v ) {
1990+ common::visit ( //
1991+ common::visitors{
1992+ [&](const parser::OmpMapperSpecifier &spec) {
1993+ ProcessMapperSpecifier (spec, clauses);
1994+ visitClauses = false ;
1995+ },
1996+ [&](const parser::OmpReductionSpecifier &spec) {
1997+ ProcessReductionSpecifier (spec, clauses, declaratives_.back ());
1998+ visitClauses = false ;
1999+ },
2000+ [&](const parser::OmpLocator &locator) {
2001+ // Manually resolve names in CRITICAL directives. This is because
2002+ // these names do not denote Fortran objects, and the CRITICAL
2003+ // directive causes them to be "auto-declared", i.e. inserted into
2004+ // the global scope. More specifically, they are not expected to
2005+ // have explicit declarations, and if they do the behavior is
2006+ // unspeficied.
2007+ if (x.DirId () == llvm::omp::Directive::OMPD_critical) {
2008+ ResolveCriticalName (arg);
2009+ } else {
2010+ Walk (locator);
2011+ }
2012+ },
2013+ },
2014+ arg.u );
2015+ }
19972016
1998- switch (x.DirId ()) {
1999- case llvm::omp::Directive::OMPD_declare_mapper:
2000- if (!args.v .empty ()) {
2001- const parser::OmpArgument &first{args.v .front ()};
2002- if (auto *spec{std::get_if<parser::OmpMapperSpecifier>(&first.u )}) {
2003- ProcessMapperSpecifier (*spec, clauses);
2004- }
2005- }
2006- break ;
2007- case llvm::omp::Directive::OMPD_declare_reduction:
2008- if (!args.v .empty ()) {
2009- const parser::OmpArgument &first{args.v .front ()};
2010- if (auto *spec{std::get_if<parser::OmpReductionSpecifier>(&first.u )}) {
2011- ProcessReductionSpecifier (*spec, clauses, declaratives_.back ());
2012- }
2013- }
2014- break ;
2015- default :
2016- // Default processing.
2017- Walk (args);
2017+ if (visitClauses) {
20182018 Walk (clauses);
2019- break ;
20202019 }
2020+
20212021 return false ;
20222022}
20232023
0 commit comments