From 711a322a235d4c8177713f11aa59156603b94aeb Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Mon, 11 Mar 2019 10:59:27 -0400 Subject: Use a proper C tokenizer to implement the obsolete typedefs test. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test for obsolete typedefs in installed headers was implemented using grep, and could therefore get false positives on e.g. “ulong” in a comment. It was also scanning all of the headers included by our headers, and therefore testing headers we don’t control, e.g. Linux kernel headers. This patch splits the obsolete-typedef test from scripts/check-installed-headers.sh to a separate program, scripts/check-obsolete-constructs.py. Being implemented in Python, it is feasible to make it tokenize C accurately enough to avoid false positives on the contents of comments and strings. It also only examines $(headers) in each subdirectory--all the headers we install, but not any external dependencies of those headers. Headers whose installed name starts with finclude/ are ignored, on the assumption that they contain Fortran. It is also feasible to make the new test understand the difference between _defining_ the obsolete typedefs and _using_ the obsolete typedefs, which means posix/{bits,sys}/types.h no longer need to be exempted. This uncovered an actual bug in bits/types.h: __quad_t and __u_quad_t were being used to define __S64_TYPE, __U64_TYPE, __SQUAD_TYPE and __UQUAD_TYPE. These are changed to __int64_t and __uint64_t respectively. This is a safe change, despite the comments in bits/types.h claiming a difference between __quad_t and __int64_t, because those comments are incorrect. In all current ABIs, both __quad_t and __int64_t are ‘long’ when ‘long’ is a 64-bit type, and ‘long long’ when ‘long’ is a 32-bit type, and similarly for __u_quad_t and __uint64_t. (Changing the types to be what the comments say they are would be an ABI break, as it affects C++ name mangling.) This patch includes a minimal change to make the comments not completely wrong. sys/types.h was defining the legacy BSD u_intN_t typedefs using a construct that was not necessarily consistent with how the C99 uintN_t typedefs are defined, and is also too complicated for the new script to understand (it lexes C relatively accurately, but it does not attempt to expand preprocessor macros, nor does it do any actual parsing). This patch cuts all of that out and uses bits/types.h's __uintN_t typedefs to define u_intN_t instead. This is verified to not change the ABI on any supported architecture, via the c++-types test, which means u_intN_t and uintN_t were, in fact, consistent on all supported architectures. Reviewed-by: Carlos O'Donell * scripts/check-obsolete-constructs.py: New test script. * scripts/check-installed-headers.sh: Remove tests for obsolete typedefs, superseded by check-obsolete-constructs.py. * Rules: Run scripts/check-obsolete-constructs.py over $(headers) as a special test. Update commentary. * posix/bits/types.h (__SQUAD_TYPE, __S64_TYPE): Define as __int64_t. (__UQUAD_TYPE, __U64_TYPE): Define as __uint64_t. Update commentary. * posix/sys/types.h (__u_intN_t): Remove. (u_int8_t): Typedef using __uint8_t. (u_int16_t): Typedef using __uint16_t. (u_int32_t): Typedef using __uint32_t. (u_int64_t): Typedef using __uint64_t. --- Rules | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'Rules') diff --git a/Rules b/Rules index e08a28d9f3..222dba6dcb 100644 --- a/Rules +++ b/Rules @@ -82,7 +82,8 @@ $(common-objpfx)dummy.c: common-generated += dummy.o dummy.c ifneq "$(headers)" "" -# Special test of all the installed headers in this directory. +# Test that all of the headers installed by this directory can be compiled +# in isolation. tests-special += $(objpfx)check-installed-headers-c.out libof-check-installed-headers-c := testsuite $(objpfx)check-installed-headers-c.out: \ @@ -93,6 +94,8 @@ $(objpfx)check-installed-headers-c.out: \ $(evaluate-test) ifneq "$(CXX)" "" +# If a C++ compiler is available, also test that they can be compiled +# in isolation as C++. tests-special += $(objpfx)check-installed-headers-cxx.out libof-check-installed-headers-cxx := testsuite $(objpfx)check-installed-headers-cxx.out: \ @@ -103,12 +106,24 @@ $(objpfx)check-installed-headers-cxx.out: \ $(evaluate-test) endif # $(CXX) +# Test that a wrapper header exists in include/ for each non-sysdeps header. +# This script does not need $(py-env). tests-special += $(objpfx)check-wrapper-headers.out $(objpfx)check-wrapper-headers.out: \ $(..)scripts/check-wrapper-headers.py $(headers) $(PYTHON) $< --root=$(..) --subdir=$(subdir) $(headers) > $@; \ $(evaluate-test) +# Test that none of the headers installed by this directory use certain +# obsolete constructs (e.g. legacy BSD typedefs superseded by stdint.h). +# This script does not need $(py-env). +tests-special += $(objpfx)check-obsolete-constructs.out +libof-check-obsolete-constructs := testsuite +$(objpfx)check-obsolete-constructs.out: \ + $(..)scripts/check-obsolete-constructs.py $(headers) + $(PYTHON) $^ > $@ 2>&1; \ + $(evaluate-test) + endif # $(headers) # This makes all the auxiliary and test programs. -- cgit 1.4.1