[flang-commits] [flang] [flang][OpenMP] DECLARE VARIANT: add more semantic checks (PR #206714)

Abid Qadeer via flang-commits flang-commits at lists.llvm.org
Tue Jun 30 04:41:01 PDT 2026


https://github.com/abidh created https://github.com/llvm/llvm-project/pull/206714

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.

>From 6c7769c57b63346f2aa88e2fb201b0e1f4f7c006 Mon Sep 17 00:00:00 2001
From: Abid Qadeer <haqadeer at amd.com>
Date: Mon, 29 Jun 2026 19:32:57 +0100
Subject: [PATCH] [flang][OpenMP] DECLARE VARIANT: add more semantic checks

1. Require the base and variant procedures to have compatible characteristics
   as required by OpenMP 6.0, 9.6.
2. Reject adjust_args/append_args as not yet implemented.
---
 flang/lib/Semantics/check-omp-variant.cpp     | 45 +++++++++++
 .../OpenMP/declare-variant-match.f90          | 27 +++++++
 .../test/Semantics/OpenMP/declare-variant.f90 | 81 +++++++++++++++++++
 3 files changed, 153 insertions(+)

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



More information about the flang-commits mailing list