On 11/19/2017 10:06 AM, Martin Sebor wrote: >>> +/* If EXPR refers to a character array or pointer declared attribute >>> + nonstring return a decl for that array or pointer and set *REF to >>> + the referenced enclosing object or pointer. Otherwise returns >>> + null. */ >> Generally we'd write NULL rather than null for a generic pointer and in >> this specific case NULL_TREE is even better. > > I agree. The C NULL macro, C++ nullptr, and GCC's NULL_TREE and > NULL_RTL are helpful both for type safety and readability of code. > But they all are implementation details that's ot not relevant to the > specification > of an API or its users. > > The established term that every C and C++ programmer is familiar > with is "null pointer." > > and exist > mainly for type safety. They are not relevant to the specification > of an API or its users. I didn't think too hard about it when > I wrote the comment (it just didn't seem important enough) but > now > that I have I believe "null" is better, clearer, and more future- > proof (in case the return type should ever change to some smart > pointer class). > > (There also comments in this file and elsewhere in GCC that use > various forms of null.) Perhaps so, but please capitalize it -- while there may be "null" references, I believe in all-caps is by far more common within comments within the GCC sources.
WRT NULL vs NULL_TREE, I'd tend to disagree. The function isn't going to return NULL, it's going to return NULL_TREE. That's actually already exposed in the API/ABI by the return value's type. The fact that NULL and NULL_TREE are interchangeable is an implementation detail and we shouldn't encourage folks to rely on that by way of the function comment. > >>> + if (TREE_CODE (dcl) == SSA_NAME) >>> + { >>> + if (SSA_NAME_IS_DEFAULT_DEF (dcl)) >>> + dcl = SSA_NAME_VAR (dcl); >>> + else >>> + { >>> + gimple *def = SSA_NAME_DEF_STMT (dcl); >>> + >>> + if (is_gimple_assign (def)) >>> + { >>> + tree_code code = gimple_assign_rhs_code (def); >>> + if (code == ADDR_EXPR >>> + || code == COMPONENT_REF >>> + || code == VAR_DECL) >>> + dcl = gimple_assign_rhs1 (def); >> Note that COMPONENT_REFs can have arguments that are themselves >> COMPONENT_REFS. So you typically want to use a loop to strip all away. > > I have seen it in the early IL but this late I couldn't come > up with a test case where such a loop would be necessary. > The COMPONENT_REF always refers to the member array. If you > can show me an example to test with I'll add the handling if > possible. There are cases where it isn't, such as in > > struct A { char a[4] __attribute__ ((nonstring)); } *pa; > > strlen (pa->a + 1); > > where pa->a is represented as a MEM_REF (char[4], pa, 1) with > the member information having been lost in translation. (This > is the same problem that I had solved for the -Warray-bounds > warning for out-of bounds offsets by implementing it in > tree-ssa-forwprop.c: because that's where the member is folded > into a reference to the base object.) Set up a nested structure then reference it like a.b.c.d. > >>> + /* It's safe to call strndup and strnlen with a non-string argument >>> + since the functions provide an explicit bound for this >>> purpose. */ >>> + if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STRNDUP) >>> + return; >> So I see you handle BUILT_IN_STRNDUP here, but not BUILT_IN_STRNLEN. Is >> there a reason for the omission? > > strnlen is not a GCC built-in so it's handled implicitly by > the test for DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL > just before the if statement above. The test I added verifies > that strnlen is excluded. (Bug 81384 tracks the missing > intrinsic support for strnlen.) > > That said, more testing revealed that Glibc uses functions like > strncmp and strncpy to compare and copy non-strings, so I've > added those to the white list and improved the checking a bit. > I've also changed the hash_map to a pointer to make Jakub happy. OK. Thanks. > >