From 7c9717fcb5cf94ce1e7ef5c903058adf9980ff28 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 22 Nov 2022 17:29:21 -0500 Subject: [PATCH] analyzer: fix 'errno' on Solaris and OS X [PR107807] gcc/analyzer/ChangeLog: PR analyzer/107807 * region-model-impl-calls.cc (register_known_functions): Register "___errno" and "__error" as synonyms for "__errno_location". gcc/testsuite/ChangeLog: PR analyzer/107807 * gcc.dg/analyzer/errno-___errno.c: New test. * gcc.dg/analyzer/errno-__error.c: New test. * gcc.dg/analyzer/errno-global-var.c: New test. Signed-off-by: David Malcolm --- gcc/analyzer/region-model-impl-calls.cc | 14 ++++++++++++ gcc/testsuite/gcc.dg/analyzer/errno-___errno.c | 29 ++++++++++++++++++++++++ gcc/testsuite/gcc.dg/analyzer/errno-__error.c | 28 +++++++++++++++++++++++ gcc/testsuite/gcc.dg/analyzer/errno-global-var.c | 26 +++++++++++++++++++++ 4 files changed, 97 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/analyzer/errno-___errno.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/errno-__error.c create mode 100644 gcc/testsuite/gcc.dg/analyzer/errno-global-var.c diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc index 6962ffd..23a21d7 100644 --- a/gcc/analyzer/region-model-impl-calls.cc +++ b/gcc/analyzer/region-model-impl-calls.cc @@ -1953,6 +1953,20 @@ register_known_functions (known_function_manager &kfm) kfm.add ("error_at_line", make_unique (5)); } + /* Other implementations of C standard library. */ + { + /* According to PR 107807 comment #2, Solaris implements "errno" + like this: + extern int *___errno(void) __attribute__((__const__)); + #define errno (*(___errno())) + and OS X like this: + extern int * __error(void); + #define errno (*__error()) + Add these as synonyms for "__errno_location". */ + kfm.add ("___errno", make_unique ()); + kfm.add ("__error", make_unique ()); + } + /* C++ support functions. */ { kfm.add ("operator new", make_unique ()); diff --git a/gcc/testsuite/gcc.dg/analyzer/errno-___errno.c b/gcc/testsuite/gcc.dg/analyzer/errno-___errno.c new file mode 100644 index 0000000..17ff8b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/errno-___errno.c @@ -0,0 +1,29 @@ +#include "analyzer-decls.h" + +/* According to PR 107807 comment #2, Solaris implements "errno" + like this: */ + +extern int *___errno(void) __attribute__((__const__)); +#define errno (*(___errno())) + + +extern void external_fn (void); + +int test_reading_errno (void) +{ + return errno; +} + +void test_setting_errno (int val) +{ + errno = val; +} + +void test_storing_to_errno (int val) +{ + __analyzer_eval (errno == val); /* { dg-warning "UNKNOWN" } */ + errno = val; + __analyzer_eval (errno == val); /* { dg-warning "TRUE" } */ + external_fn (); + __analyzer_eval (errno == val); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/errno-__error.c b/gcc/testsuite/gcc.dg/analyzer/errno-__error.c new file mode 100644 index 0000000..19bc4f9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/errno-__error.c @@ -0,0 +1,28 @@ +#include "analyzer-decls.h" + +/* According to PR 107807 comment #2, OS X implements "errno" + like this: */ + +extern int * __error(void); +#define errno (*__error()) + +extern void external_fn (void); + +int test_reading_errno (void) +{ + return errno; +} + +void test_setting_errno (int val) +{ + errno = val; +} + +void test_storing_to_errno (int val) +{ + __analyzer_eval (errno == val); /* { dg-warning "UNKNOWN" } */ + errno = val; + __analyzer_eval (errno == val); /* { dg-warning "TRUE" } */ + external_fn (); + __analyzer_eval (errno == val); /* { dg-warning "UNKNOWN" } */ +} diff --git a/gcc/testsuite/gcc.dg/analyzer/errno-global-var.c b/gcc/testsuite/gcc.dg/analyzer/errno-global-var.c new file mode 100644 index 0000000..fdf1b17 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/errno-global-var.c @@ -0,0 +1,26 @@ +#include "analyzer-decls.h" + +/* "errno" declared as a global var. */ + +extern int errno; + +extern void external_fn (void); + +int test_reading_errno (void) +{ + return errno; +} + +void test_setting_errno (int val) +{ + errno = val; +} + +void test_storing_to_errno (int val) +{ + __analyzer_eval (errno == val); /* { dg-warning "UNKNOWN" } */ + errno = val; + __analyzer_eval (errno == val); /* { dg-warning "TRUE" } */ + external_fn (); + __analyzer_eval (errno == val); /* { dg-warning "UNKNOWN" } */ +} -- 2.7.4