https://gcc.gnu.org/g:baea2a0be30d843febce3b40543aa93f91018444
commit r17-4966-gbaea2a0be30d843febce3b40543aa93f91018444 Author: Torbjörn SVENSSON <[email protected]> Date: Mon Aug 31 07:38:51 2026 +0200 analyzer: follow macro aliases for named constant [PR125265] Newlib, picolibc, and probably other libc implementations, use #define O_CREAT _FCREAT #define O_TRUNC _FTRUNC #define O_EXCL _FEXCL In r17-177-g9a5f89005dc49d, support was added to identify redundant flags, but the implementation requires that the value of the macros O_CREAT, O_EXCL, O_RDWR to be a number. This patch extends the support to also allow macro aliases. The maximum followed levels is by default 8 levels, but can be tuned via --param=analyzer-max-macro-alias-depth=n. This change fixes FAIL: gcc.dg/analyzer/mkostemp-1.c (test for warnings, line 109) FAIL: gcc.dg/analyzer/mkostemp-1.c (test for warnings, line 115) FAIL: gcc.dg/analyzer/mkostemps-1.c (test for warnings, line 115) FAIL: gcc.dg/analyzer/mkostemps-1.c (test for warnings, line 121) Regtested with arm-none-eabi (with newlib) on r17-3738-gaaa0f6b1e87bc6. PR analyzer/125265 gcc/ChangeLog: * doc/params.texi (analyzer-max-macro-alias-depth): Document. * params.opt (-param=analyzer-max-macro-alias-depth=): New. gcc/c/ChangeLog: * c-parser.cc: Follow macro alias to get the value for a named constant. gcc/testsuite/ChangeLog: * gcc.dg/analyzer/named-constants-via-macros-alias.c: New test. Signed-off-by: Torbjörn SVENSSON <[email protected]> Diff: --- gcc/c/c-parser.cc | 26 +++++++++++++++++++--- gcc/doc/params.texi | 5 +++++ gcc/params.opt | 4 ++++ .../analyzer/named-constants-via-macros-alias.c | 14 ++++++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 7523f1ad8045..519959e7290c 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -2019,9 +2019,16 @@ private: #define NAME 42 and other bases but not negative numbers, parentheses or e.g. #define NAME 1 << 7 - as doing so would require a parser. */ - tree consider_macro (cpp_macro *macro) const + as doing so would require a parser. + Also handle the case where MACRO's definition is a single identifier + that is itself a macro name (e.g. "#define O_CREAT _FCREAT"), by + following the chain of aliases. */ + tree consider_macro (cpp_macro *macro, int depth = 0) const { + /* UInteger option variables are stored as int, so "depth" must be signed + to avoid a signed/unsigned comparison here. */ + gcc_assert (depth >= 0); + if (macro->paramc > 0) return NULL_TREE; if (macro->kind != cmk_macro) @@ -2029,7 +2036,20 @@ private: if (macro->count != 1) return NULL_TREE; const cpp_token &tok = macro->exp.tokens[0]; - if (tok.type != CPP_NUMBER) + if (tok.type == CPP_NAME) + { + /* Limit recursion. */ + if (depth >= param_analyzer_max_macro_alias_depth) + return NULL_TREE; + + cpp_hashnode *alias = tok.val.node.node; + if (cpp_macro_p (alias)) + return consider_macro (alias->value.macro, depth + 1); + + /* Not a simple alias. */ + return NULL_TREE; + } + else if (tok.type != CPP_NUMBER) return NULL_TREE; cpp_reader *old_parse_in = parse_in; diff --git a/gcc/doc/params.texi b/gcc/doc/params.texi index 7393711a92ea..090af64a7e7d 100644 --- a/gcc/doc/params.texi +++ b/gcc/doc/params.texi @@ -1889,6 +1889,11 @@ the value as unknown. The maximum number of infeasible edges to reject before declaring a diagnostic as infeasible. +@paindex analyzer-max-macro-alias-depth +@item analyzer-max-macro-alias-depth +The maximum number of macro aliases to follow when resolving named constants +in the analyzer. + @paindex gimple-fe-computed-hot-bb-threshold @item gimple-fe-computed-hot-bb-threshold The number of executions of a basic block that is considered hot. diff --git a/gcc/params.opt b/gcc/params.opt index 29a5c7018a80..0dee27cfcee9 100644 --- a/gcc/params.opt +++ b/gcc/params.opt @@ -30,6 +30,10 @@ Loops iterating at least selected number of iterations get loop alignment. Common Joined UInteger Var(param_align_threshold) Init(100) IntegerRange(1, 65536) Param Optimization Select fraction of the maximal frequency of executions of basic block in function given basic block get alignment. +-param=analyzer-max-macro-alias-depth= +Common Joined UInteger Var(param_analyzer_max_macro_alias_depth) Init(8) IntegerRange(0, 255) +Maximum number of macro aliases to follow when resolving named constants in the analyzer; zero disables alias following. + -param=asan-globals= Common Joined UInteger Var(param_asan_globals) Init(1) IntegerRange(0, 1) Param Enable asan globals protection. diff --git a/gcc/testsuite/gcc.dg/analyzer/named-constants-via-macros-alias.c b/gcc/testsuite/gcc.dg/analyzer/named-constants-via-macros-alias.c new file mode 100644 index 000000000000..d74eb12958d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/named-constants-via-macros-alias.c @@ -0,0 +1,14 @@ +/* { dg-additional-options "--param=analyzer-max-macro-alias-depth=1" } */ + +#include "analyzer-decls.h" + +#define O_CREAT 42 /* 0 aliases. */ +#define O_EXCL O_CREAT /* 1 alias. */ +#define O_RDWR O_EXCL /* 2 aliases. */ + +void test_macro_aliases (void) +{ + __analyzer_dump_named_constant ("O_CREAT"); /* { dg-warning "named constant 'O_CREAT' has value '42'" } */ + __analyzer_dump_named_constant ("O_EXCL"); /* { dg-warning "named constant 'O_EXCL' has value '42'" } */ + __analyzer_dump_named_constant ("O_RDWR"); /* { dg-warning "named constant 'O_RDWR' has unknown value" } */ +}
