summaryrefslogtreecommitdiffstats
path: root/Tools/c-analyzer/c_parser
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-03-14 16:05:54 (GMT)
committerGitHub <noreply@github.com>2023-03-14 16:05:54 (GMT)
commit1ff81c0cb67215694f084e51c4d35ae53b9f5cf9 (patch)
treee8067aff7f52f7b17284caa3452b17a98a9ae1bc /Tools/c-analyzer/c_parser
parenta703f743dbf2675948e59c44fa9d7112f7825100 (diff)
downloadcpython-1ff81c0cb67215694f084e51c4d35ae53b9f5cf9.zip
cpython-1ff81c0cb67215694f084e51c4d35ae53b9f5cf9.tar.gz
cpython-1ff81c0cb67215694f084e51c4d35ae53b9f5cf9.tar.bz2
gh-81057: Add a CI Check for New Unsupported C Global Variables (gh-102506)
This will keep us from adding new unsupported (i.e. non-const) C global variables, which would break interpreter isolation. FYI, historically it is very uncommon for new global variables to get added. Furthermore, it is rare for new code to break the c-analyzer. So the check should almost always pass unnoticed. Note that I've removed test_check_c_globals. A test wasn't a great fit conceptually and was super slow on debug builds. A CI check is a better fit. This also resolves gh-100237. https://github.com/python/cpython/issues/81057
Diffstat (limited to 'Tools/c-analyzer/c_parser')
-rw-r--r--Tools/c-analyzer/c_parser/preprocessor/common.py6
-rw-r--r--Tools/c-analyzer/c_parser/preprocessor/gcc.py23
2 files changed, 19 insertions, 10 deletions
diff --git a/Tools/c-analyzer/c_parser/preprocessor/common.py b/Tools/c-analyzer/c_parser/preprocessor/common.py
index 4291a06..dbe1ede 100644
--- a/Tools/c-analyzer/c_parser/preprocessor/common.py
+++ b/Tools/c-analyzer/c_parser/preprocessor/common.py
@@ -115,15 +115,15 @@ def converted_error(tool, argv, filename):
def convert_error(tool, argv, filename, stderr, rc):
error = (stderr.splitlines()[0], rc)
if (_expected := is_os_mismatch(filename, stderr)):
- logger.debug(stderr.strip())
+ logger.info(stderr.strip())
raise OSMismatchError(filename, _expected, argv, error, tool)
elif (_missing := is_missing_dep(stderr)):
- logger.debug(stderr.strip())
+ logger.info(stderr.strip())
raise MissingDependenciesError(filename, (_missing,), argv, error, tool)
elif '#error' in stderr:
# XXX Ignore incompatible files.
error = (stderr.splitlines()[1], rc)
- logger.debug(stderr.strip())
+ logger.info(stderr.strip())
raise ErrorDirectiveError(filename, argv, error, tool)
else:
# Try one more time, with stderr written to the terminal.
diff --git a/Tools/c-analyzer/c_parser/preprocessor/gcc.py b/Tools/c-analyzer/c_parser/preprocessor/gcc.py
index 7ef1a8a..24c1b0e 100644
--- a/Tools/c-analyzer/c_parser/preprocessor/gcc.py
+++ b/Tools/c-analyzer/c_parser/preprocessor/gcc.py
@@ -6,6 +6,11 @@ from . import common as _common
TOOL = 'gcc'
+META_FILES = {
+ '<built-in>',
+ '<command-line>',
+}
+
# https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
# flags:
# 1 start of a new file
@@ -75,11 +80,15 @@ def _iter_lines(text, reqfile, samefiles, cwd, raw=False):
# The first line is special.
# The next two lines are consistent.
- for expected in [
- f'# 1 "{reqfile}"',
- '# 1 "<built-in>"',
- '# 1 "<command-line>"',
- ]:
+ firstlines = [
+ f'# 0 "{reqfile}"',
+ '# 0 "<built-in>"',
+ '# 0 "<command-line>"',
+ ]
+ if text.startswith('# 1 '):
+ # Some preprocessors emit a lineno of 1 for line-less entries.
+ firstlines = [l.replace('# 0 ', '# 1 ') for l in firstlines]
+ for expected in firstlines:
line = next(lines)
if line != expected:
raise NotImplementedError((line, expected))
@@ -121,7 +130,7 @@ def _iter_top_include_lines(lines, topfile, cwd,
# _parse_marker_line() that the preprocessor reported lno as 1.
lno = 1
for line in lines:
- if line == '# 1 "<command-line>" 2':
+ if line == '# 0 "<command-line>" 2' or line == '# 1 "<command-line>" 2':
# We're done with this top-level include.
return
@@ -174,8 +183,8 @@ def _parse_marker_line(line, reqfile=None):
return None, None, None
lno, origfile, flags = m.groups()
lno = int(lno)
+ assert origfile not in META_FILES, (line,)
assert lno > 0, (line, lno)
- assert origfile not in ('<built-in>', '<command-line>'), (line,)
flags = set(int(f) for f in flags.split()) if flags else ()
if 1 in flags: