[flang-commits] [flang] [flang] Fix USE merge for renamed ISO_FORTRAN_ENV COMPILER_* vs user generic (PR #217005)
via flang-commits
flang-commits at lists.llvm.org
Tue Aug 18 05:14:07 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: ejose02
<details>
<summary>Changes</summary>
Issue : Flang rejected merging use-associated compiler_version/compiler_options (renamed to __builtin_* intrinsics) with a same-named user generic because DoAddUse compared ultimate symbol names, producing spurious "ambiguous" errors.
Fix : Compare local USE names for intrinsic+generic merge, record the intrinsic on the merged generic, and probe the intrinsic table when resolving calls on a generic whose same-name specific is intrinsic. Added a regression test.
---
Full diff: https://github.com/llvm/llvm-project/pull/217005.diff
3 Files Affected:
- (modified) flang/lib/Semantics/expression.cpp (+14-5)
- (modified) flang/lib/Semantics/resolve-names.cpp (+7-2)
- (added) flang/test/Semantics/compiler-version-generic.f90 (+50)
``````````diff
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index fc57cc43e981c..0caf10796d5f5 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -3188,22 +3188,31 @@ auto ExpressionAnalyzer::ResolveGeneric(const Symbol &symbol,
bool isSubroutine, SymbolVector &&tried, bool mightBeStructureConstructor)
-> GenericResolution {
const Symbol &ultimate{symbol.GetUltimate()};
- // Check for a match with an explicit INTRINSIC
+ const auto *genericDetails{ultimate.detailsIf<semantics::GenericDetails>()};
const Symbol *explicitIntrinsic{nullptr};
- if (ultimate.attrs().test(semantics::Attr::INTRINSIC)) {
+ auto probeIntrinsic{[&](const Symbol &intrinsic) {
parser::Messages buffer;
auto restorer{GetContextualMessages().SetMessages(buffer)};
ActualArguments localActuals{actuals};
if (context_.intrinsics().Probe(
- CallCharacteristics{ultimate.name().ToString(), isSubroutine},
+ CallCharacteristics{intrinsic.name().ToString(), isSubroutine},
localActuals, foldingContext_) &&
!buffer.AnyFatalError()) {
- explicitIntrinsic = &ultimate;
+ explicitIntrinsic = &intrinsic;
+ }
+ }};
+ if (ultimate.attrs().test(semantics::Attr::INTRINSIC)) {
+ probeIntrinsic(ultimate);
+ } else if (genericDetails) {
+ if (const Symbol *sameNameSpecific{genericDetails->specific()}) {
+ const Symbol &specificUltimate{sameNameSpecific->GetUltimate()};
+ if (specificUltimate.attrs().test(semantics::Attr::INTRINSIC)) {
+ probeIntrinsic(specificUltimate);
+ }
}
}
const Symbol *elemental{nullptr}; // matching elemental specific proc
const Symbol *nonElemental{nullptr}; // matching non-elemental specific
- const auto *genericDetails{ultimate.detailsIf<semantics::GenericDetails>()};
if (genericDetails && !explicitIntrinsic) {
std::optional<CudaMatchingDistance> crtMatchingDistance;
for (const Symbol &specific0 : genericDetails->specificProcs()) {
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 27c4e96d269aa..2f8c218c6be2c 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -4481,8 +4481,8 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
} else if (&useUltimate == &BypassGeneric(localUltimate).GetUltimate()) {
return; // nothing to do; used subprogram is local's specific
} else if (useUltimate.attrs().test(Attr::INTRINSIC) &&
- useUltimate.name() == localSymbol->name()) {
- return; // local generic can extend intrinsic
+ useSymbol.name() == localSymbol->name()) {
+ // Fall through to merge the intrinsic into the generic.
} else {
for (const auto &ref : localGeneric->specificProcs()) {
if (&ref->GetUltimate() == &useUltimate) {
@@ -4504,6 +4504,9 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
UseDetails{localName, useUltimate})};
newSymbol.flags() = useSymbol.flags();
return;
+ } else if (localSymbol->attrs().test(Attr::INTRINSIC) &&
+ useSymbol.name() == localSymbol->name() &&
+ localUltimate.name() != useUltimate.name()) {
} else {
for (const auto &ref : useGeneric->specificProcs()) {
if (&ref->GetUltimate() == &localUltimate) {
@@ -4581,6 +4584,8 @@ void ModuleVisitor::DoAddUse(SourceName location, SourceName localName,
localGeneric->AddSpecificProc(useSpecific, useBindingName);
}
}
+ } else if (useUltimate.attrs().test(Attr::INTRINSIC)) {
+ AddGenericUse(*localGeneric, localName, useSymbol);
}
localGeneric->clear_derivedType();
if (combinedDerivedType) {
diff --git a/flang/test/Semantics/compiler-version-generic.f90 b/flang/test/Semantics/compiler-version-generic.f90
new file mode 100644
index 0000000000000..89f29ce7cf955
--- /dev/null
+++ b/flang/test/Semantics/compiler-version-generic.f90
@@ -0,0 +1,50 @@
+! RUN: %flang_fc1 -fsyntax-only %s
+! Test merging USE of ISO_FORTRAN_ENV compiler_version/compiler_options
+! with a user generic of the same local name.
+
+module user_cv_co
+ interface compiler_version
+ module procedure okp
+ end interface
+ interface compiler_options
+ module procedure oko
+ end interface
+contains
+ function okp(f)
+ character(:), allocatable :: okp
+ logical, intent(in) :: f
+ okp = merge('user:ok ', 'user:fail', f)
+ end function
+ function oko(f)
+ character(:), allocatable :: oko
+ logical, intent(in) :: f
+ oko = merge('opts:ok ', 'opts:fail', f)
+ end function
+end module
+
+program compiler_version_generic_use
+ call order1()
+ call order2()
+contains
+ subroutine order1()
+ use iso_fortran_env, only: compiler_version, compiler_options
+ use user_cv_co
+ character(*), parameter :: bufv = compiler_version()
+ character(*), parameter :: bufo = compiler_options()
+ print *, bufv
+ print *, bufo
+ print *, compiler_version(.true.), ' or ', compiler_version(.false.)
+ print *, compiler_options(.true.), ' or ', compiler_options(.false.)
+ end subroutine
+
+ subroutine order2()
+ use user_cv_co
+ use iso_fortran_env, only: compiler_version, compiler_options
+ character(*), parameter :: bufv = compiler_version()
+ character(*), parameter :: bufo = compiler_options()
+ print *, bufv
+ print *, bufo
+ print *, compiler_version(.true.), ' or ', compiler_version(.false.)
+ print *, compiler_options(.true.), ' or ', compiler_options(.false.)
+ end subroutine
+end program
``````````
</details>
https://github.com/llvm/llvm-project/pull/217005
More information about the flang-commits
mailing list