diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -407,33 +407,36 @@ genIfClause(converter, ifClause, ifCond, stmtCtx); } else if (const auto *selfClause = std::get_if(&clause.u)) { - const Fortran::parser::AccSelfClause &accSelfClause = selfClause->v; - if (const auto *optCondition = - std::get_if>( - &accSelfClause.u)) { - if (*optCondition) { - mlir::Value cond = fir::getBase(converter.genExprValue( - *Fortran::semantics::GetExpr(*optCondition), stmtCtx)); - selfCond = firOpBuilder.createConvert(currentLocation, - firOpBuilder.getI1Type(), cond); - } else { - addSelfAttr = true; - } - } else if (const auto *accClauseList = - std::get_if( - &accSelfClause.u)) { - // TODO This would be nicer to be done in canonicalization step. - if (accClauseList->v.size() == 1) { - const auto &accObject = accClauseList->v.front(); - if (const auto *designator = - std::get_if(&accObject.u)) { - if (const auto *name = getDesignatorNameIfDataRef(*designator)) { - auto cond = converter.getSymbolAddress(*name->symbol); - selfCond = firOpBuilder.createConvert( - currentLocation, firOpBuilder.getI1Type(), cond); + const std::optional &accSelfClause = + selfClause->v; + if (accSelfClause) { + if (const auto *optCondition = + std::get_if>( + &(*accSelfClause).u)) { + if (*optCondition) { + mlir::Value cond = fir::getBase(converter.genExprValue( + *Fortran::semantics::GetExpr(*optCondition), stmtCtx)); + selfCond = firOpBuilder.createConvert( + currentLocation, firOpBuilder.getI1Type(), cond); + } + } else if (const auto *accClauseList = + std::get_if( + &(*accSelfClause).u)) { + // TODO This would be nicer to be done in canonicalization step. + if (accClauseList->v.size() == 1) { + const auto &accObject = accClauseList->v.front(); + if (const auto *designator = + std::get_if(&accObject.u)) { + if (const auto *name = getDesignatorNameIfDataRef(*designator)) { + auto cond = converter.getSymbolAddress(*name->symbol); + selfCond = firOpBuilder.createConvert( + currentLocation, firOpBuilder.getI1Type(), cond); + } } } } + } else { + addSelfAttr = true; } } else if (const auto *copyClause = std::get_if(&clause.u)) { diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp --- a/flang/lib/Parser/openacc-parsers.cpp +++ b/flang/lib/Parser/openacc-parsers.cpp @@ -98,8 +98,8 @@ parenthesized(construct( Parser{} / ":", Parser{})))) || - "SELF" >> construct( - construct(Parser{})) || + "SELF" >> construct(construct( + maybe(parenthesized(Parser{})))) || "SEQ" >> construct(construct()) || "TILE" >> construct(construct( parenthesized(Parser{}))) || @@ -178,8 +178,8 @@ // SELF clause is either a simple optional condition for compute construct // or a synonym of the HOST clause for the update directive 2.14.4 holding // an object list. -TYPE_PARSER(construct(parenthesized(Parser{})) || - construct(maybe(parenthesized(scalarLogicalExpr)))) +TYPE_PARSER(construct(Parser{}) || + construct(scalarLogicalExpr)) // Modifier for copyin, copyout, cache and create TYPE_PARSER(construct( diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp --- a/flang/lib/Semantics/check-acc-structure.cpp +++ b/flang/lib/Semantics/check-acc-structure.cpp @@ -409,17 +409,20 @@ void AccStructureChecker::Enter(const parser::AccClause::Self &x) { CheckAllowed(llvm::acc::Clause::ACCC_self); - const parser::AccSelfClause &accSelfClause = x.v; + const std::optional &accSelfClause = x.v; if (GetContext().directive == llvm::acc::Directive::ACCD_update && - std::holds_alternative>( - accSelfClause.u)) { + ((accSelfClause && + std::holds_alternative>( + (*accSelfClause).u)) || + !accSelfClause)) { context_.Say(GetContext().clauseSource, "SELF clause on the %s directive must have a var-list"_err_en_US, ContextDirectiveAsFortran()); } else if (GetContext().directive != llvm::acc::Directive::ACCD_update && - std::holds_alternative(accSelfClause.u)) { + accSelfClause && + std::holds_alternative((*accSelfClause).u)) { const auto &accObjectList = - std::get(accSelfClause.u); + std::get((*accSelfClause).u); if (accObjectList.v.size() != 1) { context_.Say(GetContext().clauseSource, "SELF clause on the %s directive only accepts optional scalar logical" diff --git a/llvm/include/llvm/Frontend/OpenACC/ACC.td b/llvm/include/llvm/Frontend/OpenACC/ACC.td --- a/llvm/include/llvm/Frontend/OpenACC/ACC.td +++ b/llvm/include/llvm/Frontend/OpenACC/ACC.td @@ -218,6 +218,7 @@ // 2.5.6 def ACCC_Self : Clause<"self"> { let flangClass = "AccSelfClause"; + let isValueOptional = true; } // 2.9.5