[flang-commits] [flang] [flang][OpenMP] DECLARE VARIANT: add more semantic checks (PR #206714)
via flang-commits
flang-commits at lists.llvm.org
Tue Jun 30 04:41:40 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Abid Qadeer (abidh)
<details>
<summary>Changes</summary>
1. Require the base and variant procedures to have compatible characteristics as required by OpenMP 6.0 section 9.6.
2. Reject adjust_args/append_args as not yet implemented.
---
Full diff: https://github.com/llvm/llvm-project/pull/206714.diff
3 Files Affected:
- (modified) flang/lib/Semantics/check-omp-variant.cpp (+45)
- (modified) flang/test/Semantics/OpenMP/declare-variant-match.f90 (+27)
- (modified) flang/test/Semantics/OpenMP/declare-variant.f90 (+81)
``````````diff
diff --git a/flang/lib/Semantics/check-omp-variant.cpp b/flang/lib/Semantics/check-omp-variant.cpp
index 8b782030c37e3..2dde9c7027bab 100644
--- a/flang/lib/Semantics/check-omp-variant.cpp
+++ b/flang/lib/Semantics/check-omp-variant.cpp
@@ -15,6 +15,7 @@
#include "flang/Common/idioms.h"
#include "flang/Common/indirection.h"
#include "flang/Common/visit.h"
+#include "flang/Evaluate/characteristics.h"
#include "flang/Evaluate/check-expression.h"
#include "flang/Parser/characters.h"
#include "flang/Parser/message.h"
@@ -645,11 +646,50 @@ void OmpStructureChecker::CheckDeclareVariantUserConditions(
}
}
+// OpenMP 6.0, 9.6 (declare_variant), Fortran restriction: "The characteristic
+// of the function variant must be compatible with the characteristic of the
+// base function after the implementation defined transformation for its OpenMP
+// context."
+static void CheckDeclareVariantInterface(SemanticsContext &context,
+ const Symbol &base, const Symbol &variant, parser::CharBlock source) {
+ auto &foldingContext{context.foldingContext()};
+ auto baseChars{
+ evaluate::characteristics::Procedure::Characterize(base, foldingContext)};
+ auto variantChars{evaluate::characteristics::Procedure::Characterize(
+ variant, foldingContext)};
+ // If either procedure cannot be characterized, Characterize has already
+ // emitted diagnostics; do not add more.
+ if (!baseChars || !variantChars) {
+ return;
+ }
+
+ std::string whyNot;
+ if (!baseChars->IsCompatibleWith(
+ *variantChars, /*ignoreImplicitVsExplicit=*/false, &whyNot)) {
+ context.Say(source,
+ "The variant procedure '%s' is not compatible with the base procedure '%s': %s"_err_en_US,
+ variant.name(), base.name(), whyNot);
+ }
+}
+
void OmpStructureChecker::CheckOmpDeclareVariantDirective(
const parser::OmpDeclareVariantDirective &x) {
const parser::OmpDirectiveSpecification &spec{x.v};
const parser::OmpArgumentList &args{spec.Arguments()};
+ bool hasArgModifiers{false};
+ for (const parser::OmpClause &clause : x.v.Clauses().v) {
+ if (clause.Id() == llvm::omp::Clause::OMPC_adjust_args) {
+ hasArgModifiers = true;
+ context_.Say(clause.source,
+ "ADJUST_ARGS clause on the DECLARE VARIANT directive is not yet implemented"_err_en_US);
+ } else if (clause.Id() == llvm::omp::Clause::OMPC_append_args) {
+ hasArgModifiers = true;
+ context_.Say(clause.source,
+ "APPEND_ARGS clause on the DECLARE VARIANT directive is not yet implemented"_err_en_US);
+ }
+ }
+
if (args.v.size() != 1) {
context_.Say(args.source,
"DECLARE_VARIANT directive should have a single argument"_err_en_US);
@@ -711,6 +751,11 @@ void OmpStructureChecker::CheckOmpDeclareVariantDirective(
context_.Say(arg.source,
"Variant '%s' was already specified for '%s' in another DECLARE VARIANT directive"_err_en_US,
variant->name(), base->name());
+ } else if (!hasArgModifiers) {
+ // adjust_args/append_args perform the "transformation for its OpenMP
+ // context", so the variant interface intentionally differs from the
+ // base; skip the same-interface check until they are supported.
+ CheckDeclareVariantInterface(context_, *base, *variant, arg.source);
}
}
diff --git a/flang/test/Semantics/OpenMP/declare-variant-match.f90 b/flang/test/Semantics/OpenMP/declare-variant-match.f90
index 23b8c66a43eed..73558dc171b69 100644
--- a/flang/test/Semantics/OpenMP/declare-variant-match.f90
+++ b/flang/test/Semantics/OpenMP/declare-variant-match.f90
@@ -116,3 +116,30 @@ subroutine vsub
subroutine sub
end subroutine
end subroutine
+
+! ADJUST_ARGS is accepted by parsing but variant selection does not honour it
+! yet.
+subroutine f10
+contains
+ subroutine vsub(v1)
+ integer, value :: v1
+ end subroutine
+ subroutine sub(v1)
+ integer, value :: v1
+!ERROR: ADJUST_ARGS clause on the DECLARE VARIANT directive is not yet implemented
+ !$omp declare variant(vsub) match(construct={dispatch}) adjust_args(nothing: v1)
+ end subroutine
+end subroutine
+
+! APPEND_ARGS is likewise not yet honoured.
+subroutine f11
+contains
+ subroutine vsub(v1)
+ integer, value :: v1
+ end subroutine
+ subroutine sub(v1)
+ integer, value :: v1
+!ERROR: APPEND_ARGS clause on the DECLARE VARIANT directive is not yet implemented
+ !$omp declare variant(vsub) match(construct={dispatch}) append_args(interop(target))
+ end subroutine
+end subroutine
diff --git a/flang/test/Semantics/OpenMP/declare-variant.f90 b/flang/test/Semantics/OpenMP/declare-variant.f90
index b0380d778c75d..45fedf9b0cd75 100644
--- a/flang/test/Semantics/OpenMP/declare-variant.f90
+++ b/flang/test/Semantics/OpenMP/declare-variant.f90
@@ -42,3 +42,84 @@ subroutine sub
integer :: x
end subroutine
end subroutine
+
+subroutine incompatible_argcount
+!ERROR: The variant procedure 'vsub' is not compatible with the base procedure 'sub': distinct numbers of dummy arguments
+ !$omp declare variant (sub:vsub) match (construct={parallel})
+contains
+ subroutine sub(x)
+ integer :: x
+ end subroutine
+ subroutine vsub(x, y)
+ integer :: x, y
+ end subroutine
+end subroutine
+
+subroutine incompatible_argtype
+!ERROR: The variant procedure 'vsub' is not compatible with the base procedure 'sub': incompatible dummy argument #1: incompatible dummy data object types: REAL(4) vs INTEGER(4)
+ !$omp declare variant (sub:vsub) match (construct={parallel})
+contains
+ subroutine sub(x)
+ integer :: x
+ end subroutine
+ subroutine vsub(x)
+ real :: x
+ end subroutine
+end subroutine
+
+subroutine incompatible_function_vs_subroutine
+!ERROR: The variant procedure 'vfun' is not compatible with the base procedure 'sub': incompatible procedures: one is a function, the other a subroutine
+ !$omp declare variant (sub:vfun) match (construct={parallel})
+contains
+ subroutine sub(x)
+ integer :: x
+ end subroutine
+ integer function vfun(x)
+ integer :: x
+ vfun = x
+ end function
+end subroutine
+
+subroutine incompatible_result
+!ERROR: The variant procedure 'fvar' is not compatible with the base procedure 'fbase': function results have distinct types: INTEGER(4) vs REAL(4)
+ !$omp declare variant (fbase:fvar) match (construct={parallel})
+contains
+ integer function fbase(x)
+ integer :: x
+ fbase = x
+ end function
+ real function fvar(x)
+ real :: x
+ fvar = x
+ end function
+end subroutine
+
+! Differing dummy argument names are fine; only characteristics matter.
+
+subroutine compatible_interface
+ !$omp declare variant (sub:vsub) match (construct={parallel})
+contains
+ subroutine sub(x)
+ integer :: x
+ end subroutine
+ subroutine vsub(y)
+ integer :: y
+ end subroutine
+end subroutine
+
+! append_args is rejected as not-yet-implemented. The interface check is also
+! skipped (the appended interop argument intentionally changes the variant
+! interface), so the mismatched argument count does not produce a spurious
+! incompatibility error in addition to the not-yet-implemented one.
+
+subroutine append_args_skips_interface_check
+!ERROR: APPEND_ARGS clause on the DECLARE VARIANT directive is not yet implemented
+ !$omp declare variant (sub:vsub) match (construct={dispatch}) append_args(interop(target))
+contains
+ subroutine sub(x)
+ integer :: x
+ end subroutine
+ subroutine vsub(x, obj)
+ integer :: x, obj
+ end subroutine
+end subroutine
``````````
</details>
https://github.com/llvm/llvm-project/pull/206714
More information about the flang-commits
mailing list