Skip to content

Commit 09a3da8

Browse files
ueckerMartin Uecker
authored andcommitted
c: rewrite implementation of `arg spec' attribute
Rewrite the implementation of the `arg spec' attribute to pass the the original type of an array parameter instead of passing a string description and a list of bounds. The string and list are then created from this type during the integration of the information of `arg spec' into the access attribute because it still needed later for various warnings. This change makes the implementation simpler and more robust as the declarator is not processed and information that is already encoded in the type is not duplicated. A similar change to the access attribute could then completely remove the string processing. With this change, the original type is now available and can be used for other warnings or for _Countof. The new implementation tries to be faithful to the original, but this is not entirely true as it fixes a bug in the old implementation. gcc/c-family/ChangeLog: * c-attribs.cc (handle_argspec_attribute): Update. (build_arg_spec): New function. (build_attr_access_from_parms): Rewrite `arg spec' handling. gcc/c/ChangeLog: * c-decl.cc (get_parm_array_spec): Remove. (push_parm_decl): Do not add `arg spec` attribute. (build_arg_spec_attribute): New function. (grokdeklarator): Add `arg spec` attribute. gcc/testsuite/ChangeLog: * gcc.dg/Warray-parameter-11.c: Change Warray-parameter to -Wvla-parameter as these are VLAs. * gcc.dg/Warray-parameter.c: Remove xfail.
1 parent 3e4ced9 commit 09a3da8

File tree

4 files changed

+145
-199
lines changed

4 files changed

+145
-199
lines changed

gcc/c-family/c-attribs.cc

Lines changed: 115 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4120,10 +4120,11 @@ handle_argspec_attribute (tree *, tree, tree args, int, bool *)
41204120
{
41214121
/* Verify the attribute has one or two arguments and their kind. */
41224122
gcc_assert (args && TREE_CODE (TREE_VALUE (args)) == STRING_CST);
4123-
for (tree next = TREE_CHAIN (args); next; next = TREE_CHAIN (next))
4123+
if (TREE_CHAIN (args))
41244124
{
4125-
tree val = TREE_VALUE (next);
4126-
gcc_assert (DECL_P (val) || EXPR_P (val));
4125+
tree val = TREE_VALUE (TREE_CHAIN (args));
4126+
gcc_assert (!TREE_CHAIN (TREE_CHAIN (args)));
4127+
gcc_assert (TYPE_P (val));
41274128
}
41284129
return NULL_TREE;
41294130
}
@@ -5736,6 +5737,71 @@ handle_access_attribute (tree node[3], tree name, tree args, int flags,
57365737
return NULL_TREE;
57375738
}
57385739

5740+
5741+
/* This function builds a string which is concatenated to SPEC and returns
5742+
list of variably bounds corresponding to an array/VLA parameter with
5743+
type TYPE. The string consists of one dollar symbol for each specified
5744+
variable bound, one asterisk for each unspecified variable bound,
5745+
a space for an array of unknown size (only possibly for the outermost),
5746+
and a zero for a zero-sized array.
5747+
5748+
The chainof variable bounds starts with the most significant bound.
5749+
For example, the TYPE T[2][m][3][n] will produce "$$" and (m, (n, nil)). */
5750+
5751+
static tree
5752+
build_arg_spec (tree type, std::string *spec)
5753+
{
5754+
while (POINTER_TYPE_P (type))
5755+
type = TREE_TYPE (type);
5756+
5757+
if (TREE_CODE (type) != ARRAY_TYPE)
5758+
return NULL_TREE;
5759+
5760+
tree list = build_arg_spec (TREE_TYPE (type), spec);
5761+
5762+
if (!COMPLETE_TYPE_P (type))
5763+
{
5764+
(*spec) += ' ';
5765+
return list;
5766+
}
5767+
5768+
tree mval = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5769+
5770+
if (!mval)
5771+
{
5772+
(*spec) += '0';
5773+
return list;
5774+
}
5775+
5776+
if (TREE_CODE (mval) == COMPOUND_EXPR
5777+
&& integer_zerop (TREE_OPERAND (mval, 0))
5778+
&& integer_zerop (TREE_OPERAND (mval, 1)))
5779+
{
5780+
(*spec) += '*';
5781+
return list;
5782+
}
5783+
5784+
if (TREE_CODE (mval) == INTEGER_CST)
5785+
return list;
5786+
5787+
/* A variable bound. */
5788+
(*spec) += '$';
5789+
5790+
mval = array_type_nelts_top (type);
5791+
5792+
/* Remove NOP_EXPR and SAVE_EXPR to uncover possible PARM_DECLS. */
5793+
if (TREE_CODE (mval) == NOP_EXPR)
5794+
mval = TREE_OPERAND (mval, 0);
5795+
if (TREE_CODE (mval) == SAVE_EXPR)
5796+
{
5797+
mval = TREE_OPERAND (mval, 0);
5798+
if (TREE_CODE (mval) == NOP_EXPR)
5799+
mval = TREE_OPERAND (mval, 0);
5800+
}
5801+
5802+
return tree_cons (NULL_TREE, mval, list);
5803+
}
5804+
57395805
/* Extract attribute "arg spec" from each FNDECL argument that has it,
57405806
build a single attribute access corresponding to all the arguments,
57415807
and return the result. SKIP_VOIDPTR set to ignore void* parameters
@@ -5812,15 +5878,16 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr)
58125878
argspec = TREE_VALUE (argspec);
58135879

58145880
/* The attribute arg spec string. */
5815-
tree str = TREE_VALUE (argspec);
5816-
const char *s = TREE_STRING_POINTER (str);
5881+
const char *s = TREE_STRING_POINTER (TREE_VALUE (argspec));
5882+
bool static_p = s && (0 == strcmp("static", s));
58175883

58185884
/* Collect the list of nonnull arguments which use "[static ..]". */
5819-
if (s != NULL && s[0] == '[' && s[1] == 's')
5885+
if (static_p)
58205886
nnlist = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
58215887
argpos + 1), nnlist);
58225888

5823-
/* Create the attribute access string from the arg spec string,
5889+
tree argvbs;
5890+
/* Create the attribute access string from the arg spec data,
58245891
optionally followed by position of the VLA bound argument if
58255892
it is one. */
58265893
{
@@ -5831,21 +5898,52 @@ build_attr_access_from_parms (tree parms, bool skip_voidptr)
58315898
specend = 1;
58325899
}
58335900

5834-
/* Format the access string in place. */
5835-
int len = snprintf (NULL, 0, "%c%u%s",
5836-
attr_access::mode_chars[access_deferred],
5837-
argpos, s);
5838-
spec.resize (specend + len + 1);
5839-
sprintf (&spec[specend], "%c%u%s",
5840-
attr_access::mode_chars[access_deferred],
5841-
argpos, s);
5901+
spec += attr_access::mode_chars[access_deferred];
5902+
spec += std::to_string (argpos);
5903+
spec += '[';
5904+
tree type = TREE_VALUE (TREE_CHAIN (argspec));
5905+
argvbs = build_arg_spec (type, &spec);
5906+
5907+
/* Postprocess the string to bring it in the format expected
5908+
by the code handling the access attribute. First, we
5909+
add 's' if the array was declared as [static ...]. */
5910+
if (static_p)
5911+
{
5912+
size_t send = spec.length();
5913+
5914+
if (spec[send - 1] == '[')
5915+
{
5916+
spec += 's';
5917+
}
5918+
else
5919+
{
5920+
/* If there is a symbol, we need to swap the order. */
5921+
spec += spec[send - 1];
5922+
spec[send - 1] = 's';
5923+
}
5924+
}
5925+
5926+
/* If the outermost bound is an integer constant, we need to write
5927+
the size if it is constant. */
5928+
if (type && TYPE_DOMAIN (type))
5929+
{
5930+
tree mval = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
5931+
if (mval && TREE_CODE (mval) == INTEGER_CST)
5932+
{
5933+
char buf[40];
5934+
unsigned HOST_WIDE_INT n = tree_to_uhwi (mval) + 1;
5935+
sprintf (buf, HOST_WIDE_INT_PRINT_UNSIGNED, n);
5936+
spec += buf;
5937+
}
5938+
}
5939+
spec += ']';
5940+
58425941
/* Trim the trailing NUL. */
5843-
spec.resize (specend + len);
5942+
spec.resize (spec.length ());
58445943
}
58455944

58465945
/* The (optional) list of expressions denoting the VLA bounds
58475946
N in ARGTYPE <arg>[Ni]...[Nj]...[Nk]. */
5848-
tree argvbs = TREE_CHAIN (argspec);
58495947
if (argvbs)
58505948
{
58515949
spec += ',';

0 commit comments

Comments
 (0)