diff options
author | Martin Sebor <msebor@redhat.com> | 2021-08-13 12:21:20 -0600 |
---|---|---|
committer | Martin Sebor <msebor@redhat.com> | 2021-08-13 12:23:58 -0600 |
commit | fb85d6eb6c392e829d1ee5b8a2e2b81c53c9840f (patch) | |
tree | 3224d9384343767b06b6d06b267f3930cf5f5f51 /gcc/tree-ssa-uninit.c | |
parent | e5c00544cce1feb2c8c4e9aad766315d389c69c4 (diff) | |
download | gcc-fb85d6eb6c392e829d1ee5b8a2e2b81c53c9840f.zip gcc-fb85d6eb6c392e829d1ee5b8a2e2b81c53c9840f.tar.gz gcc-fb85d6eb6c392e829d1ee5b8a2e2b81c53c9840f.tar.bz2 |
Warn for reads from write-only arguments [PR101734].
Resolves:
PR middle-end/101734 - missing warning reading from a write-only object
gcc/ChangeLog:
PR middle-end/101734
* tree-ssa-uninit.c (maybe_warn_read_write_only): New function.
(maybe_warn_operand): Call it.
gcc/testsuite/ChangeLog:
PR middle-end/101734
* gcc.dg/uninit-42.c: New test.
Diffstat (limited to 'gcc/tree-ssa-uninit.c')
-rw-r--r-- | gcc/tree-ssa-uninit.c | 89 |
1 files changed, 80 insertions, 9 deletions
diff --git a/gcc/tree-ssa-uninit.c b/gcc/tree-ssa-uninit.c index 5d7bc80..d5cdffb 100644 --- a/gcc/tree-ssa-uninit.c +++ b/gcc/tree-ssa-uninit.c @@ -283,6 +283,64 @@ builtin_call_nomodifying_p (gimple *stmt) return true; } +/* If ARG is a FNDECL parameter declared with attribute access none or + write_only issue a warning for its read access via PTR. */ + +static void +maybe_warn_read_write_only (tree fndecl, gimple *stmt, tree arg, tree ptr) +{ + if (!fndecl) + return; + + if (get_no_uninit_warning (arg)) + return; + + tree fntype = TREE_TYPE (fndecl); + if (!fntype) + return; + + /* 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)); + + unsigned argno = 0; + tree parms = DECL_ARGUMENTS (fndecl); + for (tree parm = parms; parm; parm = TREE_CHAIN (parm), ++argno) + { + if (parm != arg) + continue; + + const attr_access* access = rdwr_idx.get (argno); + if (!access) + break; + + if (access->mode != access_none + && access->mode != access_write_only) + continue; + + location_t stmtloc + = linemap_resolve_location (line_table, gimple_location (stmt), + LRK_SPELLING_LOCATION, NULL); + + if (!warning_at (stmtloc, OPT_Wmaybe_uninitialized, + "%qE may be used uninitialized", ptr)) + break; + + suppress_warning (arg, OPT_Wmaybe_uninitialized); + + const char* const access_str = + TREE_STRING_POINTER (access->to_external_string ()); + + location_t parmloc = DECL_SOURCE_LOCATION (parm); + inform (parmloc, "accessing argument %u of a function declared with " + "attribute %<%s%>", + argno + 1, access_str); + + break; + } +} + /* Callback for walk_aliased_vdefs. */ static bool @@ -350,7 +408,9 @@ struct wlimits }; /* Determine if REF references an uninitialized operand and diagnose - it if so. */ + it if so. STMS is the referencing statement. LHS is the result + of the access and may be null. RHS is the variable referenced by + the access; it may not be null. */ static tree maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, @@ -497,14 +557,25 @@ maybe_warn_operand (ao_ref &ref, gimple *stmt, tree lhs, tree rhs, /* Do not warn if it can be initialized outside this function. If we did not reach function entry then we found killing clobbers on all paths to entry. */ - if (!found_alloc - && fentry_reached - /* ??? We'd like to use ref_may_alias_global_p but that - excludes global readonly memory and thus we get bogus - warnings from p = cond ? "a" : "b" for example. */ - && (!VAR_P (base) - || is_global_var (base))) - return NULL_TREE; + if (!found_alloc && fentry_reached) + { + if (TREE_CODE (base) == SSA_NAME) + { + tree var = SSA_NAME_VAR (base); + if (var && TREE_CODE (var) == PARM_DECL) + { + maybe_warn_read_write_only (cfun->decl, stmt, var, rhs); + return NULL_TREE; + } + } + + if (!VAR_P (base) + || is_global_var (base)) + /* ??? We'd like to use ref_may_alias_global_p but that + excludes global readonly memory and thus we get bogus + warnings from p = cond ? "a" : "b" for example. */ + return NULL_TREE; + } /* Strip the address-of expression from arrays passed to functions. */ if (TREE_CODE (rhs) == ADDR_EXPR) |