[flang-commits] [flang] [flang] Diagnose empty BIND(C) derived types (PR #193452)

Sairudra More via flang-commits flang-commits at lists.llvm.org
Wed Apr 22 03:09:18 PDT 2026


https://github.com/Saieiei created https://github.com/llvm/llvm-project/pull/193452

Flang was accepting a BIND(C) derived type with no components.

Flang was incorrectly accepting a `BIND(C)` derived type with no components.

Minimal reproducer:
```fortran
type, bind(c) :: t
end type
end

This patch diagnoses that case as a hard semantic error, removes the now-unused warning path, and updates the affected tests. It does not change the handling of non-`BIND(C)` interoperability checks.

Testing note: one Fortran test-suite failure is a direct fallout from this change: `empty_derived_type_f90.test` currently expects an empty `BIND(C`) derived type to compile, so it will need a follow-up update in llvm-test-suite. 

>From 407f78b387b262f333d9bfdc9cbfbbc31a2eeacc Mon Sep 17 00:00:00 2001
From: Sairudra More <moresair at pe31.hpc.amslabs.hpecorp.net>
Date: Wed, 22 Apr 2026 05:03:47 -0500
Subject: [PATCH] [flang] Diagnose empty BIND(C) derived types

Flang was accepting a BIND(C) derived type with no components.

A BIND(C) derived type must have at least one component, so diagnose this
case as a hard semantic error, remove the now-unused warning path, and
update the affected tests.
---
 flang/include/flang/Support/Fortran-features.h | 8 ++++----
 flang/lib/Semantics/check-declarations.cpp     | 8 ++++----
 flang/test/Semantics/bind-c06.f90              | 2 +-
 flang/test/Semantics/bindings01.f90            | 4 ++--
 flang/test/Semantics/resolve70.f90             | 1 +
 flang/test/Semantics/resolve85.f90             | 2 +-
 flang/test/Semantics/typeinfo01.f90            | 4 +++-
 flang/unittests/Common/FortranFeaturesTest.cpp | 3 ---
 8 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index f2bd0d21f25b6..fdf709c15b377 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -42,10 +42,10 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
     HollerithOrCharacterAsBOZ, BindingAsProcedure, StatementFunctionExtensions,
     UseGenericIntrinsicWhenSpecificDoesntMatch, DataStmtExtensions,
     RedundantContiguous, RedundantAttribute, InitBlankCommon,
-    EmptyBindCDerivedType, MiscSourceExtensions, AllocateToOtherLength,
-    LongNames, IntrinsicAsSpecific, BenignNameClash, BenignRedundancy,
-    NullMoldAllocatableComponentValue, NopassScalarBase, MiscUseExtensions,
-    ImpliedDoIndexScope, DistinctCommonSizes, OddIndexVariableRestrictions,
+    MiscSourceExtensions, AllocateToOtherLength, LongNames, IntrinsicAsSpecific,
+    BenignNameClash, BenignRedundancy, NullMoldAllocatableComponentValue,
+    NopassScalarBase, MiscUseExtensions, ImpliedDoIndexScope,
+    DistinctCommonSizes, OddIndexVariableRestrictions,
     IndistinguishableSpecifics, SubroutineAndFunctionSpecifics,
     EmptySequenceType, NonSequenceCrayPointee, BranchIntoConstruct,
     BadBranchTarget, HollerithPolymorphic, ListDirectedSize,
diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp
index 4174cf6d1e340..8c98cdb904381 100644
--- a/flang/lib/Semantics/check-declarations.cpp
+++ b/flang/lib/Semantics/check-declarations.cpp
@@ -3256,10 +3256,10 @@ parser::Messages CheckHelper::WhyNotInteroperableDerivedType(
             "An array component of an interoperable type must have at least one element"_err_en_US);
       }
     }
-    if (derived->componentNames().empty()) { // F'2023 C1805
-      context().Warn(msgs, common::LanguageFeature::EmptyBindCDerivedType,
-          symbol.name(),
-          "A derived type with the BIND attribute should not be empty"_warn_en_US);
+    if (symbol.attrs().test(Attr::BIND_C) &&
+        derived->componentNames().empty()) { // F'2023 C1805
+      msgs.Say(symbol.name(),
+          "A derived type with the BIND(C) attribute must have at least one component"_err_en_US);
     }
   }
   if (msgs.AnyFatalError()) {
diff --git a/flang/test/Semantics/bind-c06.f90 b/flang/test/Semantics/bind-c06.f90
index 608d193ee04de..81c9010e65802 100644
--- a/flang/test/Semantics/bind-c06.f90
+++ b/flang/test/Semantics/bind-c06.f90
@@ -40,7 +40,7 @@ program main
     procedure, nopass :: b => s
   end type
 
-  ! WARNING: A derived type with the BIND attribute should not be empty [-Wempty-bind-c-derived-type]
+  ! ERROR: A derived type with the BIND(C) attribute must have at least one component
   type, bind(c) :: t5
   end type
 
diff --git a/flang/test/Semantics/bindings01.f90 b/flang/test/Semantics/bindings01.f90
index ae02b8f5142df..145f12d24d4c7 100644
--- a/flang/test/Semantics/bindings01.f90
+++ b/flang/test/Semantics/bindings01.f90
@@ -4,7 +4,7 @@
 
 module m
   !ERROR: An ABSTRACT derived type must be extensible
-  !PORTABILITY: A derived type with the BIND attribute should not be empty [-Wempty-bind-c-derived-type]
+  !ERROR: A derived type with the BIND(C) attribute must have at least one component
   type, abstract, bind(c) :: badAbstract1
   end type
   !ERROR: An ABSTRACT derived type must be extensible
@@ -45,7 +45,7 @@ module m
   end type
   type, extends(intermediate) :: concrete2  ! ensure no false missing binding error
   end type
-  !WARNING: A derived type with the BIND attribute should not be empty [-Wempty-bind-c-derived-type]
+  !ERROR: A derived type with the BIND(C) attribute must have at least one component
   type, bind(c) :: inextensible1
   end type
   !ERROR: The parent type is not extensible
diff --git a/flang/test/Semantics/resolve70.f90 b/flang/test/Semantics/resolve70.f90
index 54f0ff6527a7a..0198198a0e591 100644
--- a/flang/test/Semantics/resolve70.f90
+++ b/flang/test/Semantics/resolve70.f90
@@ -48,6 +48,7 @@ subroutine s1()
   type :: extensible
   end type
   type, bind(c) :: inextensible
+    integer :: n
   end type
 
   ! This one's OK
diff --git a/flang/test/Semantics/resolve85.f90 b/flang/test/Semantics/resolve85.f90
index 64b8081dd457b..09e5a074bd7ce 100644
--- a/flang/test/Semantics/resolve85.f90
+++ b/flang/test/Semantics/resolve85.f90
@@ -24,7 +24,7 @@ module m
   end type derived4
 
   !WARNING: Attribute 'BIND(C)' cannot be used more than once [-Wredundant-attribute]
-  !WARNING: A derived type with the BIND attribute should not be empty [-Wempty-bind-c-derived-type]
+  !ERROR: A derived type with the BIND(C) attribute must have at least one component
   type, bind(c), public, bind(c) :: derived5
   end type derived5
 
diff --git a/flang/test/Semantics/typeinfo01.f90 b/flang/test/Semantics/typeinfo01.f90
index bc433a131695a..55fcf177b6035 100644
--- a/flang/test/Semantics/typeinfo01.f90
+++ b/flang/test/Semantics/typeinfo01.f90
@@ -204,6 +204,7 @@ subroutine wu(x,u,iostat,iomsg)
 
 module m10
   type, bind(c) :: t ! non-extensible
+    integer :: n
   end type
   interface read(formatted)
     procedure :: rf
@@ -246,7 +247,8 @@ subroutine wu(x,u,iostat,iomsg)
     integer, intent(out) :: iostat
     character(len=*), intent(inout) :: iomsg
   end subroutine
-!CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t,sizeinbytes=0_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=NULL(),procptr=NULL(),special=.s.t,specialbitset=120_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1)
+!CHECK: .c.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(component) shape: 0_8:0_8 init:[component::component(name=.n.n,genre=1_1,category=0_1,kind=4_1,rank=0_1,memoryspace=0_1,offset=0_8,characterlen=value(genre=1_1,value=0_8),derived=NULL(),lenvalue=NULL(),bounds=NULL(),initialization=NULL())]
+!CHECK: .dt.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(derivedtype) init:derivedtype(binding=NULL(),name=.n.t,sizeinbytes=4_8,uninstantiated=NULL(),kindparameter=NULL(),lenparameterkind=NULL(),component=.c.t,procptr=NULL(),special=.s.t,specialbitset=120_4,hasparent=0_1,noinitializationneeded=1_1,nodestructionneeded=1_1,nofinalizationneeded=1_1,nodefinedassignment=1_1)
 !CHECK: .s.t, SAVE, TARGET (CompilerCreated, ReadOnly): ObjectEntity type: TYPE(specialbinding) shape: 0_8:3_8 init:[specialbinding::specialbinding(which=3_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=rf),specialbinding(which=4_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=ru),specialbinding(which=5_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=wf),specialbinding(which=6_1,isargdescriptorset=0_1,istypebound=0_1,specialcaseflag=0_1,proc=wu)]
 end module
 
diff --git a/flang/unittests/Common/FortranFeaturesTest.cpp b/flang/unittests/Common/FortranFeaturesTest.cpp
index 2caacb5f3dacf..e358fd1d17994 100644
--- a/flang/unittests/Common/FortranFeaturesTest.cpp
+++ b/flang/unittests/Common/FortranFeaturesTest.cpp
@@ -261,9 +261,6 @@ TEST(FortranFeaturesTest, CamelCaseToLowerCaseHyphenated) {
   EXPECT_EQ(CamelCaseToLowerCaseHyphenated(
                 EnumToString(LanguageFeature::InitBlankCommon)),
       "init-blank-common");
-  EXPECT_EQ(CamelCaseToLowerCaseHyphenated(
-                EnumToString(LanguageFeature::EmptyBindCDerivedType)),
-      "empty-bind-c-derived-type");
   EXPECT_EQ(CamelCaseToLowerCaseHyphenated(
                 EnumToString(LanguageFeature::MiscSourceExtensions)),
       "misc-source-extensions");



More information about the flang-commits mailing list