Skip to content

Commit 97753d8

Browse files
committed
[GR-68568] Fix autopatch_capi overruning into preprocessor directives
PullRequest: graalpython/3946
2 parents c881345 + 4cf05d3 commit 97753d8

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

graalpython/com.oracle.graal.python.test/src/tests/test_autopatch_capi.py

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
1+
# Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
22
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33
#
44
# The Universal Permissive License (UPL), Version 1.0
@@ -54,7 +54,7 @@ def check_autopatched(source, expected):
5454
autopatch_capi.auto_patch(f.name, False)
5555
f.seek(0)
5656
actual = f.read()
57-
assert actual == expected, f"Autopatch didn't make expected changes. Expected:\n{expected}\nActual:{actual}"
57+
assert actual == expected, f"Autopatch didn't make expected changes. Expected:\n{expected}\nActual:\n{actual}"
5858

5959

6060
def test_replace_field_access():
@@ -106,3 +106,29 @@ def test_replace_field_access():
106106
#endif
107107
''',
108108
)
109+
check_autopatched(
110+
'''
111+
#if SOME_MACRO
112+
((PyCFunctionObject *) func)->m_ml,
113+
#else
114+
((PyCFunctionObject *) func)->m_ml,
115+
#endif
116+
''',
117+
'''
118+
#if SOME_MACRO
119+
GraalPyCFunction_GetMethodDef((PyObject*)(((PyCFunctionObject *) func))),
120+
#else
121+
GraalPyCFunction_GetMethodDef((PyObject*)(((PyCFunctionObject *) func))),
122+
#endif
123+
''',
124+
)
125+
check_autopatched(
126+
'''
127+
// PyList_SET_ITEM().
128+
L->ob_item[len] = x;
129+
''',
130+
'''
131+
// PyList_SET_ITEM().
132+
PySequence_Fast_ITEMS((PyObject*)L)[len] = x;
133+
''',
134+
)

graalpython/lib-graalpython/modules/autopatch_capi.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,13 @@ def replace_field_access(contents, match, replacement, assignment):
6565
start, end = match.span(1)
6666
level = 0
6767

68-
def consume_whitespace_backwards(idx):
69-
while idx >= 0 and contents[idx].isspace():
68+
def consume_whitespace_backwards(idx, newlines=True):
69+
while idx >= 0 and contents[idx].isspace() and (not newlines or contents[idx] != '\n'):
70+
idx -= 1
71+
return idx
72+
73+
def consume_line_backwards(idx):
74+
while idx >= 0 and contents[idx] != '\n':
7075
idx -= 1
7176
return idx
7277

@@ -124,6 +129,13 @@ def consume_identifier_backwards(idx):
124129
else:
125130
idx += 1
126131
break
132+
idx = consume_whitespace_backwards(idx, newlines=False)
133+
if contents[idx + 1] == '\n':
134+
# Get previous line. If it's a comment or a preprocessor directive, stop
135+
line_start = consume_whitespace_forward(consume_line_backwards(idx))
136+
if contents[line_start: line_start + 2].startswith(('#', '//')):
137+
idx += 1
138+
break
127139
idx = consume_whitespace_backwards(idx)
128140

129141
receiver_start = consume_whitespace_forward(idx)

0 commit comments

Comments
 (0)