Index: flang/lib/Semantics/check-declarations.cpp =================================================================== --- flang/lib/Semantics/check-declarations.cpp +++ flang/lib/Semantics/check-declarations.cpp @@ -112,6 +112,7 @@ } bool IsResultOkToDiffer(const FunctionResult &); void CheckBindC(const Symbol &); + void CheckBindCFunctionResult(const Symbol &); // Check functions for defined I/O procedures void CheckDefinedIoProc( const Symbol &, const GenericDetails &, GenericKind::DefinedIo); @@ -360,7 +361,9 @@ symbol.Rank() == 0) { // C830 messages_.Say("CONTIGUOUS POINTER must be an array"_err_en_US); } - if (IsDummy(symbol)) { + bool dummy{IsDummy(symbol)}; + bool funcRes{IsFunctionResult(symbol)}; + if (dummy) { if (IsNamedConstant(symbol)) { messages_.Say( "A dummy argument may not also be a named constant"_err_en_US); @@ -370,7 +373,7 @@ messages_.Say( "A dummy argument may not have the SAVE attribute"_err_en_US); } - } else if (IsFunctionResult(symbol)) { + } else if (funcRes) { if (IsNamedConstant(symbol)) { messages_.Say( "A function result may not also be a named constant"_err_en_US); @@ -380,6 +383,29 @@ messages_.Say( "A function result may not have the SAVE attribute"_err_en_US); } + CheckBindCFunctionResult(symbol); + } + if (dummy || funcRes) { + if (innermostSymbol_ && IsBindCProcedure(*innermostSymbol_)) { + if (const DeclTypeSpec * type{symbol.GetType()}; + type && type->category() == DeclTypeSpec::Character) { + bool isConstOne{false}; // 18.3.1(1) + if (const auto &len{type->characterTypeSpec().length().GetExplicit()}) { + if (auto constLen{evaluate::ToInt64(*len)}) { + isConstOne = constLen == 1; + } + } + if (!isConstOne) { + if (funcRes) { + messages_.Say( + "BIND(C) function result must have the length type parameter of value 1 if it is character type"_err_en_US); + } else { + messages_.Say( + "BIND(C) procedure argument must have the length type parameter of value 1 if it is character type"_err_en_US); + } + } + } + } } if (symbol.owner().IsDerivedType() && (symbol.attrs().test(Attr::CONTIGUOUS) && @@ -397,6 +423,22 @@ void CheckHelper::CheckCommonBlock(const Symbol &symbol) { CheckBindC(symbol); } +void CheckHelper::CheckBindCFunctionResult(const Symbol &symbol) { // C1553 + if (!innermostSymbol_ || !IsBindCProcedure(*innermostSymbol_)) { + return; + } + if (IsPointer(symbol) || IsAllocatable(symbol)) { + messages_.Say( + "BIND(C) function result cannot have ALLOCATABLE or POINTER attribute"_err_en_US); + } + if (symbol.Rank() > 0) { + messages_.Say("BIND(C) function result must be scalar"_err_en_US); + } + if (symbol.Corank()) { + messages_.Say("BIND(C) function result cannot be a coarray"_err_en_US); + } +} + void CheckHelper::CheckValue( const Symbol &symbol, const DerivedTypeSpec *derived) { // C863 - C865 if (!IsDummy(symbol)) { Index: flang/test/Semantics/bind-c09.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/bind-c09.f90 @@ -0,0 +1,57 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! Check for C1553 and 18.3.4(1) + +function func1() result(res) bind(c) + ! ERROR: BIND(C) function result cannot have ALLOCATABLE or POINTER attribute + integer, pointer :: res +end + +function func2() result(res) bind(c) + ! ERROR: BIND(C) function result cannot have ALLOCATABLE or POINTER attribute + integer, allocatable :: res +end + +function func3() result(res) bind(c) + ! ERROR: BIND(C) function result must be scalar + integer :: res(2) +end + +function func4(arg) result(res) bind(c) + ! ERROR: BIND(C) function result must have the length type parameter of value 1 if it is character type + character(*) :: res + ! ERROR: BIND(C) procedure argument must have the length type parameter of value 1 if it is character type + character(*) :: arg +end + +function func5(n, arg) result(res) bind(c) + integer :: n + ! ERROR: BIND(C) function result must have the length type parameter of value 1 if it is character type + character(n) :: res + ! ERROR: BIND(C) procedure argument must have the length type parameter of value 1 if it is character type + character(n) :: arg +end + +function func6(arg) result(res) bind(c) + ! ERROR: BIND(C) function result must have the length type parameter of value 1 if it is character type + character(2) :: res + ! ERROR: BIND(C) procedure argument must have the length type parameter of value 1 if it is character type + character(2) :: arg +end + +function func7(arg) result(res) bind(c) + integer, parameter :: n = 1 + character(n) :: res, arg! OK +end + +function func8(arg) result(res) bind(c) + ! ERROR: BIND(C) function result cannot have ALLOCATABLE or POINTER attribute + ! ERROR: BIND(C) function result must have the length type parameter of value 1 if it is character type + character(:), pointer :: res + ! ERROR: BIND(C) procedure argument must have the length type parameter of value 1 if it is character type + character(:), pointer :: arg +end + +function func9() result(res) bind(c) + ! ERROR: BIND(C) function result cannot be a coarray + integer :: res[10, *] +end