From 7f892acb42c546252fc566450fe9abd28df2a377 Mon Sep 17 00:00:00 2001 From: Aljen Uitbeijerse Date: Fri, 13 Oct 2023 20:15:45 +0200 Subject: [PATCH 01/10] test: Add test for preprocessor #if-#else parsing --- test/test_preproc.py | 5 +++++ test/test_source/pp/preproc_else.F90 | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 test/test_source/pp/preproc_else.F90 diff --git a/test/test_preproc.py b/test/test_preproc.py index e1bdd49d..9b1b8aee 100644 --- a/test/test_preproc.py +++ b/test/test_preproc.py @@ -30,6 +30,9 @@ def check_return(result_array, checks): string += hover_req(file_path, 10, 15) # defined without () file_path = root_dir / "preproc_keywords.F90" string += hover_req(file_path, 6, 2) # ignores PP across Fortran line continuations + file_path = root_dir / "preproc_else.F90" + string += hover_req(file_path, 8, 12) + string += hover_req(file_path, 18, 12) config = str(root_dir / ".pp_conf.json") errcode, results = run_request(string, ["--config", config]) assert errcode == 0 @@ -49,6 +52,8 @@ def check_return(result_array, checks): ), "```fortran90\n#define SUCCESS .true.\n```", "```fortran90\nREAL, CONTIGUOUS, POINTER, DIMENSION(:) :: var1\n```", + "```fortran90\nINTEGER :: var0\n```", + "```fortran90\nREAL :: var1\n```", ) assert len(ref_results) == len(results) - 1 check_return(results[1:], ref_results) diff --git a/test/test_source/pp/preproc_else.F90 b/test/test_source/pp/preproc_else.F90 new file mode 100644 index 00000000..edd19f63 --- /dev/null +++ b/test/test_source/pp/preproc_else.F90 @@ -0,0 +1,21 @@ +subroutine preprocessor_else(var) + +#if 0 +#define MYTYPE logical +#else +#define MYTYPE integer +#endif + +MYTYPE :: var0 + +#undef MYTYPE + +#if 1 +#define MYTYPE real +#else +#define MYTYPE character +#endif + +MYTYPE :: var1 + +endsubroutine preprocessor_else From 21bd3310354ce6cb9b1e553ee32509cc487101bd Mon Sep 17 00:00:00 2001 From: Aljen Uitbeijerse Date: Fri, 13 Oct 2023 20:22:22 +0200 Subject: [PATCH 02/10] fix: preprocessor #else branch preprocessor content of the #else branch is now included when the #if evaluates to false --- fortls/parse_fortran.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fortls/parse_fortran.py b/fortls/parse_fortran.py index 235b5c08..f135edaf 100644 --- a/fortls/parse_fortran.py +++ b/fortls/parse_fortran.py @@ -2150,6 +2150,8 @@ def replace_vars(line: str): exc_start = True else: pp_stack[-1][1] = i + 1 + pp_skips.append(pp_stack.pop()) + pp_stack.append([-1, -1]) inc_start = True elif match.group(1) == "endif": if pp_stack[-1][0] < 0: From faf6d7e8714e16428b58ff9e323d85a4f5ee6d0f Mon Sep 17 00:00:00 2001 From: Aljen Uitbeijerse Date: Fri, 13 Oct 2023 20:43:40 +0200 Subject: [PATCH 03/10] test: Add test for preprocessor #elif parsing --- test/test_preproc.py | 5 +++++ test/test_source/pp/preproc_elif.F90 | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test/test_source/pp/preproc_elif.F90 diff --git a/test/test_preproc.py b/test/test_preproc.py index 9b1b8aee..9d276680 100644 --- a/test/test_preproc.py +++ b/test/test_preproc.py @@ -33,6 +33,9 @@ def check_return(result_array, checks): file_path = root_dir / "preproc_else.F90" string += hover_req(file_path, 8, 12) string += hover_req(file_path, 18, 12) + file_path = root_dir / "preproc_elif.F90" + string += hover_req(file_path, 10, 12) + string += hover_req(file_path, 14, 15) config = str(root_dir / ".pp_conf.json") errcode, results = run_request(string, ["--config", config]) assert errcode == 0 @@ -54,6 +57,8 @@ def check_return(result_array, checks): "```fortran90\nREAL, CONTIGUOUS, POINTER, DIMENSION(:) :: var1\n```", "```fortran90\nINTEGER :: var0\n```", "```fortran90\nREAL :: var1\n```", + "```fortran90\nLOGICAL :: var1\n```", + "```fortran90\nINTEGER :: var2\n```", ) assert len(ref_results) == len(results) - 1 check_return(results[1:], ref_results) diff --git a/test/test_source/pp/preproc_elif.F90 b/test/test_source/pp/preproc_elif.F90 new file mode 100644 index 00000000..53980569 --- /dev/null +++ b/test/test_source/pp/preproc_elif.F90 @@ -0,0 +1,17 @@ +subroutine preprocessor_elif(var) + +#if 0 +#define MYTYPE character +#elif 1 +#define MYTYPE logical +#else +#define MYTYPE integer +#endif + +MYTYPE :: var1 + +#define OTHERTYPE integer + +OTHERTYPE :: var2 + +endsubroutine preprocessor_elif \ No newline at end of file From 10dc58f288edfd70eb04397a1cdc74d6c0236aa6 Mon Sep 17 00:00:00 2001 From: Aljen Uitbeijerse Date: Fri, 13 Oct 2023 20:55:44 +0200 Subject: [PATCH 04/10] fix: preprocessor #elif no longer skips whole file When an #elif branch evaluates to true, after the next #endif the rest of the whole files #define, #undef and #include statements would not be parsed. Now those are correctly parsed. --- fortls/parse_fortran.py | 1 + 1 file changed, 1 insertion(+) diff --git a/fortls/parse_fortran.py b/fortls/parse_fortran.py index f135edaf..c1b8b584 100644 --- a/fortls/parse_fortran.py +++ b/fortls/parse_fortran.py @@ -2142,6 +2142,7 @@ def replace_vars(line: str): else: if eval_pp_if(line[match.end(1) :], defs_tmp): pp_stack[-1][1] = i - 1 + pp_skips.append(pp_stack.pop()) pp_stack.append([-1, -1]) inc_start = True elif match.group(1) == "else": From a5d6e8f0e7382a798cab4854643a70344a3360ee Mon Sep 17 00:00:00 2001 From: Aljen Uitbeijerse Date: Fri, 13 Oct 2023 21:17:50 +0200 Subject: [PATCH 05/10] test: Update test for preprocessor #elif parsing Only content from the true branch should be in the final parsed file --- test/test_preproc.py | 6 ++++-- test/test_source/pp/preproc_elif.F90 | 7 +++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/test/test_preproc.py b/test/test_preproc.py index 9d276680..d2b7a7f0 100644 --- a/test/test_preproc.py +++ b/test/test_preproc.py @@ -34,8 +34,9 @@ def check_return(result_array, checks): string += hover_req(file_path, 8, 12) string += hover_req(file_path, 18, 12) file_path = root_dir / "preproc_elif.F90" - string += hover_req(file_path, 10, 12) - string += hover_req(file_path, 14, 15) + string += hover_req(file_path, 15, 12) + string += hover_req(file_path, 19, 15) + string += hover_req(file_path, 21, 10) config = str(root_dir / ".pp_conf.json") errcode, results = run_request(string, ["--config", config]) assert errcode == 0 @@ -59,6 +60,7 @@ def check_return(result_array, checks): "```fortran90\nREAL :: var1\n```", "```fortran90\nLOGICAL :: var1\n```", "```fortran90\nINTEGER :: var2\n```", + "```fortran90\nINTEGER, INTENT(INOUT) :: var\n```", ) assert len(ref_results) == len(results) - 1 check_return(results[1:], ref_results) diff --git a/test/test_source/pp/preproc_elif.F90 b/test/test_source/pp/preproc_elif.F90 index 53980569..f64dcb89 100644 --- a/test/test_source/pp/preproc_elif.F90 +++ b/test/test_source/pp/preproc_elif.F90 @@ -2,10 +2,15 @@ subroutine preprocessor_elif(var) #if 0 #define MYTYPE character +integer, intent(in) :: var #elif 1 #define MYTYPE logical +integer, intent(inout) :: var +var = 3 #else #define MYTYPE integer +integer, intent(out) :: var +var = 5 #endif MYTYPE :: var1 @@ -14,4 +19,6 @@ subroutine preprocessor_elif(var) OTHERTYPE :: var2 +PRINT*, var + endsubroutine preprocessor_elif \ No newline at end of file From 412cadea01e0b32005485af3ed061fca8cce16e9 Mon Sep 17 00:00:00 2001 From: Aljen Uitbeijerse Date: Fri, 13 Oct 2023 21:18:52 +0200 Subject: [PATCH 06/10] fix: preprocessor indexing error in #elif parsing --- fortls/parse_fortran.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fortls/parse_fortran.py b/fortls/parse_fortran.py index c1b8b584..2b27c809 100644 --- a/fortls/parse_fortran.py +++ b/fortls/parse_fortran.py @@ -2141,7 +2141,7 @@ def replace_vars(line: str): exc_start = True else: if eval_pp_if(line[match.end(1) :], defs_tmp): - pp_stack[-1][1] = i - 1 + pp_stack[-1][1] = i + 1 pp_skips.append(pp_stack.pop()) pp_stack.append([-1, -1]) inc_start = True From ed566cdf4cb8b4ae8973556aeb70a18637d8aa7c Mon Sep 17 00:00:00 2001 From: Aljen Uitbeijerse Date: Fri, 13 Oct 2023 23:24:36 +0200 Subject: [PATCH 07/10] test: update test for preprocessor #elif parsing Only the first true branch of a #if-#elif-#else should be included --- test/test_source/pp/preproc_elif.F90 | 117 ++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/test/test_source/pp/preproc_elif.F90 b/test/test_source/pp/preproc_elif.F90 index f64dcb89..548a5934 100644 --- a/test/test_source/pp/preproc_elif.F90 +++ b/test/test_source/pp/preproc_elif.F90 @@ -1,4 +1,4 @@ -subroutine preprocessor_elif(var) +subroutine preprocessor_elif(var, var3, var4, var5, var6) #if 0 #define MYTYPE character @@ -21,4 +21,119 @@ subroutine preprocessor_elif(var) PRINT*, var +#if 1 +#define PART1 1, +#elif 0 +#define PART2 2, +#elif 1 +#define PART3 3, +#else +#define PART4 4 +#endif + +#ifndef PART1 +#define PART1 5, +#endif +#ifndef PART2 +#define PART2 5, +#endif +#ifndef PART3 +#define PART3 5, +#endif +#ifndef PART4 +#define PART4 5 +#endif + +REAL(PART1 PART2 PART3 PART4) :: var3 + +#undef PART1 +#undef PART2 +#undef PART3 +#undef PART4 + +#if 0 +#define PART1 1, +#elif 1 +#define PART2 2, +#elif 1 +#define PART3 3, +#else +#define PART4 4 +#endif + +#ifndef PART1 +#define PART1 5, +#endif +#ifndef PART2 +#define PART2 5, +#endif +#ifndef PART3 +#define PART3 5, +#endif +#ifndef PART4 +#define PART4 5 +#endif + +REAL(PART1 PART2 PART3 PART4) :: var4 + +#undef PART1 +#undef PART2 +#undef PART3 +#undef PART4 + +#if 0 +#define PART1 1, +#elif 0 +#define PART2 2, +#elif 0 +#define PART3 3, +#else +#define PART4 4 +#endif + +#ifndef PART1 +#define PART1 5, +#endif +#ifndef PART2 +#define PART2 5, +#endif +#ifndef PART3 +#define PART3 5, +#endif +#ifndef PART4 +#define PART4 5 +#endif + +REAL(PART1 PART2 PART3 PART4) :: var5 + +#undef PART1 +#undef PART2 +#undef PART3 +#undef PART4 + +#if 1 +#define PART1 1, +#elif 1 +#define PART2 2, +#elif 0 +#define PART3 3, +#else +#define PART4 4 +#endif + +#ifndef PART1 +#define PART1 5, +#endif +#ifndef PART2 +#define PART2 5, +#endif +#ifndef PART3 +#define PART3 5, +#endif +#ifndef PART4 +#define PART4 5 +#endif + +REAL(PART1 PART2 PART3 PART4) :: var6 + endsubroutine preprocessor_elif \ No newline at end of file From a1645e67b74c7860126eb481e2479e67b69f9ba3 Mon Sep 17 00:00:00 2001 From: Aljen Uitbeijerse Date: Fri, 13 Oct 2023 23:25:31 +0200 Subject: [PATCH 08/10] fix: preprocessor #elif only includes first true branch --- fortls/parse_fortran.py | 40 ++++++++++++++++++++++------ test/test_preproc.py | 8 ++++++ test/test_source/pp/preproc_elif.F90 | 2 +- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/fortls/parse_fortran.py b/fortls/parse_fortran.py index 2b27c809..b707aea9 100644 --- a/fortls/parse_fortran.py +++ b/fortls/parse_fortran.py @@ -2090,6 +2090,7 @@ def replace_vars(line: str): pp_skips = [] pp_defines = [] pp_stack = [] + pp_stack_group = [] defs_tmp = pp_defs.copy() def_regexes = {} output_file = [] @@ -2135,28 +2136,49 @@ def replace_vars(line: str): # Closing/middle conditional statements inc_start = False exc_start = False + exc_continue = False if match.group(1) == "elif": - if pp_stack[-1][0] < 0: - pp_stack[-1][0] = i + 1 - exc_start = True + if (not pp_stack_group) or (pp_stack_group[-1][0] != len(pp_stack)): + # First elif statement for this elif group + if pp_stack[-1][0] < 0: + pp_stack_group.append([len(pp_stack), True]) + else: + pp_stack_group.append([len(pp_stack), False]) + if pp_stack_group[-1][1]: + # An earlier if or elif in this group has been true + exc_continue = True + if pp_stack[-1][0] < 0: + pp_stack[-1][0] = i + 1 + elif eval_pp_if(line[match.end(1) :], defs_tmp): + pp_stack[-1][1] = i + 1 + pp_skips.append(pp_stack.pop()) + pp_stack_group[-1][1] = True + pp_stack.append([-1, -1]) + inc_start = True else: - if eval_pp_if(line[match.end(1) :], defs_tmp): - pp_stack[-1][1] = i + 1 - pp_skips.append(pp_stack.pop()) - pp_stack.append([-1, -1]) - inc_start = True + exc_start = True elif match.group(1) == "else": if pp_stack[-1][0] < 0: pp_stack[-1][0] = i + 1 exc_start = True + elif ( + pp_stack_group + and (pp_stack_group[-1][0] == len(pp_stack)) + and (pp_stack_group[-1][1]) + ): + # An earlier if or elif in this group has been true + exc_continue = True else: pp_stack[-1][1] = i + 1 pp_skips.append(pp_stack.pop()) pp_stack.append([-1, -1]) inc_start = True elif match.group(1) == "endif": + if pp_stack_group and (pp_stack_group[-1][0] == len(pp_stack)): + pp_stack_group.pop() if pp_stack[-1][0] < 0: pp_stack.pop() + log.debug(f"{line.strip()} !!! Conditional TRUE/END({i + 1})") continue if pp_stack[-1][1] < 0: pp_stack[-1][1] = i + 1 @@ -2167,6 +2189,8 @@ def replace_vars(line: str): log.debug(f"{line.strip()} !!! Conditional TRUE({i + 1})") elif exc_start: log.debug(f"{line.strip()} !!! Conditional FALSE({i + 1})") + elif exc_continue: + log.debug(f"{line.strip()} !!! Conditional EXCLUDED({i + 1})") continue # Handle variable/macro definitions files match = FRegex.PP_DEF.match(line) diff --git a/test/test_preproc.py b/test/test_preproc.py index d2b7a7f0..b162b87b 100644 --- a/test/test_preproc.py +++ b/test/test_preproc.py @@ -37,6 +37,10 @@ def check_return(result_array, checks): string += hover_req(file_path, 15, 12) string += hover_req(file_path, 19, 15) string += hover_req(file_path, 21, 10) + string += hover_req(file_path, 46, 36) + string += hover_req(file_path, 76, 36) + string += hover_req(file_path, 106, 36) + string += hover_req(file_path, 136, 36) config = str(root_dir / ".pp_conf.json") errcode, results = run_request(string, ["--config", config]) assert errcode == 0 @@ -61,6 +65,10 @@ def check_return(result_array, checks): "```fortran90\nLOGICAL :: var1\n```", "```fortran90\nINTEGER :: var2\n```", "```fortran90\nINTEGER, INTENT(INOUT) :: var\n```", + "```fortran90\nREAL(1, 5, 5, 5) :: var3\n```", + "```fortran90\nREAL(5, 2, 5, 5) :: var4\n```", + "```fortran90\nREAL(5, 5, 5, 4) :: var5\n```", + "```fortran90\nREAL(1, 5, 5, 5) :: var6\n```", ) assert len(ref_results) == len(results) - 1 check_return(results[1:], ref_results) diff --git a/test/test_source/pp/preproc_elif.F90 b/test/test_source/pp/preproc_elif.F90 index 548a5934..dbcef3dc 100644 --- a/test/test_source/pp/preproc_elif.F90 +++ b/test/test_source/pp/preproc_elif.F90 @@ -136,4 +136,4 @@ subroutine preprocessor_elif(var, var3, var4, var5, var6) REAL(PART1 PART2 PART3 PART4) :: var6 -endsubroutine preprocessor_elif \ No newline at end of file +endsubroutine preprocessor_elif From 4f7bc5c760219ac774bbcdd00110093d599b2193 Mon Sep 17 00:00:00 2001 From: gnikit Date: Sat, 21 Oct 2023 15:53:11 +0100 Subject: [PATCH 09/10] refactor: preprocessor elif test --- test/test_preproc.py | 23 ++-- test/test_source/pp/preproc_elif.F90 | 128 ++---------------- .../test_source/pp/preproc_elif_elif_skip.F90 | 33 +++++ test/test_source/pp/preproc_if_elif_else.F90 | 33 +++++ test/test_source/pp/preproc_if_elif_skip.F90 | 33 +++++ 5 files changed, 118 insertions(+), 132 deletions(-) create mode 100644 test/test_source/pp/preproc_elif_elif_skip.F90 create mode 100644 test/test_source/pp/preproc_if_elif_else.F90 create mode 100644 test/test_source/pp/preproc_if_elif_skip.F90 diff --git a/test/test_preproc.py b/test/test_preproc.py index b162b87b..50f50607 100644 --- a/test/test_preproc.py +++ b/test/test_preproc.py @@ -34,13 +34,14 @@ def check_return(result_array, checks): string += hover_req(file_path, 8, 12) string += hover_req(file_path, 18, 12) file_path = root_dir / "preproc_elif.F90" - string += hover_req(file_path, 15, 12) - string += hover_req(file_path, 19, 15) - string += hover_req(file_path, 21, 10) - string += hover_req(file_path, 46, 36) - string += hover_req(file_path, 76, 36) - string += hover_req(file_path, 106, 36) - string += hover_req(file_path, 136, 36) + string += hover_req(file_path, 22, 15) + string += hover_req(file_path, 24, 10) + file_path = root_dir / "preproc_elif_elif_skip.F90" + string += hover_req(file_path, 30, 23) + file_path = root_dir / "preproc_if_elif_else.F90" + string += hover_req(file_path, 30, 23) + file_path = root_dir / "preproc_if_elif_skip.F90" + string += hover_req(file_path, 30, 23) config = str(root_dir / ".pp_conf.json") errcode, results = run_request(string, ["--config", config]) assert errcode == 0 @@ -62,13 +63,11 @@ def check_return(result_array, checks): "```fortran90\nREAL, CONTIGUOUS, POINTER, DIMENSION(:) :: var1\n```", "```fortran90\nINTEGER :: var0\n```", "```fortran90\nREAL :: var1\n```", - "```fortran90\nLOGICAL :: var1\n```", "```fortran90\nINTEGER :: var2\n```", "```fortran90\nINTEGER, INTENT(INOUT) :: var\n```", - "```fortran90\nREAL(1, 5, 5, 5) :: var3\n```", - "```fortran90\nREAL(5, 2, 5, 5) :: var4\n```", - "```fortran90\nREAL(5, 5, 5, 4) :: var5\n```", - "```fortran90\nREAL(1, 5, 5, 5) :: var6\n```", + "```fortran90\nINTEGER, PARAMETER :: res = 0+1+0+0\n```", + "```fortran90\nINTEGER, PARAMETER :: res = 0+0+0+1\n```", + "```fortran90\nINTEGER, PARAMETER :: res = 1+0+0+0\n```", ) assert len(ref_results) == len(results) - 1 check_return(results[1:], ref_results) diff --git a/test/test_source/pp/preproc_elif.F90 b/test/test_source/pp/preproc_elif.F90 index dbcef3dc..87138247 100644 --- a/test/test_source/pp/preproc_elif.F90 +++ b/test/test_source/pp/preproc_elif.F90 @@ -1,139 +1,27 @@ subroutine preprocessor_elif(var, var3, var4, var5, var6) +! This file, as used in test_preproc, checks that +! 1. the steps after the preprocessor parsing has fully finished, are only +! using content from the parts within the preprocessor if-elif-else that +! should be used. To do this, it has some regular fortran code within the +! #if and #elif. +! 2. the #endif correctly concludes the if-elif, so any new #define statements +! that come after the #endif, are picked up during the preprocessor parsing. + #if 0 -#define MYTYPE character integer, intent(in) :: var #elif 1 -#define MYTYPE logical integer, intent(inout) :: var var = 3 #else -#define MYTYPE integer integer, intent(out) :: var var = 5 #endif -MYTYPE :: var1 - #define OTHERTYPE integer OTHERTYPE :: var2 PRINT*, var -#if 1 -#define PART1 1, -#elif 0 -#define PART2 2, -#elif 1 -#define PART3 3, -#else -#define PART4 4 -#endif - -#ifndef PART1 -#define PART1 5, -#endif -#ifndef PART2 -#define PART2 5, -#endif -#ifndef PART3 -#define PART3 5, -#endif -#ifndef PART4 -#define PART4 5 -#endif - -REAL(PART1 PART2 PART3 PART4) :: var3 - -#undef PART1 -#undef PART2 -#undef PART3 -#undef PART4 - -#if 0 -#define PART1 1, -#elif 1 -#define PART2 2, -#elif 1 -#define PART3 3, -#else -#define PART4 4 -#endif - -#ifndef PART1 -#define PART1 5, -#endif -#ifndef PART2 -#define PART2 5, -#endif -#ifndef PART3 -#define PART3 5, -#endif -#ifndef PART4 -#define PART4 5 -#endif - -REAL(PART1 PART2 PART3 PART4) :: var4 - -#undef PART1 -#undef PART2 -#undef PART3 -#undef PART4 - -#if 0 -#define PART1 1, -#elif 0 -#define PART2 2, -#elif 0 -#define PART3 3, -#else -#define PART4 4 -#endif - -#ifndef PART1 -#define PART1 5, -#endif -#ifndef PART2 -#define PART2 5, -#endif -#ifndef PART3 -#define PART3 5, -#endif -#ifndef PART4 -#define PART4 5 -#endif - -REAL(PART1 PART2 PART3 PART4) :: var5 - -#undef PART1 -#undef PART2 -#undef PART3 -#undef PART4 - -#if 1 -#define PART1 1, -#elif 1 -#define PART2 2, -#elif 0 -#define PART3 3, -#else -#define PART4 4 -#endif - -#ifndef PART1 -#define PART1 5, -#endif -#ifndef PART2 -#define PART2 5, -#endif -#ifndef PART3 -#define PART3 5, -#endif -#ifndef PART4 -#define PART4 5 -#endif - -REAL(PART1 PART2 PART3 PART4) :: var6 - endsubroutine preprocessor_elif diff --git a/test/test_source/pp/preproc_elif_elif_skip.F90 b/test/test_source/pp/preproc_elif_elif_skip.F90 new file mode 100644 index 00000000..a41250b2 --- /dev/null +++ b/test/test_source/pp/preproc_elif_elif_skip.F90 @@ -0,0 +1,33 @@ +subroutine preprocessor_elif_elif_skip() + +! This file, as used in test_preproc, and together with the two similar files, +! tests that when there is an if-elif-elif-else, only the first branch that +! evaluates to true is used, and the others ignored. Also when multiple +! conditions evaluate to true. + +#if 0 +#define PART1 0 +#elif 1 +#define PART2 1 +#elif 1 +#define PART3 0 +#else +#define PART4 0 +#endif + +#ifndef PART1 +#define PART1 0 +#endif +#ifndef PART2 +#define PART2 0 +#endif +#ifndef PART3 +#define PART3 0 +#endif +#ifndef PART4 +#define PART4 0 +#endif + +integer, parameter :: res = PART1+PART2+PART3+PART4 + +end subroutine preprocessor_elif_elif_skip diff --git a/test/test_source/pp/preproc_if_elif_else.F90 b/test/test_source/pp/preproc_if_elif_else.F90 new file mode 100644 index 00000000..8457ab60 --- /dev/null +++ b/test/test_source/pp/preproc_if_elif_else.F90 @@ -0,0 +1,33 @@ +subroutine preprocessor_if_elif_else() + +! This file, as used in test_preproc, and together with the two similar files, +! tests that when there is an if-elif-elif-else, only the first branch that +! evaluates to true is used, and the others ignored. Also when multiple +! conditions evaluate to true. + +#if 0 +#define PART1 0 +#elif 0 +#define PART2 0 +#elif 0 +#define PART3 0 +#else +#define PART4 1 +#endif + +#ifndef PART1 +#define PART1 0 +#endif +#ifndef PART2 +#define PART2 0 +#endif +#ifndef PART3 +#define PART3 0 +#endif +#ifndef PART4 +#define PART4 0 +#endif + +integer, parameter :: res = PART1+PART2+PART3+PART4 + +endsubroutine preprocessor_if_elif_else diff --git a/test/test_source/pp/preproc_if_elif_skip.F90 b/test/test_source/pp/preproc_if_elif_skip.F90 new file mode 100644 index 00000000..d478fd0e --- /dev/null +++ b/test/test_source/pp/preproc_if_elif_skip.F90 @@ -0,0 +1,33 @@ +subroutine preprocessor_if_elif_skip() + +! This file, as used in test_preproc, and together with the two similar files, +! tests that when there is an if-elif-elif-else, only the first branch that +! evaluates to true is used, and the others ignored. Also when multiple +! conditions evaluate to true. + +#if 1 +#define PART1 1 +#elif 0 +#define PART2 0 +#elif 1 +#define PART3 0 +#else +#define PART4 0 +#endif + +#ifndef PART1 +#define PART1 0 +#endif +#ifndef PART2 +#define PART2 0 +#endif +#ifndef PART3 +#define PART3 0 +#endif +#ifndef PART4 +#define PART4 0 +#endif + +integer, parameter :: res = PART1+PART2+PART3+PART4 + +end subroutine preprocessor_if_elif_skip From dc3449e5ff1617b98c5affbf1633bad82dcf443e Mon Sep 17 00:00:00 2001 From: gnikit Date: Sat, 28 Oct 2023 12:30:00 +0100 Subject: [PATCH 10/10] chore: updated CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dfcf1965..8a478156 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ ### Fixed +- Fixed preprocessor bug with `if` and `elif` conditionals + ([#322](https://github.com/fortran-lang/fortls/issues/322)) - Fixed bug where type fields or methods were not detected if spaces were used around `%` ([#286](https://github.com/fortran-lang/fortls/issues/286))