Skip to content

Commit a1645e6

Browse files
committed
fix: preprocessor #elif only includes first true branch
1 parent ed566cd commit a1645e6

File tree

3 files changed

+41
-9
lines changed

3 files changed

+41
-9
lines changed

fortls/parse_fortran.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,7 @@ def replace_vars(line: str):
20902090
pp_skips = []
20912091
pp_defines = []
20922092
pp_stack = []
2093+
pp_stack_group = []
20932094
defs_tmp = pp_defs.copy()
20942095
def_regexes = {}
20952096
output_file = []
@@ -2135,28 +2136,49 @@ def replace_vars(line: str):
21352136
# Closing/middle conditional statements
21362137
inc_start = False
21372138
exc_start = False
2139+
exc_continue = False
21382140
if match.group(1) == "elif":
2139-
if pp_stack[-1][0] < 0:
2140-
pp_stack[-1][0] = i + 1
2141-
exc_start = True
2141+
if (not pp_stack_group) or (pp_stack_group[-1][0] != len(pp_stack)):
2142+
# First elif statement for this elif group
2143+
if pp_stack[-1][0] < 0:
2144+
pp_stack_group.append([len(pp_stack), True])
2145+
else:
2146+
pp_stack_group.append([len(pp_stack), False])
2147+
if pp_stack_group[-1][1]:
2148+
# An earlier if or elif in this group has been true
2149+
exc_continue = True
2150+
if pp_stack[-1][0] < 0:
2151+
pp_stack[-1][0] = i + 1
2152+
elif eval_pp_if(line[match.end(1) :], defs_tmp):
2153+
pp_stack[-1][1] = i + 1
2154+
pp_skips.append(pp_stack.pop())
2155+
pp_stack_group[-1][1] = True
2156+
pp_stack.append([-1, -1])
2157+
inc_start = True
21422158
else:
2143-
if eval_pp_if(line[match.end(1) :], defs_tmp):
2144-
pp_stack[-1][1] = i + 1
2145-
pp_skips.append(pp_stack.pop())
2146-
pp_stack.append([-1, -1])
2147-
inc_start = True
2159+
exc_start = True
21482160
elif match.group(1) == "else":
21492161
if pp_stack[-1][0] < 0:
21502162
pp_stack[-1][0] = i + 1
21512163
exc_start = True
2164+
elif (
2165+
pp_stack_group
2166+
and (pp_stack_group[-1][0] == len(pp_stack))
2167+
and (pp_stack_group[-1][1])
2168+
):
2169+
# An earlier if or elif in this group has been true
2170+
exc_continue = True
21522171
else:
21532172
pp_stack[-1][1] = i + 1
21542173
pp_skips.append(pp_stack.pop())
21552174
pp_stack.append([-1, -1])
21562175
inc_start = True
21572176
elif match.group(1) == "endif":
2177+
if pp_stack_group and (pp_stack_group[-1][0] == len(pp_stack)):
2178+
pp_stack_group.pop()
21582179
if pp_stack[-1][0] < 0:
21592180
pp_stack.pop()
2181+
log.debug(f"{line.strip()} !!! Conditional TRUE/END({i + 1})")
21602182
continue
21612183
if pp_stack[-1][1] < 0:
21622184
pp_stack[-1][1] = i + 1
@@ -2167,6 +2189,8 @@ def replace_vars(line: str):
21672189
log.debug(f"{line.strip()} !!! Conditional TRUE({i + 1})")
21682190
elif exc_start:
21692191
log.debug(f"{line.strip()} !!! Conditional FALSE({i + 1})")
2192+
elif exc_continue:
2193+
log.debug(f"{line.strip()} !!! Conditional EXCLUDED({i + 1})")
21702194
continue
21712195
# Handle variable/macro definitions files
21722196
match = FRegex.PP_DEF.match(line)

test/test_preproc.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ def check_return(result_array, checks):
3737
string += hover_req(file_path, 15, 12)
3838
string += hover_req(file_path, 19, 15)
3939
string += hover_req(file_path, 21, 10)
40+
string += hover_req(file_path, 46, 36)
41+
string += hover_req(file_path, 76, 36)
42+
string += hover_req(file_path, 106, 36)
43+
string += hover_req(file_path, 136, 36)
4044
config = str(root_dir / ".pp_conf.json")
4145
errcode, results = run_request(string, ["--config", config])
4246
assert errcode == 0
@@ -61,6 +65,10 @@ def check_return(result_array, checks):
6165
"```fortran90\nLOGICAL :: var1\n```",
6266
"```fortran90\nINTEGER :: var2\n```",
6367
"```fortran90\nINTEGER, INTENT(INOUT) :: var\n```",
68+
"```fortran90\nREAL(1, 5, 5, 5) :: var3\n```",
69+
"```fortran90\nREAL(5, 2, 5, 5) :: var4\n```",
70+
"```fortran90\nREAL(5, 5, 5, 4) :: var5\n```",
71+
"```fortran90\nREAL(1, 5, 5, 5) :: var6\n```",
6472
)
6573
assert len(ref_results) == len(results) - 1
6674
check_return(results[1:], ref_results)

test/test_source/pp/preproc_elif.F90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,4 @@ subroutine preprocessor_elif(var, var3, var4, var5, var6)
136136

137137
REAL(PART1 PART2 PART3 PART4) :: var6
138138

139-
endsubroutine preprocessor_elif
139+
endsubroutine preprocessor_elif

0 commit comments

Comments
 (0)