/* Functions dealing with attribute handling, used by most front ends.
- Copyright (C) 1992-2019 Free Software Foundation, Inc.
+ Copyright (C) 1992-2020 Free Software Foundation, Inc.
This file is part of GCC.
}
continue;
}
- else if (list_length (args) < spec->min_length
- || (spec->max_length >= 0
- && list_length (args) > spec->max_length))
+ else
{
- error ("wrong number of arguments specified for %qE attribute",
- name);
- continue;
+ int nargs = list_length (args);
+ if (nargs < spec->min_length
+ || (spec->max_length >= 0
+ && nargs > spec->max_length))
+ {
+ error ("wrong number of arguments specified for %qE attribute",
+ name);
+ if (spec->max_length < 0)
+ inform (input_location, "expected %i or more, found %i",
+ spec->min_length, nargs);
+ else
+ inform (input_location, "expected between %i and %i, found %i",
+ spec->min_length, spec->max_length, nargs);
+ continue;
+ }
}
gcc_assert (is_attribute_p (spec->name, name));
- if (TYPE_P (*node)
- && cxx11_attr_p
- && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
- {
- /* This is a c++11 attribute that appertains to a
- type-specifier, outside of the definition of, a class
- type. Ignore it. */
- auto_diagnostic_group d;
- if (warning (OPT_Wattributes, "attribute ignored"))
- inform (input_location,
- "an attribute that appertains to a type-specifier "
- "is ignored");
- continue;
- }
-
if (spec->decl_required && !DECL_P (*anode))
{
if (flags & ((int) ATTR_FLAG_DECL_NEXT
reject incompatible attributes. */
bool built_in = flags & ATTR_FLAG_BUILT_IN;
if (spec->exclude
- && (flag_checking || !built_in))
+ && (flag_checking || !built_in)
+ && !error_operand_p (last_decl))
{
/* Always check attributes on user-defined functions.
Check them on built-ins only when -fchecking is set.
if (!built_in
|| !DECL_P (*anode)
+ || DECL_BUILT_IN_CLASS (*anode) != BUILT_IN_NORMAL
|| (DECL_FUNCTION_CODE (*anode) != BUILT_IN_UNREACHABLE
&& (DECL_FUNCTION_CODE (*anode)
!= BUILT_IN_UBSAN_HANDLE_BUILTIN_UNREACHABLE)))
}
}
+/* Initialize a mapping for a call to function FNDECL declared with
+ attribute access. Each attribute positional operand inserts one
+ entry into the mapping with the operand number as the key. */
+
+void
+init_attr_rdwr_indices (rdwr_map *rwm, tree fntype)
+{
+ if (!fntype)
+ return;
+
+ for (tree access = TYPE_ATTRIBUTES (fntype);
+ (access = lookup_attribute ("access", access));
+ access = TREE_CHAIN (access))
+ {
+ /* The TREE_VALUE of an attribute is a TREE_LIST whose TREE_VALUE
+ is the attribute argument's value. */
+ tree mode = TREE_VALUE (access);
+ gcc_assert (TREE_CODE (mode) == TREE_LIST);
+ mode = TREE_VALUE (mode);
+ gcc_assert (TREE_CODE (mode) == STRING_CST);
+
+ const char *modestr = TREE_STRING_POINTER (mode);
+ for (const char *m = modestr; *m; )
+ {
+ attr_access acc = { };
+
+ switch (*m)
+ {
+ case 'r': acc.mode = acc.read_only; break;
+ case 'w': acc.mode = acc.write_only; break;
+ case 'x': acc.mode = acc.read_write; break;
+ case '-': acc.mode = acc.none; break;
+ default: gcc_unreachable ();
+ }
+
+ char *end;
+ acc.ptrarg = strtoul (++m, &end, 10);
+ m = end;
+ if (*m == ',')
+ {
+ acc.sizarg = strtoul (++m, &end, 10);
+ m = end;
+ }
+ else
+ acc.sizarg = UINT_MAX;
+
+ acc.ptr = NULL_TREE;
+ acc.size = NULL_TREE;
+
+ /* Unconditionally add an entry for the required pointer
+ operand of the attribute, and one for the optional size
+ operand when it's specified. */
+ rwm->put (acc.ptrarg, acc);
+ if (acc.sizarg != UINT_MAX)
+ rwm->put (acc.sizarg, acc);
+ }
+ }
+}
+
#if CHECKING_P
x = value_type (NULL, NULL);
}
+ static const bool empty_zero_p = false;
+
static void mark_empty (value_type &x)
{
x = value_type ("", "");