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" } */
+}

Reply via email to