diff options
author | Brad King <brad.king@kitware.com> | 2018-04-19 13:21:58 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2018-04-20 14:57:31 (GMT) |
commit | 402735314ec7fe48ec21e5f4c5b19b6f17682c54 (patch) | |
tree | 6ad7b1ccfa99d27779cabaa23095bded497a6cfd | |
parent | 62538b2c4c70eeef52886092e24c97a9a7699a00 (diff) | |
download | CMake-402735314ec7fe48ec21e5f4c5b19b6f17682c54.zip CMake-402735314ec7fe48ec21e5f4c5b19b6f17682c54.tar.gz CMake-402735314ec7fe48ec21e5f4c5b19b6f17682c54.tar.bz2 |
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
-rw-r--r-- | Help/release/dev/fortran-submodule-depends.rst | 7 | ||||
-rw-r--r-- | Source/LexerParser/cmFortranParser.cxx | 4 | ||||
-rw-r--r-- | Source/LexerParser/cmFortranParser.y | 4 | ||||
-rw-r--r-- | Source/cmDependsFortran.cxx | 7 | ||||
-rw-r--r-- | Source/cmFortranParser.h | 7 | ||||
-rw-r--r-- | Source/cmFortranParserImpl.cxx | 44 | ||||
-rw-r--r-- | Tests/FortranModules/Submodules/CMakeLists.txt | 21 | ||||
-rw-r--r-- | Tests/FortranModules/Submodules/child.f90 | 10 | ||||
-rw-r--r-- | Tests/FortranModules/Submodules/grandchild.f90 | 8 | ||||
-rw-r--r-- | Tests/FortranModules/Submodules/parent.f90 | 17 | ||||
-rw-r--r-- | Tests/FortranModules/Submodules/provide.f90 | 57 | ||||
-rw-r--r-- | Tests/FortranModules/Submodules/sibling.f90 | 4 |
12 files changed, 126 insertions, 64 deletions
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<std::string>& 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 |