summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2018-04-19 09:21:58 -0400
committerBrad King <brad.king@kitware.com>2018-04-20 10:57:31 -0400
commit402735314ec7fe48ec21e5f4c5b19b6f17682c54 (patch)
tree6ad7b1ccfa99d27779cabaa23095bded497a6cfd
parent62538b2c4c70eeef52886092e24c97a9a7699a00 (diff)
downloadcmake-402735314ec7fe48ec21e5f4c5b19b6f17682c54.tar.gz
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.rst7
-rw-r--r--Source/LexerParser/cmFortranParser.cxx4
-rw-r--r--Source/LexerParser/cmFortranParser.y4
-rw-r--r--Source/cmDependsFortran.cxx7
-rw-r--r--Source/cmFortranParser.h7
-rw-r--r--Source/cmFortranParserImpl.cxx44
-rw-r--r--Tests/FortranModules/Submodules/CMakeLists.txt21
-rw-r--r--Tests/FortranModules/Submodules/child.f9010
-rw-r--r--Tests/FortranModules/Submodules/grandchild.f908
-rw-r--r--Tests/FortranModules/Submodules/parent.f9017
-rw-r--r--Tests/FortranModules/Submodules/provide.f9057
-rw-r--r--Tests/FortranModules/Submodules/sibling.f904
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 0000000000..b795a84640
--- /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 2b3452f2e2..00c8a8afc3 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 acfb40ad8e..5e0924872f 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 da644ddcd3..dbea15ae04 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 5a0bb09aee..efcd100882 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 e4a6ac71c1..01cbb7843c 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 bf0152f63c..da204d0ea1 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 0000000000..838ab61291
--- /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 0000000000..1aef63e310
--- /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 0000000000..7693a729e2
--- /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 0ad216ac51..0000000000
--- 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 0000000000..bba5f92a91
--- /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