From 62538b2c4c70eeef52886092e24c97a9a7699a00 Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 18 Apr 2018 13:56:01 -0400 Subject: Fortran: Refactor to treat .mod extension as part of module name When tracking module names internally, include the `.mod` extension. This will later be useful to distinguish them from `.smod` extensions for submodules. --- Source/cmDependsFortran.cxx | 56 ++++++++++++++++++++++++++------------- Source/cmFortranParser.h | 5 ++-- Source/cmFortranParserImpl.cxx | 25 ++++++++++++----- Source/cmGlobalNinjaGenerator.cxx | 2 +- 4 files changed, 60 insertions(+), 28 deletions(-) diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index 1a66ca0..da644dd 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -10,6 +10,7 @@ #include #include +#include "cmAlgorithms.h" #include "cmFortranParser.h" /* Interface to parser object. */ #include "cmGeneratedFileStream.h" #include "cmLocalGenerator.h" @@ -23,6 +24,20 @@ // use lower case and some always use upper case. I do not know if any // use the case from the source code. +static void cmFortranModuleAppendUpperLower(std::string const& mod, + std::string& mod_upper, + std::string& mod_lower) +{ + std::string::size_type ext_len = 0; + if (cmHasLiteralSuffix(mod, ".mod")) { + ext_len = 4; + } + std::string const& name = mod.substr(0, mod.size() - ext_len); + std::string const& ext = mod.substr(mod.size() - ext_len); + mod_upper += cmSystemTools::UpperCase(name) + ext; + mod_lower += mod; +} + class cmDependsFortranInternals { public: @@ -181,16 +196,13 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, for (std::string const& i : provides) { std::string mod_upper = mod_dir; mod_upper += "/"; - mod_upper += cmSystemTools::UpperCase(i); - mod_upper += ".mod"; std::string mod_lower = mod_dir; mod_lower += "/"; - mod_lower += i; - mod_lower += ".mod"; + cmFortranModuleAppendUpperLower(i, mod_upper, mod_lower); std::string stamp = stamp_dir; stamp += "/"; stamp += i; - stamp += ".mod.stamp"; + stamp += ".stamp"; fcStream << "\n"; fcStream << " \"" << this->MaybeConvertToRelativePath(currentBinDir, mod_lower) @@ -270,7 +282,13 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin, if (line[0] == ' ') { if (doing_provides) { - this->ConsiderModule(line.c_str() + 1, stampDir); + std::string mod = line; + if (!cmHasLiteralSuffix(mod, ".mod")) { + // Support fortran.internal files left by older versions of CMake. + // They do not include the ".mod" extension. + mod += ".mod"; + } + this->ConsiderModule(mod.c_str() + 1, stampDir); } } else if (line == "provides") { doing_provides = true; @@ -292,7 +310,7 @@ void cmDependsFortran::ConsiderModule(const char* name, const char* stampDir) std::string stampFile = stampDir; stampFile += "/"; stampFile += name; - stampFile += ".mod.stamp"; + stampFile += ".stamp"; required->second = stampFile; } } @@ -366,7 +384,6 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, // Always use lower case for the mod stamp file name. The // cmake_copy_f90_mod will call back to this class, which will // try various cases for the real mod file name. - std::string m = cmSystemTools::LowerCase(i); std::string modFile = mod_dir; modFile += "/"; modFile += i; @@ -375,8 +392,8 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, cmOutputConverter::SHELL); std::string stampFile = stamp_dir; stampFile += "/"; - stampFile += m; - stampFile += ".mod.stamp"; + stampFile += i; + stampFile += ".stamp"; stampFile = this->MaybeConvertToRelativePath(binDir, stampFile); std::string const stampFileForShell = this->LocalGenerator->ConvertToOutputFormat(stampFile, @@ -423,10 +440,9 @@ bool cmDependsFortran::WriteDependenciesReal(const char* obj, bool cmDependsFortran::FindModule(std::string const& name, std::string& module) { // Construct possible names for the module file. - std::string mod_upper = cmSystemTools::UpperCase(name); - std::string mod_lower = name; - mod_upper += ".mod"; - mod_lower += ".mod"; + std::string mod_upper; + std::string mod_lower; + cmFortranModuleAppendUpperLower(name, mod_upper, mod_lower); // Search the include path for the module. std::string fullName; @@ -470,17 +486,19 @@ bool cmDependsFortran::CopyModule(const std::vector& args) if (args.size() >= 5) { compilerId = args[4]; } + if (!cmHasLiteralSuffix(mod, ".mod")) { + // Support depend.make files left by older versions of CMake. + // They do not include the ".mod" extension. + mod += ".mod"; + } std::string mod_dir = cmSystemTools::GetFilenamePath(mod); if (!mod_dir.empty()) { mod_dir += "/"; } std::string mod_upper = mod_dir; - mod_upper += cmSystemTools::UpperCase(cmSystemTools::GetFilenameName(mod)); std::string mod_lower = mod_dir; - mod_lower += cmSystemTools::LowerCase(cmSystemTools::GetFilenameName(mod)); - mod += ".mod"; - mod_upper += ".mod"; - mod_lower += ".mod"; + cmFortranModuleAppendUpperLower(cmSystemTools::GetFilenameName(mod), + mod_upper, mod_lower); if (cmSystemTools::FileExists(mod_upper, true)) { if (cmDependsFortran::ModulesDiffer(mod_upper.c_str(), stamp.c_str(), compilerId.c_str())) { diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 3f5ad87..5a0bb09 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -39,11 +39,12 @@ int cmFortranParser_GetOldStartcond(cmFortranParser* parser); /* Callbacks for parser. */ void cmFortranParser_Error(cmFortranParser* parser, const char* message); -void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name); +void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name); void cmFortranParser_RuleLineDirective(cmFortranParser* parser, const char* filename); void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name); -void cmFortranParser_RuleModule(cmFortranParser* parser, const char* name); +void cmFortranParser_RuleModule(cmFortranParser* parser, + const char* module_name); void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* name); void cmFortranParser_RuleUndef(cmFortranParser* parser, const char* name); void cmFortranParser_RuleIfdef(cmFortranParser* parser, const char* name); diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx index dd4f16b..e4a6ac7 100644 --- a/Source/cmFortranParserImpl.cxx +++ b/Source/cmFortranParserImpl.cxx @@ -168,11 +168,16 @@ void cmFortranParser_Error(cmFortranParser* parser, const char* msg) parser->Error = msg ? msg : "unknown error"; } -void cmFortranParser_RuleUse(cmFortranParser* parser, const char* name) +void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name) { - if (!parser->InPPFalseBranch) { - parser->Info.Requires.insert(cmSystemTools::LowerCase(name)); + if (parser->InPPFalseBranch) { + return; } + + // syntax: "use module_name" + // requires: "module_name.mod" + std::string const& mod_name = cmSystemTools::LowerCase(module_name); + parser->Info.Requires.insert(mod_name + ".mod"); } void cmFortranParser_RuleLineDirective(cmFortranParser* parser, @@ -225,10 +230,18 @@ void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name) } } -void cmFortranParser_RuleModule(cmFortranParser* parser, const char* name) +void cmFortranParser_RuleModule(cmFortranParser* parser, + const char* module_name) { - if (!parser->InPPFalseBranch && !parser->InInterface) { - parser->Info.Provides.insert(cmSystemTools::LowerCase(name)); + if (parser->InPPFalseBranch) { + return; + } + + if (!parser->InInterface) { + // syntax: "module module_name" + // provides: "module_name.mod" + std::string const& mod_name = cmSystemTools::LowerCase(module_name); + parser->Info.Provides.insert(mod_name + ".mod"); } } diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 599e27c..2a8576f 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1812,7 +1812,7 @@ bool cmGlobalNinjaGenerator::WriteDyndepFile( Json::Value tm = Json::objectValue; for (cmFortranObjectInfo const& object : objects) { for (std::string const& p : object.Provides) { - std::string const mod = module_dir + p + ".mod"; + std::string const mod = module_dir + p; mod_files[p] = mod; tm[p] = mod; } -- cgit v0.12 From 402735314ec7fe48ec21e5f4c5b19b6f17682c54 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 19 Apr 2018 09:21:58 -0400 Subject: Fortran: Add support for submodule dependencies Since commit v3.7.0-rc1~73^2~1 (Fortran: Add support for submodule syntax in dependency scanning, 2016-09-05) we support parsing Fortran sources that use submodule syntax, but it left addition of `.smod` dependencies to future work. Add it now. The syntax submodule (module_name) submodule_name means the current source requires `module_name.mod` and provides `module_name@submodule_name.smod`. The syntax submodule (module_name:submodule_name) nested_submodule_name means the current source requires `module_name@submodule_name.smod` provides `module_name@nested_submodule_name.smod`. Fixes: #17017 --- Help/release/dev/fortran-submodule-depends.rst | 7 ++++ Source/LexerParser/cmFortranParser.cxx | 4 +- Source/LexerParser/cmFortranParser.y | 4 +- Source/cmDependsFortran.cxx | 7 +++- Source/cmFortranParser.h | 7 ++++ Source/cmFortranParserImpl.cxx | 44 ++++++++++++++++++++ Tests/FortranModules/Submodules/CMakeLists.txt | 21 +++++++++- Tests/FortranModules/Submodules/child.f90 | 10 +++++ Tests/FortranModules/Submodules/grandchild.f90 | 8 ++++ Tests/FortranModules/Submodules/parent.f90 | 17 ++++++++ Tests/FortranModules/Submodules/provide.f90 | 57 -------------------------- Tests/FortranModules/Submodules/sibling.f90 | 4 ++ 12 files changed, 126 insertions(+), 64 deletions(-) create mode 100644 Help/release/dev/fortran-submodule-depends.rst create mode 100644 Tests/FortranModules/Submodules/child.f90 create mode 100644 Tests/FortranModules/Submodules/grandchild.f90 create mode 100644 Tests/FortranModules/Submodules/parent.f90 delete mode 100644 Tests/FortranModules/Submodules/provide.f90 create mode 100644 Tests/FortranModules/Submodules/sibling.f90 diff --git a/Help/release/dev/fortran-submodule-depends.rst b/Help/release/dev/fortran-submodule-depends.rst new file mode 100644 index 0000000..b795a84 --- /dev/null +++ b/Help/release/dev/fortran-submodule-depends.rst @@ -0,0 +1,7 @@ +fortran-submodule-depends +------------------------- + +* Fortran dependency scanning now supports dependencies implied by + `Fortran Submodules`_. + +.. _`Fortran Submodules`: http://fortranwiki.org/fortran/show/Submodules diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 2b3452f..00c8a8a 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -1563,7 +1563,7 @@ yyreduce: #line 119 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - cmFortranParser_RuleUse(parser, (yyvsp[-4].string)); + cmFortranParser_RuleSubmodule(parser, (yyvsp[-4].string), (yyvsp[-2].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); } @@ -1574,7 +1574,7 @@ yyreduce: #line 125 "cmFortranParser.y" /* yacc.c:1646 */ { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - cmFortranParser_RuleUse(parser, (yyvsp[-6].string)); + cmFortranParser_RuleSubmoduleNested(parser, (yyvsp[-6].string), (yyvsp[-4].string), (yyvsp[-2].string)); free((yyvsp[-6].string)); free((yyvsp[-4].string)); free((yyvsp[-2].string)); diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index acfb40a..5e09248 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -118,13 +118,13 @@ stmt: } | SUBMODULE LPAREN WORD RPAREN WORD other EOSTMT { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - cmFortranParser_RuleUse(parser, $3); + cmFortranParser_RuleSubmodule(parser, $3, $5); free($3); free($5); } | SUBMODULE LPAREN WORD COLON WORD RPAREN WORD other EOSTMT { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); - cmFortranParser_RuleUse(parser, $3); + cmFortranParser_RuleSubmoduleNested(parser, $3, $5, $7); free($3); free($5); free($7); diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index da644dd..dbea15a 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -31,6 +31,8 @@ static void cmFortranModuleAppendUpperLower(std::string const& mod, std::string::size_type ext_len = 0; if (cmHasLiteralSuffix(mod, ".mod")) { ext_len = 4; + } else if (cmHasLiteralSuffix(mod, ".smod")) { + ext_len = 5; } std::string const& name = mod.substr(0, mod.size() - ext_len); std::string const& ext = mod.substr(mod.size() - ext_len); @@ -283,7 +285,8 @@ void cmDependsFortran::MatchRemoteModules(std::istream& fin, if (line[0] == ' ') { if (doing_provides) { std::string mod = line; - if (!cmHasLiteralSuffix(mod, ".mod")) { + if (!cmHasLiteralSuffix(mod, ".mod") && + !cmHasLiteralSuffix(mod, ".smod")) { // Support fortran.internal files left by older versions of CMake. // They do not include the ".mod" extension. mod += ".mod"; @@ -486,7 +489,7 @@ bool cmDependsFortran::CopyModule(const std::vector& args) if (args.size() >= 5) { compilerId = args[4]; } - if (!cmHasLiteralSuffix(mod, ".mod")) { + if (!cmHasLiteralSuffix(mod, ".mod") && !cmHasLiteralSuffix(mod, ".smod")) { // Support depend.make files left by older versions of CMake. // They do not include the ".mod" extension. mod += ".mod"; diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 5a0bb09..efcd100 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -45,6 +45,13 @@ void cmFortranParser_RuleLineDirective(cmFortranParser* parser, void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name); void cmFortranParser_RuleModule(cmFortranParser* parser, const char* module_name); +void cmFortranParser_RuleSubmodule(cmFortranParser* parser, + const char* module_name, + const char* submodule_name); +void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser, + const char* module_name, + const char* submodule_name, + const char* nested_submodule_name); void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* name); void cmFortranParser_RuleUndef(cmFortranParser* parser, const char* name); void cmFortranParser_RuleIfdef(cmFortranParser* parser, const char* name); diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx index e4a6ac7..01cbb78 100644 --- a/Source/cmFortranParserImpl.cxx +++ b/Source/cmFortranParserImpl.cxx @@ -245,6 +245,50 @@ void cmFortranParser_RuleModule(cmFortranParser* parser, } } +void cmFortranParser_RuleSubmodule(cmFortranParser* parser, + const char* module_name, + const char* submodule_name) +{ + if (parser->InPPFalseBranch) { + return; + } + + // syntax: "submodule (module_name) submodule_name" + // requires: "module_name.mod" + // provides: "module_name@submodule_name.smod" + // + // FIXME: Some compilers split the submodule part of a module into a + // separate "module_name.smod" file. Whether it is generated or + // not depends on conditions more subtle than we currently detect. + // For now we depend directly on "module_name.mod". + + std::string const& mod_name = cmSystemTools::LowerCase(module_name); + std::string const& sub_name = cmSystemTools::LowerCase(submodule_name); + parser->Info.Requires.insert(mod_name + ".mod"); + parser->Info.Provides.insert(mod_name + "@" + sub_name + ".smod"); +} + +void cmFortranParser_RuleSubmoduleNested(cmFortranParser* parser, + const char* module_name, + const char* submodule_name, + const char* nested_submodule_name) +{ + if (parser->InPPFalseBranch) { + return; + } + + // syntax: "submodule (module_name:submodule_name) nested_submodule_name" + // requires: "module_name@submodule_name.smod" + // provides: "module_name@nested_submodule_name.smod" + + std::string const& mod_name = cmSystemTools::LowerCase(module_name); + std::string const& sub_name = cmSystemTools::LowerCase(submodule_name); + std::string const& nest_name = + cmSystemTools::LowerCase(nested_submodule_name); + parser->Info.Requires.insert(mod_name + "@" + sub_name + ".smod"); + parser->Info.Provides.insert(mod_name + "@" + nest_name + ".smod"); +} + void cmFortranParser_RuleDefine(cmFortranParser* parser, const char* macro) { if (!parser->InPPFalseBranch) { diff --git a/Tests/FortranModules/Submodules/CMakeLists.txt b/Tests/FortranModules/Submodules/CMakeLists.txt index bf0152f..da204d0 100644 --- a/Tests/FortranModules/Submodules/CMakeLists.txt +++ b/Tests/FortranModules/Submodules/CMakeLists.txt @@ -1 +1,20 @@ -add_executable(submod main.f90 provide.f90) +# The program units in this file consist of a module/submodule +# tree represented by the following graph: +# +# parent +# | +# / \ +# / \ +# child sibling +# | +# grandchild +# +# where the parent node is a module and all other nodes are submodules. + +add_executable(submod + main.f90 + parent.f90 + child.f90 + grandchild.f90 + sibling.f90 + ) diff --git a/Tests/FortranModules/Submodules/child.f90 b/Tests/FortranModules/Submodules/child.f90 new file mode 100644 index 0000000..838ab61 --- /dev/null +++ b/Tests/FortranModules/Submodules/child.f90 @@ -0,0 +1,10 @@ +! Test the notation for a 1st-generation direct +! descendant of a parent module +submodule ( parent ) child + implicit none +contains + module function child_function() result(child_stuff) + logical :: child_stuff + child_stuff=.true. + end function +end submodule child diff --git a/Tests/FortranModules/Submodules/grandchild.f90 b/Tests/FortranModules/Submodules/grandchild.f90 new file mode 100644 index 0000000..1aef63e --- /dev/null +++ b/Tests/FortranModules/Submodules/grandchild.f90 @@ -0,0 +1,8 @@ +! Test the notation for an Nth-generation descendant +! for N>1, which necessitates the colon. +submodule ( parent : child ) grandchild +contains + module subroutine grandchild_subroutine() + print *,"Test passed." + end subroutine +end submodule grandchild diff --git a/Tests/FortranModules/Submodules/parent.f90 b/Tests/FortranModules/Submodules/parent.f90 new file mode 100644 index 0000000..7693a72 --- /dev/null +++ b/Tests/FortranModules/Submodules/parent.f90 @@ -0,0 +1,17 @@ +module parent + implicit none + + interface + + ! Test Fortran 2008 "module function" syntax + module function child_function() result(child_stuff) + logical :: child_stuff + end function + + ! Test Fortran 2008 "module subroutine" syntax + module subroutine grandchild_subroutine() + end subroutine + + end interface + +end module parent diff --git a/Tests/FortranModules/Submodules/provide.f90 b/Tests/FortranModules/Submodules/provide.f90 deleted file mode 100644 index 0ad216a..0000000 --- a/Tests/FortranModules/Submodules/provide.f90 +++ /dev/null @@ -1,57 +0,0 @@ -! The program units in this file consist of a -! module/submodule tree represented by the following -! graph: -! -! parent -! | -! / \ -! / \ -! child sibling -! | -! grandchild -! -! where the parent node is a module and all other -! nodes are submodules. - -module parent - implicit none - - interface - - ! Test Fortran 2008 "module function" syntax - module function child_function() result(child_stuff) - logical :: child_stuff - end function - - ! Test Fortran 2008 "module subroutine" syntax - module subroutine grandchild_subroutine() - end subroutine - - end interface - -end module parent - -! Test the notation for a 1st-generation direct -! descendant of a parent module -submodule ( parent ) child - implicit none -contains - module function child_function() result(child_stuff) - logical :: child_stuff - child_stuff=.true. - end function -end submodule child - -! Empty submodule for checking disambiguation of -! nodes at the same vertical level in the tree -submodule ( parent ) sibling -end submodule sibling - -! Test the notation for an Nth-generation descendant -! for N>1, which necessitates the colon. -submodule ( parent : child ) grandchild -contains - module subroutine grandchild_subroutine() - print *,"Test passed." - end subroutine -end submodule grandchild diff --git a/Tests/FortranModules/Submodules/sibling.f90 b/Tests/FortranModules/Submodules/sibling.f90 new file mode 100644 index 0000000..bba5f92 --- /dev/null +++ b/Tests/FortranModules/Submodules/sibling.f90 @@ -0,0 +1,4 @@ +! Empty submodule for checking disambiguation of +! nodes at the same vertical level in the tree +submodule ( parent ) sibling +end submodule sibling -- cgit v0.12 From b1f95e5b1477794c0ee3a56a4ea016a34c3e3d5c Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 19 Apr 2018 11:26:06 -0400 Subject: Fortran: Extend submodule test with great-grandchild Name the module using CamelCase to test lower-case file name conversion. Also add coverage of existing "sibling" module. --- Tests/FortranModules/Submodules/CMakeLists.txt | 3 +++ Tests/FortranModules/Submodules/greatgrandchild.f90 | 8 ++++++++ Tests/FortranModules/Submodules/main.f90 | 2 ++ Tests/FortranModules/Submodules/parent.f90 | 5 +++++ Tests/FortranModules/Submodules/sibling.f90 | 5 +++++ 5 files changed, 23 insertions(+) create mode 100644 Tests/FortranModules/Submodules/greatgrandchild.f90 diff --git a/Tests/FortranModules/Submodules/CMakeLists.txt b/Tests/FortranModules/Submodules/CMakeLists.txt index da204d0..ab8e0f9 100644 --- a/Tests/FortranModules/Submodules/CMakeLists.txt +++ b/Tests/FortranModules/Submodules/CMakeLists.txt @@ -8,6 +8,8 @@ # child sibling # | # grandchild +# | +# GreatGrandChild # # where the parent node is a module and all other nodes are submodules. @@ -16,5 +18,6 @@ add_executable(submod parent.f90 child.f90 grandchild.f90 + greatgrandchild.f90 sibling.f90 ) diff --git a/Tests/FortranModules/Submodules/greatgrandchild.f90 b/Tests/FortranModules/Submodules/greatgrandchild.f90 new file mode 100644 index 0000000..85404ea --- /dev/null +++ b/Tests/FortranModules/Submodules/greatgrandchild.f90 @@ -0,0 +1,8 @@ +! Test the notation for an Nth-generation descendant +! for N>1, which necessitates the colon. +submodule ( parent : grandchild ) GreatGrandChild +contains + module subroutine GreatGrandChild_subroutine() + print *,"Test passed." + end subroutine +end submodule GreatGrandChild diff --git a/Tests/FortranModules/Submodules/main.f90 b/Tests/FortranModules/Submodules/main.f90 index 3c750ce..3cd2989 100644 --- a/Tests/FortranModules/Submodules/main.f90 +++ b/Tests/FortranModules/Submodules/main.f90 @@ -1,5 +1,7 @@ program main use parent, only : child_function,grandchild_subroutine + use parent, only : sibling_function,GreatGrandChild_subroutine implicit none if (child_function()) call grandchild_subroutine + if (sibling_function()) call GreatGrandChild_subroutine end program diff --git a/Tests/FortranModules/Submodules/parent.f90 b/Tests/FortranModules/Submodules/parent.f90 index 7693a72..3180b70 100644 --- a/Tests/FortranModules/Submodules/parent.f90 +++ b/Tests/FortranModules/Submodules/parent.f90 @@ -7,10 +7,15 @@ module parent module function child_function() result(child_stuff) logical :: child_stuff end function + module function sibling_function() result(sibling_stuff) + logical :: sibling_stuff + end function ! Test Fortran 2008 "module subroutine" syntax module subroutine grandchild_subroutine() end subroutine + module subroutine GreatGrandChild_subroutine() + end subroutine end interface diff --git a/Tests/FortranModules/Submodules/sibling.f90 b/Tests/FortranModules/Submodules/sibling.f90 index bba5f92..8c0943d 100644 --- a/Tests/FortranModules/Submodules/sibling.f90 +++ b/Tests/FortranModules/Submodules/sibling.f90 @@ -1,4 +1,9 @@ ! Empty submodule for checking disambiguation of ! nodes at the same vertical level in the tree submodule ( parent ) sibling +contains + module function sibling_function() result(sibling_stuff) + logical :: sibling_stuff + sibling_stuff=.true. + end function end submodule sibling -- cgit v0.12