From: Martin Sebor Date: Sat, 19 Sep 2020 23:30:32 +0000 (-0600) Subject: Make use of new attribute access infrastructure in -Wuninitialized (PR 50584). X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=72be80e47d059f33ff11f5015b9494c42b4e0a12;p=gcc.git Make use of new attribute access infrastructure in -Wuninitialized (PR 50584). gcc/ChangeLog: * tree-ssa-uninit.c (maybe_warn_pass_by_reference): Handle attribute access internal representation of arrays. gcc/testsuite/ChangeLog: * gcc.dg/uninit-37.c: New test. --- diff --git a/gcc/testsuite/gcc.dg/uninit-37.c b/gcc/testsuite/gcc.dg/uninit-37.c new file mode 100644 index 00000000000..b8c49ad17ce --- /dev/null +++ b/gcc/testsuite/gcc.dg/uninit-37.c @@ -0,0 +1,154 @@ +/* PR middle-end/10138 - warn for uninitialized arrays passed as const arguments + Verify that -Wuninitialized and -Wmaybe-uninitialized trigger (or don't) + when passing uninitialized variables by reference to functions declared + with or without attribute access and with (or without) const qualified + arguments of array, VLA, or pointer types. + { dg-do compile } + { dg-options "-O2 -Wall -ftrack-macro-expansion=0" } */ + +#define NONE /* none */ +#define RO(...) __attribute__ ((access (read_only, __VA_ARGS__))) +#define RW(...) __attribute__ ((access (read_write, __VA_ARGS__))) +#define WO(...) __attribute__ ((access (write_only, __VA_ARGS__))) +#define X(...) __attribute__ ((access (none, __VA_ARGS__))) + +#define CONCAT(x, y) x ## y +#define CAT(x, y) CONCAT (x, y) +#define UNIQ(pfx) CAT (pfx, __LINE__) + +extern void sink (void*); + + +#define T1(attr, name, type) \ + void UNIQ (CAT (test_, name))(void) { \ + extern attr void UNIQ (name)(type); \ + int x; \ + UNIQ (name)(&x); \ + sink (&x); \ + } + +#define T2(attr, name, types) \ + void UNIQ (CAT (test_, name))(void) { \ + extern attr void UNIQ (name)(types); \ + int x; \ + UNIQ (name)(1, &x); \ + sink (&x); \ + } + + +typedef int IA_[]; +typedef const int CIA_[]; + +T1 (NONE, fia_, IA_); +T1 (NONE, fcia_, CIA_); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froia_, IA_); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwia_, IA_); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoia_, IA_); +T1 (X (1), fxia_, IA_); + + +typedef int IA1[1]; +typedef const int CIA1[1]; + +T1 (NONE, fia1, IA1); +T1 (NONE, fcia1, CIA1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froia1, IA1); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwia1, IA1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoia1, IA1); +T1 (X (1), fxia1, IA1); + + +#define IARS1 int[restrict static 1] +#define CIARS1 const int[restrict static 1] + +T1 (NONE, fiars1, IARS1); +T1 (NONE, fciars1, CIARS1);// { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froiars1, IARS1); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwiars1, IARS1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoiars1, IARS1); +T1 (X (1), fxiars1, IARS1); + + +#define IAS1 int[static 1] +#define CIAS1 const int[static 1] + +T1 (NONE, fias1, IAS1); +T1 (NONE, fcias1, CIAS1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froias1, IAS1); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwias1, IAS1); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoias1, IAS1); +T1 (X (1), fxias1, IAS1); + + +#define IAX int[*] +#define CIAX const int[*] + +T1 (NONE, fiax, IAX); +T1 (NONE, fciax, CIAX); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froiax, IAX); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwiax, IAX); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoiax, IAX); +T1 (X (1), fxiax, IAX); + + +#define IAN int n, int[n] +#define CIAN int n, const int[n] + +T2 (NONE, fian, IAN); +T2 (NONE, fcian, CIAN); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T2 (RO (2, 1), froian, IAN); // { dg-warning "\\\[-Wuninitialized" } +T2 (RW (2, 1), frwian, IAN); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T2 (WO (2, 1), fwoian, IAN); +T2 (X (2, 1), fxian, IAN); + + +typedef int* IP; +typedef const int* CIP; + +T1 (NONE, fip, IP); +T1 (NONE, fcip, CIP); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (RO (1), froip, IP); // { dg-warning "\\\[-Wuninitialized" } +T1 (RW (1), frwip, IP); // { dg-warning "\\\[-Wmaybe-uninitialized" } +T1 (WO (1), fwoip, IP); +T1 (X (1), fxip, IP); + + +/* Verify that the notes printed after the warning mention attribute + access only when the attribute is explicitly used in the declaration + and not otherwise. */ + +void test_note_cst_restrict (void) +{ + extern void + fccar (const char[restrict]); // { dg-message "by argument 1 of type 'const char\\\[restrict]' to 'fccar'" "note" } + + char a[1]; // { dg-message "'a' declared here" "note" } + fccar (a); // { dg-warning "'a' may be used uninitialized" } +} + +void test_note_vla (int n) +{ + extern void + fccvla (const char[n]); // { dg-message "by argument 1 of type 'const char\\\[n]' to 'fccvla'" "note" } + + char a[2]; // { dg-message "'a' declared here" "note" } + fccvla (a); // { dg-warning "'a' may be used uninitialized" } +} + +void test_note_ro (void) +{ + extern RO (1) void + frocar (char[restrict]); // { dg-message "in a call to 'frocar' declared with attribute 'access \\\(read_only, 1\\\)'" "note" } + + char a[3]; // { dg-message "'a' declared here" "note" } + frocar (a); // { dg-warning "'a' is used uninitialized" } +} + +void test_note_rw (void) +{ + extern RW (1) void + frwcar (char[restrict]); // { dg-message "in a call to 'frwcar' declared with attribute 'access \\\(read_write, 1\\\)'" "note" } + + char a[4]; // { dg-message "'a' declared here" "note" } + frwcar (a); // { dg-warning "'a' may be used uninitialized" } +} diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 2cef5f3643f..0447bb2f3fb 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ +#define INCLUDE_STRING #include "config.h" #include "system.h" #include "coretypes.h" @@ -472,7 +473,8 @@ maybe_warn_pass_by_reference (gimple *stmt, wlimits &wlims) read_only. */ const bool save_always_executed = wlims.always_executed; - /* Map of attribute access specifications for function arguments. */ + /* Initialize a map of attribute access specifications for arguments + to the function function call. */ rdwr_map rdwr_idx; init_attr_rdwr_indices (&rdwr_idx, TYPE_ATTRIBUTES (fntype)); @@ -488,12 +490,17 @@ maybe_warn_pass_by_reference (gimple *stmt, wlimits &wlims) continue; tree access_size = NULL_TREE; - attr_access *access = rdwr_idx.get (argno - 1); + const attr_access* access = rdwr_idx.get (argno - 1); if (access) { if (access->mode == access_none || access->mode == access_write_only) continue; + + if (access->mode == access_deferred + && !TYPE_READONLY (TREE_TYPE (argtype))) + continue; + if (save_always_executed && access->mode == access_read_only) /* Attribute read_only arguments imply read access. */ wlims.always_executed = true; @@ -524,45 +531,48 @@ maybe_warn_pass_by_reference (gimple *stmt, wlimits &wlims) if (!argbase) continue; - if (access) + if (access && access->mode != access_deferred) { - const char* const mode = (access->mode == access_read_only - ? "read_only" : "read_write"); - char attrstr[80]; - int n = sprintf (attrstr, "access (%s, %u", mode, argno); - if (access->sizarg < UINT_MAX) - sprintf (attrstr + n, ", %u)", access->sizarg); - else - strcpy (attrstr + n, ")"); + const char* const access_str = + TREE_STRING_POINTER (access->to_external_string ()); if (fndecl) { location_t loc = DECL_SOURCE_LOCATION (fndecl); - inform (loc, "in a call to %qD declared " - "with attribute % here", - fndecl, mode, argno); + inform (loc, "in a call to %qD declared with " + "attribute %<%s%> here", fndecl, access_str); } else { /* Handle calls through function pointers. */ location_t loc = gimple_location (stmt); inform (loc, "in a call to %qT declared with " - "attribute %", - fntype, mode, argno); + "attribute %<%s%>", fntype, access_str); } } - else if (fndecl) - { - location_t loc = DECL_SOURCE_LOCATION (fndecl); - inform (loc, "by argument %u of type %qT to %qD declared here", - argno, argtype, fndecl); - } else { - /* Handle calls through function pointers. */ - location_t loc = gimple_location (stmt); - inform (loc, "by argument %u of type %qT to %qT", - argno, argtype, fntype); + /* For a declaration with no relevant attribute access create + a dummy object and use the formatting function to avoid + having to complicate things here. */ + attr_access ptr_access = { }; + if (!access) + access = &ptr_access; + const std::string argtypestr = access->array_as_string (argtype); + if (fndecl) + { + location_t loc (DECL_SOURCE_LOCATION (fndecl)); + inform (loc, "by argument %u of type %<%s%> to %qD " + "declared here", + argno, argtypestr.c_str (), fndecl); + } + else + { + /* Handle calls through function pointers. */ + location_t loc (gimple_location (stmt)); + inform (loc, "by argument %u of type %<%s%> to %qT", + argno, argtypestr.c_str (), fntype); + } } if (DECL_P (argbase))