aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family/c-attribs.cc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2022-03-31 18:31:39 -0400
committerMarek Polacek <polacek@redhat.com>2022-05-07 10:33:25 -0400
commit0c723bb4be2a67657828b692997855afcdc5d286 (patch)
tree38c8c63369f73a22cf6476c909890304e55633bb /gcc/c-family/c-attribs.cc
parentea3fbfda608a148f112f1d2f4bdd0e8bf9429cd9 (diff)
downloadgcc-0c723bb4be2a67657828b692997855afcdc5d286.zip
gcc-0c723bb4be2a67657828b692997855afcdc5d286.tar.gz
gcc-0c723bb4be2a67657828b692997855afcdc5d286.tar.bz2
c, c++: attribute format on a ctor with a vbase [PR101833, PR47634]
Attribute format takes three arguments: archetype, string-index, and first-to-check. The last two specify the position in the function parameter list. r63030 clarified that "Since non-static C++ methods have an implicit this argument, the arguments of such methods should be counted from two, not one, when giving values for string-index and first-to-check." Therefore one has to write struct D { D(const char *, ...) __attribute__((format(printf, 2, 3))); }; However -- and this is the problem in this PR -- ctors with virtual bases also get two additional parameters: the in-charge parameter and the VTT parameter (added in maybe_retrofit_in_chrg). In fact we'll end up with two clones of the ctor: an in-charge and a not-in-charge version (see build_cdtor_clones). That means that the argument position the user specified in the attribute argument will refer to different arguments, depending on which constructor we're currently dealing with. This can cause a range of problems: wrong errors, confusing warnings, or crashes. This patch corrects that; for C we don't have to do anything, and in C++ we can use num_artificial_parms_for. It would be wrong to rewrite the attributes the user supplied, so I've changed POS to be passed by reference so that we don't have to change all the call sites of positional_argument and we still get the default_conversion adjustment. Attribute format_arg is not affected, because it requires that the function returns "const char *" which will never be the case for cdtors. PR c++/101833 PR c++/47634 gcc/c-family/ChangeLog: * c-attribs.cc (positional_argument): Pass POS by reference. Deal with FN being either a function declaration or function type. Use maybe_adjust_arg_pos_for_attribute. * c-common.cc (check_function_arguments): Maybe pass FNDECL down to check_function_format. * c-common.h (maybe_adjust_arg_pos_for_attribute): Declare. (positional_argument): Adjust. * c-format.cc (get_constant): Rename to ... (validate_constant): ... this. Take EXPR by reference. Return bool instead of tree. (handle_format_arg_attribute): Don't overwrite FORMAT_NUM_EXPR by the return value of validate_constant. (decode_format_attr): Don't overwrite FORMAT_NUM_EXPR and FIRST_ARG_NUM_EXPR by the return value of validate_constant. (check_function_format): Adjust a parameter name. (handle_format_attribute): Maybe pass FNDECL down to decode_format_attr. gcc/c/ChangeLog: * c-objc-common.cc (maybe_adjust_arg_pos_for_attribute): New. gcc/cp/ChangeLog: * tree.cc (maybe_adjust_arg_pos_for_attribute): New. gcc/ChangeLog: * tree-core.h (struct attribute_spec): Update comment for HANDLER. gcc/testsuite/ChangeLog: * g++.dg/ext/attr-format-arg1.C: New test. * g++.dg/ext/attr-format1.C: New test. * g++.dg/ext/attr-format2.C: New test. * g++.dg/ext/attr-format3.C: New test.
Diffstat (limited to 'gcc/c-family/c-attribs.cc')
-rw-r--r--gcc/c-family/c-attribs.cc33
1 files changed, 22 insertions, 11 deletions
diff --git a/gcc/c-family/c-attribs.cc b/gcc/c-family/c-attribs.cc
index b1953a4..0f047a1 100644
--- a/gcc/c-family/c-attribs.cc
+++ b/gcc/c-family/c-attribs.cc
@@ -594,18 +594,23 @@ attribute_takes_identifier_p (const_tree attr_id)
}
/* Verify that argument value POS at position ARGNO to attribute NAME
- applied to function TYPE refers to a function parameter at position
- POS and the expected type CODE. Treat CODE == INTEGER_TYPE as
- matching all C integral types except bool. If successful, return
- POS after default conversions, if any. Otherwise, issue appropriate
- warnings and return null. A non-zero 1-based ARGNO should be passed
- in by callers only for attributes with more than one argument. */
+ applied to function FN (which is either a function declaration or function
+ type) refers to a function parameter at position POS and the expected type
+ CODE. Treat CODE == INTEGER_TYPE as matching all C integral types except
+ bool. If successful, return POS after default conversions (and possibly
+ adjusted by ADJUST_POS). Otherwise, issue appropriate warnings and return
+ null. A non-zero 1-based ARGNO should be passed in by callers only for
+ attributes with more than one argument.
+
+ N.B. This function modifies POS. */
tree
-positional_argument (const_tree fntype, const_tree atname, tree pos,
+positional_argument (const_tree fn, const_tree atname, tree &pos,
tree_code code, int argno /* = 0 */,
int flags /* = posargflags () */)
{
+ const_tree fndecl = TYPE_P (fn) ? NULL_TREE : fn;
+ const_tree fntype = TYPE_P (fn) ? fn : TREE_TYPE (fn);
if (pos && TREE_CODE (pos) != IDENTIFIER_NODE
&& TREE_CODE (pos) != FUNCTION_DECL)
pos = default_conversion (pos);
@@ -682,6 +687,11 @@ positional_argument (const_tree fntype, const_tree atname, tree pos,
if (!prototype_p (fntype))
return pos;
+ /* ADJUST_POS is non-zero in C++ when the function type has invisible
+ parameters generated by the compiler, such as the in-charge or VTT
+ parameters. */
+ const int adjust_pos = maybe_adjust_arg_pos_for_attribute (fndecl);
+
/* Verify that the argument position does not exceed the number
of formal arguments to the function. When POSARG_ELLIPSIS
is set, ARGNO may be beyond the last argument of a vararg
@@ -690,7 +700,7 @@ positional_argument (const_tree fntype, const_tree atname, tree pos,
if (!nargs
|| !tree_fits_uhwi_p (pos)
|| ((flags & POSARG_ELLIPSIS) == 0
- && !IN_RANGE (tree_to_uhwi (pos), 1, nargs)))
+ && !IN_RANGE (tree_to_uhwi (pos) + adjust_pos, 1, nargs)))
{
if (argno < 1)
@@ -707,8 +717,9 @@ positional_argument (const_tree fntype, const_tree atname, tree pos,
}
/* Verify that the type of the referenced formal argument matches
- the expected type. */
- unsigned HOST_WIDE_INT ipos = tree_to_uhwi (pos);
+ the expected type. Invisible parameters may have been added by
+ the compiler, so adjust the position accordingly. */
+ unsigned HOST_WIDE_INT ipos = tree_to_uhwi (pos) + adjust_pos;
/* Zero was handled above. */
gcc_assert (ipos != 0);
@@ -791,7 +802,7 @@ positional_argument (const_tree fntype, const_tree atname, tree pos,
return NULL_TREE;
}
- return pos;
+ return build_int_cst (TREE_TYPE (pos), ipos);
}
/* Return the first of DECL or TYPE attributes installed in NODE if it's