diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index d031993603c15..7b8da73f404cc 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -2483,7 +2483,7 @@ std::optional ExpressionAnalyzer::CheckCall( bool treatExternalAsImplicit{IsExternalCalledImplicitly(callSite, proc)}; if (treatExternalAsImplicit && !chars->CanBeCalledViaImplicitInterface()) { Say(callSite, - "References to the procedure '%s' require an explicit interface"_en_US, + "References to the procedure '%s' require an explicit interface"_err_en_US, DEREF(proc.GetSymbol()).name()); } // Checks for ASSOCIATED() are done in intrinsic table processing diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp index a77d3c83cb2c7..4308260e9fb7c 100644 --- a/flang/lib/Semantics/resolve-names.cpp +++ b/flang/lib/Semantics/resolve-names.cpp @@ -6462,6 +6462,18 @@ void ResolveNamesVisitor::NoteExecutablePartCall( } } +static bool IsLocallyImplicitGlobalSymbol( + const Symbol &symbol, const parser::Name &localName) { + return symbol.owner().IsGlobal() && + (!symbol.scope() || + !symbol.scope()->sourceRange().Contains(localName.source)); +} + +static bool TypesMismatchIfNonNull( + const DeclTypeSpec *type1, const DeclTypeSpec *type2) { + return type1 && type2 && *type1 != *type2; +} + // Check and set the Function or Subroutine flag on symbol; false on error. bool ResolveNamesVisitor::SetProcFlag( const parser::Name &name, Symbol &symbol, Symbol::Flag flag) { @@ -6474,6 +6486,12 @@ bool ResolveNamesVisitor::SetProcFlag( SayWithDecl( name, symbol, "Cannot call subroutine '%s' like a function"_err_en_US); return false; + } else if (flag == Symbol::Flag::Function && + IsLocallyImplicitGlobalSymbol(symbol, name) && + TypesMismatchIfNonNull(symbol.GetType(), GetImplicitType(symbol))) { + SayWithDecl(name, symbol, + "Implicit declaration of function '%s' has a different result type than in previous declaration"_err_en_US); + return false; } else if (symbol.has()) { symbol.set(flag); // in case it hasn't been set yet if (flag == Symbol::Flag::Function) { diff --git a/flang/test/Semantics/call24.f90 b/flang/test/Semantics/call24.f90 new file mode 100644 index 0000000000000..9013a3f621b26 --- /dev/null +++ b/flang/test/Semantics/call24.f90 @@ -0,0 +1,26 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! 15.4.2.2. Test that errors are reported when an explicit interface +! is not provided for an external procedure that requires an explicit +! interface (the definition needs to be visible so that the compiler +! can detect the violation). + +subroutine foo(a_pointer) + real, pointer :: a_pointer(:) +end subroutine + +subroutine test() + real, pointer :: a_pointer(:) + real, pointer :: an_array(:) + + ! This call would be allowed if the interface was explicit here, + ! but its handling with an implicit interface is different (no + ! descriptor involved, copy-in/copy-out...) + + !ERROR: References to the procedure 'foo' require an explicit interface + call foo(a_pointer) + + ! This call would be error if the interface was explicit here. + + !ERROR: References to the procedure 'foo' require an explicit interface + call foo(an_array) +end subroutine diff --git a/flang/test/Semantics/resolve89.f90 b/flang/test/Semantics/resolve89.f90 index a15e54578589c..e929536b8b362 100644 --- a/flang/test/Semantics/resolve89.f90 +++ b/flang/test/Semantics/resolve89.f90 @@ -16,11 +16,11 @@ impure function impureFunc() impureFunc = 3 end function impureFunc -pure function pureFunc() - integer :: pureFunc +pure function iPureFunc() + integer :: iPureFunc - pureFunc = 3 -end function pureFunc + iPureFunc = 3 +end function iPureFunc module m real, allocatable :: mVar @@ -49,7 +49,7 @@ subroutine s(iArg, allocArg, pointerArg, arrayArg, ioArg, optionalArg) ! statement functions referenced below iVolatileStmtFunc() = 3 * volatileVar iImpureStmtFunc() = 3 * impureFunc() - iPureStmtFunc() = 3 * pureFunc() + iPureStmtFunc() = 3 * iPureFunc() ! This is OK real, dimension(merge(1, 2, allocated(mVar))) :: rVar