[flang-commits] [flang] 81353cb - [Flang] Avoid crash resolving restricted specific intrinsics (#217852)

via flang-commits flang-commits at lists.llvm.org
Tue Sep 15 08:49:57 PDT 2026


Author: nudt_yixiao
Date: 2026-09-15T11:49:52-04:00
New Revision: 81353cba9f68d1beb5fe220b693f9dc3646d990c

URL: https://github.com/llvm/llvm-project/commit/81353cba9f68d1beb5fe220b693f9dc3646d990c
DIFF: https://github.com/llvm/llvm-project/commit/81353cba9f68d1beb5fe220b693f9dc3646d990c.diff

LOG: [Flang] Avoid crash resolving restricted specific intrinsics (#217852)

Name resolution assumed that every specific intrinsic function handled
in a procedure context was unrestricted and had a numeric result. An
undeclared LLT used as a procedure pointer target therefore triggered a
CHECK because LLT is restricted and returns LOGICAL.

Rename the handler to reflect that it resolves both restricted and
unrestricted specific intrinsic functions. Preserve result types only
for unrestricted intrinsics; restricted intrinsics retain an untyped
symbol so later semantic checks can issue the appropriate diagnostic.

Fixes https://github.com/llvm/llvm-project/issues/208825

Co-authored-by: yixiao <yixiao at hygon.cn>

Added: 
    

Modified: 
    flang/lib/Semantics/resolve-names.cpp
    flang/test/Semantics/resolve46.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 21f83e9d87cc1..20a098d9f0732 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1341,7 +1341,7 @@ class DeclarationVisitor : public ArraySpecVisitor,
       const parser::TypeParamValue &, common::TypeParamAttr attr);
   Attrs HandleSaveName(const SourceName &, Attrs);
   void AddSaveName(std::set<SourceName> &, const SourceName &);
-  bool HandleUnrestrictedSpecificIntrinsicFunction(const parser::Name &);
+  bool HandleSpecificIntrinsicFunction(const parser::Name &);
   const parser::Name *FindComponent(const parser::Name *, const parser::Name &);
   void Initialization(const parser::Name &, const parser::Initialization &,
       bool inComponentDecl);
@@ -8331,10 +8331,13 @@ Symbol &DeclarationVisitor::MakeCommonBlockSymbol(
 }
 
 bool DeclarationVisitor::NameIsKnownOrIntrinsic(const parser::Name &name) {
-  return FindSymbol(name) || HandleUnrestrictedSpecificIntrinsicFunction(name);
+  return FindSymbol(name) || HandleSpecificIntrinsicFunction(name);
 }
 
-bool DeclarationVisitor::HandleUnrestrictedSpecificIntrinsicFunction(
+// Create a symbol for a specific intrinsic function. Unrestricted names
+// receive their result type here; restricted names are kept typeless so
+// that later semantic checks can diagnose their invalid use.
+bool DeclarationVisitor::HandleSpecificIntrinsicFunction(
     const parser::Name &name) {
   if (auto interface{context().intrinsics().IsSpecificIntrinsicFunction(
           name.source.ToString())}) {
@@ -8343,17 +8346,19 @@ bool DeclarationVisitor::HandleUnrestrictedSpecificIntrinsicFunction(
     // INTRINSIC flag will cause this symbol to have a complete interface
     // recreated for it later on demand, but capturing its result type here
     // will make GetType() return a correct result without having to
-    // probe the intrinsics table again.
+    // probe the intrinsics table again.  Restricted specific intrinsic
+    // function names are also resolved here so that their use can be
+    // diagnosed later, but they do not need a result type.
     Symbol &symbol{MakeSymbol(InclusiveScope(), name.source, Attrs{})};
     SetImplicitAttr(symbol, Attr::INTRINSIC);
-    CHECK(interface->functionResult.has_value());
-    evaluate::DynamicType dyType{
-        DEREF(interface->functionResult->GetTypeAndShape()).type()};
-    CHECK(common::IsNumericTypeCategory(dyType.category()));
-    const DeclTypeSpec &typeSpec{
-        MakeNumericType(dyType.category(), dyType.kind())};
     ProcEntityDetails details;
-    details.set_type(typeSpec);
+    if (!interface->isRestrictedSpecific) {
+      CHECK(interface->functionResult.has_value());
+      evaluate::DynamicType dyType{
+          DEREF(interface->functionResult->GetTypeAndShape()).type()};
+      CHECK(common::IsNumericTypeCategory(dyType.category()));
+      details.set_type(MakeNumericType(dyType.category(), dyType.kind()));
+    }
     symbol.set_details(std::move(details));
     symbol.set(Symbol::Flag::Function);
     if (interface->IsElemental()) {

diff  --git a/flang/test/Semantics/resolve46.f90 b/flang/test/Semantics/resolve46.f90
index d473226edaabe..bfa481cd26bbc 100644
--- a/flang/test/Semantics/resolve46.f90
+++ b/flang/test/Semantics/resolve46.f90
@@ -45,3 +45,46 @@ end function chrcmp
   !ERROR: 'llt' is not an unrestricted specific intrinsic procedure
   u => llt
 end program main
+
+! A restricted specific intrinsic used with an implicit procedure interface
+! must be diagnosed even without an explicit INTRINSIC statement.
+subroutine testRestrictedSpecificWithoutIntrinsicStmt
+  procedure(), pointer :: p
+  !ERROR: 'llt' is not an unrestricted specific intrinsic procedure
+  p => llt
+end subroutine
+
+! A restricted specific intrinsic used in a procedure pointer assignment
+! must be diagnosed even without an explicit INTRINSIC statement.
+subroutine testRestrictedSpecificWithoutIntrinsicStmt1
+  !ERROR: 'llt' is not an unrestricted specific intrinsic procedure
+  u => llt
+end subroutine
+
+! Restricted intrinsic used as a procedure pointer interface.
+subroutine testRestrictedSpecificInterfaceWithoutIntrinsicStmt
+  !ERROR: Intrinsic procedure 'llt' is not an unrestricted specific intrinsic permitted for use as the definition of the interface to procedure pointer 'p'
+  procedure(llt), pointer :: p
+end subroutine
+
+! A restricted specific intrinsic used as the initial target of a procedure
+! pointer must be diagnosed even without an explicit INTRINSIC statement.
+subroutine testRestrictedSpecificInitializerWithoutIntrinsicStmt
+  !ERROR: Intrinsic procedure 'llt' is not an unrestricted specific intrinsic permitted for use as the initializer for procedure pointer 'p'
+  procedure(), pointer :: p => llt
+  !ERROR: Intrinsic procedure 'lge' is not an unrestricted specific intrinsic permitted for use as the initializer for procedure pointer 'q'
+  procedure(), pointer :: q => lge
+end subroutine
+
+! Restricted intrinsic with a numeric result.
+subroutine testRestrictedSpecificIntegerWithoutIntrinsicStmt
+  procedure(), pointer :: p
+  !ERROR: 'amin0' is not an unrestricted specific intrinsic procedure
+  p => amin0
+end subroutine
+
+! A restricted intrinsic remains valid when used as an ordinary function call.
+subroutine testRestrictedSpecificCallWithoutIntrinsicStmt
+  logical :: result
+  result = llt('a', 'b')
+end subroutine


        


More information about the flang-commits mailing list