cpython/Tools/c-analyzer/c_parser/preprocessor/clang.py
dgpb 5ec03cf3b0
gh-133228: c-analyzer clang preprocessor (GH-133229)
* impl
* included 2 failures to tsvs next to similar entries
* added fix/hack for curses.h fails
* fix leftover from debug
2025-11-27 22:22:21 +00:00

104 lines
3 KiB
Python

import os.path
import re, sys
from . import common as _common
from . import gcc as _gcc
_normpath = _gcc._normpath
TOOL = 'clang'
META_FILES = {
'<built-in>',
'<command line>',
}
def preprocess(filename,
incldirs=None,
includes=None,
macros=None,
samefiles=None,
cwd=None,
):
if not cwd or not os.path.isabs(cwd):
cwd = os.path.abspath(cwd or '.')
filename = _normpath(filename, cwd)
postargs = _gcc.POST_ARGS
basename = os.path.basename(filename)
dirname = os.path.basename(os.path.dirname(filename))
if (basename not in _gcc.FILES_WITHOUT_INTERNAL_CAPI
and dirname not in _gcc.DIRS_WITHOUT_INTERNAL_CAPI):
postargs += ('-DPy_BUILD_CORE=1',)
text = _common.preprocess(
TOOL,
filename,
incldirs=incldirs,
includes=includes,
macros=macros,
#preargs=PRE_ARGS,
postargs=postargs,
executable=['clang'],
compiler='unix',
cwd=cwd,
)
return _iter_lines(text, filename, samefiles, cwd)
EXIT_MARKERS = {'# 2 "<built-in>" 2', '# 3 "<built-in>" 2', '# 4 "<built-in>" 2'}
def _iter_lines(text, reqfile, samefiles, cwd, raw=False):
lines = iter(text.splitlines())
# The first line is special.
# The subsequent lines are consistent.
firstlines = [
f'# 1 "{reqfile}"',
'# 1 "<built-in>" 1',
'# 1 "<built-in>" 3',
'# 370 "<built-in>" 3',
'# 1 "<command line>" 1',
'# 1 "<built-in>" 2',
]
for expected in firstlines:
line = next(lines)
if line != expected:
raise NotImplementedError((line, expected))
# Do all the CLI-provided includes.
filter_reqfile = (lambda f: _gcc._filter_reqfile(f, reqfile, samefiles))
make_info = (lambda lno: _common.FileInfo(reqfile, lno))
last = None
for line in lines:
assert last != reqfile, (last,)
# NOTE:condition is clang specific
if not line:
continue
lno, included, flags = _gcc._parse_marker_line(line, reqfile)
if not included:
raise NotImplementedError((line,))
if included == reqfile:
# This will be the last one.
assert 2 in flags, (line, flags)
else:
# NOTE:first condition is specific to clang
if _normpath(included, cwd) == reqfile:
assert 1 in flags or 2 in flags, (line, flags, included, reqfile)
else:
assert 1 in flags, (line, flags, included, reqfile)
yield from _gcc._iter_top_include_lines(
lines,
_normpath(included, cwd),
cwd,
filter_reqfile,
make_info,
raw,
EXIT_MARKERS
)
last = included
# The last one is always the requested file.
# NOTE:_normpath is clang specific
assert _normpath(included, cwd) == reqfile, (line,)