aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2020-11-10 07:26:18 -0800
committerIan Lance Taylor <iant@golang.org>2020-11-10 07:26:18 -0800
commit8d703821c69062c0cd255787d793e44f1a95d463 (patch)
tree6b1df9cdc36cc47b6164db69a14bc86a63dc77c6 /gcc/c
parent9cd320ea6572c577cdf17ce1f9ea5230b166af6d (diff)
parentcf392dbdf17e38026f8e3c0e9af7f5b87f63be56 (diff)
downloadgcc-8d703821c69062c0cd255787d793e44f1a95d463.zip
gcc-8d703821c69062c0cd255787d793e44f1a95d463.tar.gz
gcc-8d703821c69062c0cd255787d793e44f1a95d463.tar.bz2
Merge from trunk revision cf392dbdf17e38026f8e3c0e9af7f5b87f63be56.
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog90
-rw-r--r--gcc/c/c-decl.c51
-rw-r--r--gcc/c/c-parser.c605
-rw-r--r--gcc/c/c-tree.h1
-rw-r--r--gcc/c/c-typeck.c204
5 files changed, 649 insertions, 302 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 839bfa1..5b0d42c 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,93 @@
+2020-11-07 Martin Uecker <muecker@gwdg.de>
+
+ * c-parser.c (c_parser_label): Implement mixing of labels and code.
+ (c_parser_all_labels): Likewise.
+
+2020-11-06 Iain Sandoe <iain@sandoe.co.uk>
+
+ * c-parser.c (c_parser_objc_at_property_declaration):
+ Improve parsing fidelity. Associate better location info
+ with @property attributes. Clean up the interface to
+ objc_add_property_declaration ().
+
+2020-11-06 Nathan Sidwell <nathan@acm.org>
+
+ * c-decl.c (diagnose_mismatched_decls): Rename
+ DECL_IS_BUILTIN->DECL_IS_UNDECLARED_BUILTIN.
+ (warn_if_shadowing, implicitly_declare, names_builtin_p)
+ (collect_source_refs): Likewise.
+ * c-typeck.c (inform_declaration, inform_for_arg)
+ (convert_for_assignment): Likewise.
+
+2020-11-06 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_atomic): Add openacc parameter and update
+ OpenACC matching.
+ (c_parser_omp_construct): Update call.
+
+2020-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/97670
+ * c-typeck.c (c_finish_omp_clauses): Look through array reductions to
+ find underlying decl to clear in the aligned_head bitmap.
+
+2020-11-04 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.c (handle_nodiscard_attribute): New.
+ (std_attribute_table): Add nodiscard.
+ * c-parser.c (c_parser_std_attribute): Expect argument to
+ nodiscard attribute to be a string. Do not special-case ignoring
+ nodiscard.
+ * c-typeck.c (maybe_warn_nodiscard): New.
+ (build_compound_expr, emit_side_effect_warnings): Call
+ maybe_warn_nodiscard.
+ (c_process_expr_stmt, c_finish_stmt_expr): Also call
+ emit_side_effect_warnings if warn_unused_result.
+
+2020-10-29 Asher Gordon <AsDaGo@posteo.net>
+
+ * c-typeck.c (free_all_tagged_tu_seen_up_to): Replace free
+ with XDELETE.
+ (finish_init): Likewise.
+ (pop_init_level): Likewise.
+
+2020-10-28 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.c (store_parm_decls_newstyle): Use pedwarn_c11 not
+ error_at for omitted parameter name.
+
+2020-10-28 Jakub Jelinek <jakub@redhat.com>
+
+ * c-parser.c (c_parser_omp_clause_name): Handle allocate.
+ (c_parser_omp_clause_allocate): New function.
+ (c_parser_omp_all_clauses): Handle PRAGMA_OMP_CLAUSE_ALLOCATE.
+ (OMP_FOR_CLAUSE_MASK, OMP_SECTIONS_CLAUSE_MASK,
+ OMP_PARALLEL_CLAUSE_MASK, OMP_SINGLE_CLAUSE_MASK,
+ OMP_TASK_CLAUSE_MASK, OMP_TASKGROUP_CLAUSE_MASK,
+ OMP_DISTRIBUTE_CLAUSE_MASK, OMP_TEAMS_CLAUSE_MASK,
+ OMP_TARGET_CLAUSE_MASK, OMP_TASKLOOP_CLAUSE_MASK): Add
+ PRAGMA_OMP_CLAUSE_ALLOCATE.
+ * c-typeck.c (c_finish_omp_clauses): Handle OMP_CLAUSE_ALLOCATE.
+
+2020-10-27 Joseph Myers <joseph@codesourcery.com>
+
+ * c-parser.c (c_parser_std_attribute_specifier): Allow duplicate
+ standard attributes.
+
+2020-10-23 Marek Polacek <polacek@redhat.com>
+
+ PR c++/91741
+ * c-parser.c (c_parser_binary_expression): Implement -Wsizeof-array-div.
+ (c_parser_postfix_expression): Set PAREN_SIZEOF_EXPR.
+ (c_parser_expr_list): Handle PAREN_SIZEOF_EXPR like SIZEOF_EXPR.
+ * c-tree.h (char_type_p): Declare.
+ * c-typeck.c (char_type_p): No longer static.
+
+2020-10-23 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97552
+ * c-decl.c (get_parm_array_spec): Handle static VLA parameters.
+
2020-09-19 Martin Sebor <msebor@redhat.com>
PR c/50584
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 81b9adb..f19c82c 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -2051,7 +2051,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
}
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_IS_BUILTIN (olddecl))
+ && DECL_IS_UNDECLARED_BUILTIN (olddecl))
{
/* A conflicting function declaration for a predeclared
function that isn't actually built in. Objective C uses
@@ -2265,7 +2265,7 @@ diagnose_mismatched_decls (tree newdecl, tree olddecl,
built in, newdecl silently overrides olddecl. The latter
occur only in Objective C; see also above. (FIXME: Make
Objective C use normal builtins.) */
- if (!DECL_IS_BUILTIN (olddecl)
+ if (!DECL_IS_UNDECLARED_BUILTIN (olddecl)
&& !DECL_EXTERN_INLINE (olddecl))
{
auto_diagnostic_group d;
@@ -2978,7 +2978,7 @@ warn_if_shadowing (tree new_decl)
|| warn_shadow_local
|| warn_shadow_compatible_local)
/* No shadow warnings for internally generated vars. */
- || DECL_IS_BUILTIN (new_decl))
+ || DECL_IS_UNDECLARED_BUILTIN (new_decl))
return;
/* Is anything being shadowed? Invisible decls do not count. */
@@ -3631,7 +3631,7 @@ implicitly_declare (location_t loc, tree functionid)
in the external scope because they're pushed before the file
scope gets created. Catch this here and rebind them into the
file scope. */
- if (!fndecl_built_in_p (decl) && DECL_IS_BUILTIN (decl))
+ if (!fndecl_built_in_p (decl) && DECL_IS_UNDECLARED_BUILTIN (decl))
{
bind (functionid, decl, file_scope,
/*invisible=*/false, /*nested=*/true,
@@ -4400,6 +4400,31 @@ lookup_name_fuzzy (tree name, enum lookup_name_fuzzy_kind kind, location_t loc)
}
+/* Handle the standard [[nodiscard]] attribute. */
+
+static tree
+handle_nodiscard_attribute (tree *node, tree name, tree /*args*/,
+ int /*flags*/, bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) == FUNCTION_DECL)
+ {
+ if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
+ warning_at (DECL_SOURCE_LOCATION (*node),
+ OPT_Wattributes, "%qE attribute applied to %qD with void "
+ "return type", name, *node);
+ }
+ else if (RECORD_OR_UNION_TYPE_P (*node)
+ || TREE_CODE (*node) == ENUMERAL_TYPE)
+ /* OK */;
+ else
+ {
+ pedwarn (input_location,
+ OPT_Wattributes, "%qE attribute can only be applied to "
+ "functions or to structure, union or enumeration types", name);
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
/* Table of supported standard (C2x) attributes. */
const struct attribute_spec std_attribute_table[] =
{
@@ -4411,6 +4436,8 @@ const struct attribute_spec std_attribute_table[] =
handle_fallthrough_attribute, NULL },
{ "maybe_unused", 0, 0, false, false, false, false,
handle_unused_attribute, NULL },
+ { "nodiscard", 0, 1, false, false, false, false,
+ handle_nodiscard_attribute, NULL },
{ NULL, 0, 0, false, false, false, false, NULL, NULL }
};
@@ -5784,6 +5811,9 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
continue;
}
+ if (pd->u.array.static_p)
+ spec += 's';
+
if (TREE_CODE (nelts) == INTEGER_CST)
{
/* Skip all constant bounds except the most significant one.
@@ -5796,9 +5826,8 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
return attrs;
char buf[40];
- const char *code = pd->u.array.static_p ? "s" : "";
unsigned HOST_WIDE_INT n = tree_to_uhwi (nelts);
- sprintf (buf, "%s%llu", code, (unsigned long long)n);
+ sprintf (buf, "%llu", (unsigned long long)n);
spec += buf;
break;
}
@@ -9628,7 +9657,9 @@ store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
warn_if_shadowing (decl);
}
else
- error_at (DECL_SOURCE_LOCATION (decl), "parameter name omitted");
+ pedwarn_c11 (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+ "ISO C does not support omitting parameter names in "
+ "function definitions before C2X");
}
/* Record the parameter list in the function declaration. */
@@ -10469,7 +10500,7 @@ names_builtin_p (const char *name)
{
tree id = get_identifier (name);
if (tree decl = identifier_global_value (id))
- return TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_BUILTIN (decl);
+ return TREE_CODE (decl) == FUNCTION_DECL && DECL_IS_UNDECLARED_BUILTIN (decl);
/* Also detect common reserved C words that aren't strictly built-in
functions. */
@@ -12103,12 +12134,12 @@ collect_source_refs (void)
{
decls = DECL_INITIAL (t);
for (decl = BLOCK_VARS (decls); decl; decl = TREE_CHAIN (decl))
- if (!DECL_IS_BUILTIN (decl))
+ if (!DECL_IS_UNDECLARED_BUILTIN (decl))
collect_source_ref (DECL_SOURCE_FILE (decl));
}
for (decl = BLOCK_VARS (ext_block); decl; decl = TREE_CHAIN (decl))
- if (!DECL_IS_BUILTIN (decl))
+ if (!DECL_IS_UNDECLARED_BUILTIN (decl))
collect_source_ref (DECL_SOURCE_FILE (decl));
}
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 7d58356..377914c 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -1521,7 +1521,7 @@ static void c_parser_initval (c_parser *, struct c_expr *,
struct obstack *);
static tree c_parser_compound_statement (c_parser *, location_t * = NULL);
static location_t c_parser_compound_statement_nostart (c_parser *);
-static void c_parser_label (c_parser *);
+static void c_parser_label (c_parser *, tree);
static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
static void c_parser_statement_after_labels (c_parser *, bool *,
vec<tree> * = NULL);
@@ -4950,7 +4950,8 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
&& attribute_takes_identifier_p (name));
bool require_string
= (ns == NULL_TREE
- && strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0);
+ && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0
+ || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0));
TREE_VALUE (attribute)
= c_parser_attribute_arguments (parser, takes_identifier,
require_string, false);
@@ -4960,13 +4961,12 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
parens.require_close (parser);
}
out:
- if (ns == NULL_TREE && !for_tm && !as && !is_attribute_p ("nodiscard", name))
+ if (ns == NULL_TREE && !for_tm && !as)
{
/* An attribute with standard syntax and no namespace specified
is a constraint violation if it is not one of the known
- standard attributes (of which nodiscard is the only one
- without a handler in GCC). Diagnose it here with a pedwarn
- and then discard it to prevent a duplicate warning later. */
+ standard attributes. Diagnose it here with a pedwarn and
+ then discard it to prevent a duplicate warning later. */
pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
name);
return error_mark_node;
@@ -4977,9 +4977,6 @@ c_parser_std_attribute (c_parser *parser, bool for_tm)
static tree
c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
{
- bool seen_deprecated = false;
- bool seen_fallthrough = false;
- bool seen_maybe_unused = false;
location_t loc = c_parser_peek_token (parser)->location;
if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
return NULL_TREE;
@@ -5005,55 +5002,8 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
tree attribute = c_parser_std_attribute (parser, for_tm);
if (attribute != error_mark_node)
{
- bool duplicate = false;
- tree name = get_attribute_name (attribute);
- tree ns = get_attribute_namespace (attribute);
- if (ns == NULL_TREE)
- {
- /* Some standard attributes may appear at most once in
- each attribute list. Diagnose duplicates and remove
- them from the list to avoid subsequent diagnostics
- such as the more general one for multiple
- "fallthrough" attributes in the same place (including
- in separate attribute lists in the same attribute
- specifier sequence, which is not a constraint
- violation). */
- if (is_attribute_p ("deprecated", name))
- {
- if (seen_deprecated)
- {
- error ("attribute %<deprecated%> can appear at most "
- "once in an attribute-list");
- duplicate = true;
- }
- seen_deprecated = true;
- }
- else if (is_attribute_p ("fallthrough", name))
- {
- if (seen_fallthrough)
- {
- error ("attribute %<fallthrough%> can appear at most "
- "once in an attribute-list");
- duplicate = true;
- }
- seen_fallthrough = true;
- }
- else if (is_attribute_p ("maybe_unused", name))
- {
- if (seen_maybe_unused)
- {
- error ("attribute %<maybe_unused%> can appear at most "
- "once in an attribute-list");
- duplicate = true;
- }
- seen_maybe_unused = true;
- }
- }
- if (!duplicate)
- {
- TREE_CHAIN (attribute) = attributes;
- attributes = attribute;
- }
+ TREE_CHAIN (attribute) = attributes;
+ attributes = attribute;
}
if (c_parser_next_token_is_not (parser, CPP_COMMA))
break;
@@ -5573,7 +5523,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
}
/* Parse a compound statement (possibly a function body) (C90 6.6.2,
- C99 6.8.2, C11 6.8.2).
+ C99 6.8.2, C11 6.8.2, C2X 6.8.2).
compound-statement:
{ block-item-list[opt] }
@@ -5584,6 +5534,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
block-item-list block-item
block-item:
+ label
nested-declaration
statement
@@ -5724,7 +5675,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
{
location_t loc = c_parser_peek_token (parser)->location;
loc = expansion_point_location_if_in_system_header (loc);
- /* Standard attributes may start a statement or a declaration. */
+ /* Standard attributes may start a label, statement or declaration. */
bool have_std_attrs
= c_parser_nth_token_starts_std_attributes (parser, 1);
tree std_attrs = NULL_TREE;
@@ -5735,7 +5686,6 @@ c_parser_compound_statement_nostart (c_parser *parser)
|| (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON))
{
- c_warn_unused_attributes (std_attrs);
if (c_parser_next_token_is_keyword (parser, RID_CASE))
label_loc = c_parser_peek_2nd_token (parser)->location;
else
@@ -5743,27 +5693,31 @@ c_parser_compound_statement_nostart (c_parser *parser)
last_label = true;
last_stmt = false;
mark_valid_location_for_stdc_pragma (false);
- c_parser_label (parser);
+ c_parser_label (parser, std_attrs);
}
- else if (!last_label
- && (c_parser_next_tokens_start_declaration (parser)
- || (have_std_attrs
- && c_parser_next_token_is (parser, CPP_SEMICOLON))))
+ else if (c_parser_next_tokens_start_declaration (parser)
+ || (have_std_attrs
+ && c_parser_next_token_is (parser, CPP_SEMICOLON)))
{
- last_label = false;
+ if (last_label)
+ pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic,
+ "a label can only be part of a statement and "
+ "a declaration is not a statement");
+
mark_valid_location_for_stdc_pragma (false);
bool fallthru_attr_p = false;
c_parser_declaration_or_fndef (parser, true, !have_std_attrs,
true, true, true, NULL,
vNULL, have_std_attrs, std_attrs,
NULL, &fallthru_attr_p);
+
if (last_stmt && !fallthru_attr_p)
pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
"ISO C90 forbids mixed declarations and code");
last_stmt = fallthru_attr_p;
+ last_label = false;
}
- else if (!last_label
- && c_parser_next_token_is_keyword (parser, RID_EXTENSION))
+ else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
{
/* __extension__ can start a declaration, but is also an
unary operator that can start an expression. Consume all
@@ -5846,7 +5800,7 @@ c_parser_compound_statement_nostart (c_parser *parser)
parser->error = false;
}
if (last_label)
- error_at (label_loc, "label at end of compound statement");
+ pedwarn_c11 (label_loc, OPT_Wpedantic, "label at end of compound statement");
location_t endloc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
/* Restore the value we started with. */
@@ -5862,19 +5816,29 @@ c_parser_compound_statement_nostart (c_parser *parser)
static void
c_parser_all_labels (c_parser *parser)
{
+ tree std_attrs = NULL;
if (c_parser_nth_token_starts_std_attributes (parser, 1))
{
- tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
+ std_attrs = c_parser_std_attribute_specifier_sequence (parser);
if (c_parser_next_token_is (parser, CPP_SEMICOLON))
c_parser_error (parser, "expected statement");
- else
- c_warn_unused_attributes (std_attrs);
}
while (c_parser_next_token_is_keyword (parser, RID_CASE)
|| c_parser_next_token_is_keyword (parser, RID_DEFAULT)
|| (c_parser_next_token_is (parser, CPP_NAME)
&& c_parser_peek_2nd_token (parser)->type == CPP_COLON))
- c_parser_label (parser);
+ {
+ c_parser_label (parser, std_attrs);
+ std_attrs = NULL;
+ if (c_parser_nth_token_starts_std_attributes (parser, 1))
+ {
+ std_attrs = c_parser_std_attribute_specifier_sequence (parser);
+ if (c_parser_next_token_is (parser, CPP_SEMICOLON))
+ c_parser_error (parser, "expected statement");
+ }
+ }
+ if (std_attrs)
+ c_warn_unused_attributes (std_attrs);
}
/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
@@ -5896,9 +5860,8 @@ c_parser_all_labels (c_parser *parser)
in the caller, to distinguish statements from declarations. Any
attribute-specifier-sequence after the label is parsed in this
function. */
-
static void
-c_parser_label (c_parser *parser)
+c_parser_label (c_parser *parser, tree std_attrs)
{
location_t loc1 = c_parser_peek_token (parser)->location;
tree label = NULL_TREE;
@@ -5948,8 +5911,13 @@ c_parser_label (c_parser *parser)
if (tlab)
{
decl_attributes (&tlab, attrs, 0);
+ decl_attributes (&tlab, std_attrs, 0);
label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
}
+ if (attrs
+ && c_parser_next_tokens_start_declaration (parser))
+ warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
+ " label and declaration appertains to the label");
}
if (label)
{
@@ -5957,55 +5925,6 @@ c_parser_label (c_parser *parser)
FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
else
FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
-
- /* Standard attributes are only allowed here if they start a
- statement, not a declaration (including the case of an
- attribute-declaration with only attributes). */
- bool have_std_attrs
- = c_parser_nth_token_starts_std_attributes (parser, 1);
- tree std_attrs = NULL_TREE;
- if (have_std_attrs)
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
-
- /* Allow '__attribute__((fallthrough));'. */
- if (!have_std_attrs
- && c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- {
- location_t loc = c_parser_peek_token (parser)->location;
- tree attrs = c_parser_gnu_attributes (parser);
- if (attribute_fallthrough_p (attrs))
- {
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- tree fn = build_call_expr_internal_loc (loc,
- IFN_FALLTHROUGH,
- void_type_node, 0);
- add_stmt (fn);
- }
- else
- warning_at (loc, OPT_Wattributes, "%<fallthrough%> attribute "
- "not followed by %<;%>");
- }
- else if (attrs != NULL_TREE)
- warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
- " can be applied to a null statement");
- }
- if (c_parser_next_tokens_start_declaration (parser)
- || (have_std_attrs
- && c_parser_next_token_is (parser, CPP_SEMICOLON)))
- {
- error_at (c_parser_peek_token (parser)->location,
- "a label can only be part of a statement and "
- "a declaration is not a statement");
- c_parser_declaration_or_fndef (parser, /*fndef_ok*/ false,
- /*static_assert_ok*/ true,
- /*empty_ok*/ true, /*nested*/ true,
- /*start_attr_ok*/ true, NULL,
- vNULL, have_std_attrs, std_attrs);
- }
- else if (std_attrs)
- /* Nonempty attributes on the following statement are ignored. */
- c_warn_unused_attributes (std_attrs);
}
}
@@ -7876,7 +7795,7 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
enum tree_code op;
/* The source location of this operation. */
location_t loc;
- /* The sizeof argument if expr.original_code == SIZEOF_EXPR. */
+ /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR. */
tree sizeof_arg;
} stack[NUM_PRECS];
int sp;
@@ -7894,9 +7813,11 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
== truthvalue_true_node); \
break; \
- case TRUNC_DIV_EXPR: \
- if (stack[sp - 1].expr.original_code == SIZEOF_EXPR \
- && stack[sp].expr.original_code == SIZEOF_EXPR) \
+ case TRUNC_DIV_EXPR: \
+ if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR \
+ || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR) \
+ && (stack[sp].expr.original_code == SIZEOF_EXPR \
+ || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR)) \
{ \
tree type0 = stack[sp - 1].sizeof_arg; \
tree type1 = stack[sp].sizeof_arg; \
@@ -7910,18 +7831,23 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
&& !(TREE_CODE (first_arg) == PARM_DECL \
&& C_ARRAY_PARAMETER (first_arg) \
&& warn_sizeof_array_argument)) \
- { \
- auto_diagnostic_group d; \
- if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
- "division %<sizeof (%T) / sizeof (%T)%> " \
- "does not compute the number of array " \
- "elements", \
- type0, type1)) \
- if (DECL_P (first_arg)) \
- inform (DECL_SOURCE_LOCATION (first_arg), \
- "first %<sizeof%> operand was declared here"); \
- } \
- } \
+ { \
+ auto_diagnostic_group d; \
+ if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
+ "division %<sizeof (%T) / sizeof (%T)%> " \
+ "does not compute the number of array " \
+ "elements", \
+ type0, type1)) \
+ if (DECL_P (first_arg)) \
+ inform (DECL_SOURCE_LOCATION (first_arg), \
+ "first %<sizeof%> operand was declared here"); \
+ } \
+ else if (TREE_CODE (type0) == ARRAY_TYPE \
+ && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0))) \
+ && stack[sp].expr.original_code != PAREN_SIZEOF_EXPR) \
+ maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, type0, \
+ stack[sp].sizeof_arg, type1); \
+ } \
break; \
default: \
break; \
@@ -9177,6 +9103,9 @@ c_parser_postfix_expression (c_parser *parser)
if (expr.original_code != C_MAYBE_CONST_EXPR
&& expr.original_code != SIZEOF_EXPR)
expr.original_code = ERROR_MARK;
+ /* Remember that we saw ( ) around the sizeof. */
+ if (expr.original_code == SIZEOF_EXPR)
+ expr.original_code = PAREN_SIZEOF_EXPR;
/* Don't change EXPR.ORIGINAL_TYPE. */
location_t loc_close_paren = c_parser_peek_token (parser)->location;
set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren);
@@ -10792,7 +10721,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
if (locations)
locations->safe_push (expr.get_location ());
if (sizeof_arg != NULL
- && expr.original_code == SIZEOF_EXPR)
+ && (expr.original_code == SIZEOF_EXPR
+ || expr.original_code == PAREN_SIZEOF_EXPR))
{
sizeof_arg[0] = c_last_sizeof_arg;
sizeof_arg_loc[0] = c_last_sizeof_loc;
@@ -10815,7 +10745,8 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
locations->safe_push (expr.get_location ());
if (++idx < 3
&& sizeof_arg != NULL
- && expr.original_code == SIZEOF_EXPR)
+ && (expr.original_code == SIZEOF_EXPR
+ || expr.original_code == PAREN_SIZEOF_EXPR))
{
sizeof_arg[idx] = c_last_sizeof_arg;
sizeof_arg_loc[idx] = c_last_sizeof_loc;
@@ -11996,158 +11927,196 @@ c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
static void
c_parser_objc_at_property_declaration (c_parser *parser)
{
- /* The following variables hold the attributes of the properties as
- parsed. They are 'false' or 'NULL_TREE' if the attribute was not
- seen. When we see an attribute, we set them to 'true' (if they
- are boolean properties) or to the identifier (if they have an
- argument, ie, for getter and setter). Note that here we only
- parse the list of attributes, check the syntax and accumulate the
- attributes that we find. objc_add_property_declaration() will
- then process the information. */
- bool property_assign = false;
- bool property_copy = false;
- tree property_getter_ident = NULL_TREE;
- bool property_nonatomic = false;
- bool property_readonly = false;
- bool property_readwrite = false;
- bool property_retain = false;
- tree property_setter_ident = NULL_TREE;
-
- /* 'properties' is the list of properties that we read. Usually a
- single one, but maybe more (eg, in "@property int a, b, c;" there
- are three). */
- tree properties;
- location_t loc;
-
- loc = c_parser_peek_token (parser)->location;
gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
-
+ location_t loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser); /* Eat '@property'. */
- /* Parse the optional attribute list... */
+ /* Parse the optional attribute list.
+
+ A list of parsed, but not verified, attributes. */
+ vec<property_attribute_info *> prop_attr_list = vNULL;
+
+ bool syntax_error = false;
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
matching_parens parens;
+ location_t attr_start = c_parser_peek_token (parser)->location;
/* Eat the '(' */
parens.consume_open (parser);
/* Property attribute keywords are valid now. */
parser->objc_property_attr_context = true;
- while (true)
+ /* Allow @property (), with a warning. */
+ location_t attr_end = c_parser_peek_token (parser)->location;
+
+ if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
{
- bool syntax_error = false;
- c_token *token = c_parser_peek_token (parser);
- enum rid keyword;
+ location_t attr_comb = make_location (attr_end, attr_start, attr_end);
+ warning_at (attr_comb, OPT_Wattributes,
+ "empty property attribute list");
+ }
+ else
+ while (true)
+ {
+ c_token *token = c_parser_peek_token (parser);
+ attr_start = token->location;
+ attr_end = get_finish (token->location);
+ location_t attr_comb = make_location (attr_start, attr_start,
+ attr_end);
- if (token->type != CPP_KEYWORD)
- {
- if (token->type == CPP_CLOSE_PAREN)
- c_parser_error (parser, "expected identifier");
- else
- {
- c_parser_consume_token (parser);
- c_parser_error (parser, "unknown property attribute");
- }
- break;
- }
- keyword = token->keyword;
- c_parser_consume_token (parser);
- switch (keyword)
- {
- case RID_ASSIGN: property_assign = true; break;
- case RID_COPY: property_copy = true; break;
- case RID_NONATOMIC: property_nonatomic = true; break;
- case RID_READONLY: property_readonly = true; break;
- case RID_READWRITE: property_readwrite = true; break;
- case RID_RETAIN: property_retain = true; break;
-
- case RID_GETTER:
- case RID_SETTER:
- if (c_parser_next_token_is_not (parser, CPP_EQ))
- {
- if (keyword == RID_GETTER)
- c_parser_error (parser,
- "missing %<=%> (after %<getter%> attribute)");
- else
- c_parser_error (parser,
- "missing %<=%> (after %<setter%> attribute)");
- syntax_error = true;
- break;
- }
- c_parser_consume_token (parser); /* eat the = */
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- syntax_error = true;
+ if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
+ {
+ warning_at (attr_comb, OPT_Wattributes,
+ "missing property attribute");
+ if (token->type == CPP_CLOSE_PAREN)
break;
- }
- if (keyword == RID_SETTER)
- {
- if (property_setter_ident != NULL_TREE)
- c_parser_error (parser, "the %<setter%> attribute may only be specified once");
- else
- property_setter_ident = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_COLON))
- c_parser_error (parser, "setter name must terminate with %<:%>");
- else
- c_parser_consume_token (parser);
- }
- else
- {
- if (property_getter_ident != NULL_TREE)
- c_parser_error (parser, "the %<getter%> attribute may only be specified once");
- else
- property_getter_ident = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
- break;
- default:
- c_parser_error (parser, "unknown property attribute");
- syntax_error = true;
- break;
+ c_parser_consume_token (parser);
+ continue;
+ }
+
+ tree attr_name = NULL_TREE;
+ enum rid keyword = RID_MAX; /* Not a valid property attribute. */
+ bool add_at = false;
+ if (token->type == CPP_KEYWORD)
+ {
+ keyword = token->keyword;
+ if (OBJC_IS_AT_KEYWORD (keyword))
+ {
+ /* For '@' keywords the token value has the keyword,
+ prepend the '@' for diagnostics. */
+ attr_name = token->value;
+ add_at = true;
+ }
+ else
+ attr_name = ridpointers[(int)keyword];
+ }
+ else if (token->type == CPP_NAME)
+ attr_name = token->value;
+ c_parser_consume_token (parser);
+
+ enum objc_property_attribute_kind prop_kind
+ = objc_prop_attr_kind_for_rid (keyword);
+ property_attribute_info *prop
+ = new property_attribute_info (attr_name, attr_comb, prop_kind);
+ prop_attr_list.safe_push (prop);
+
+ tree meth_name;
+ switch (prop->prop_kind)
+ {
+ default: break;
+ case OBJC_PROPERTY_ATTR_UNKNOWN:
+ if (attr_name)
+ error_at (attr_comb, "unknown property attribute %<%s%s%>",
+ add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
+ else
+ error_at (attr_comb, "unknown property attribute");
+ prop->parse_error = syntax_error = true;
+ break;
+
+ case OBJC_PROPERTY_ATTR_GETTER:
+ case OBJC_PROPERTY_ATTR_SETTER:
+ if (c_parser_next_token_is_not (parser, CPP_EQ))
+ {
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ error_at (attr_comb, "expected %<=%> after Objective-C %qE",
+ attr_name);
+ prop->parse_error = syntax_error = true;
+ break;
+ }
+ token = c_parser_peek_token (parser);
+ attr_end = token->location;
+ c_parser_consume_token (parser); /* eat the = */
+ if (c_parser_next_token_is_not (parser, CPP_NAME))
+ {
+ attr_comb = make_location (attr_end, attr_start, attr_end);
+ error_at (attr_comb, "expected %qE selector name",
+ attr_name);
+ prop->parse_error = syntax_error = true;
+ break;
+ }
+ /* Get the end of the method name, and consume the name. */
+ token = c_parser_peek_token (parser);
+ attr_end = get_finish (token->location);
+ meth_name = token->value;
+ c_parser_consume_token (parser);
+ if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
+ {
+ if (c_parser_next_token_is_not (parser, CPP_COLON))
+ {
+ attr_comb = make_location (attr_end, attr_start,
+ attr_end);
+ error_at (attr_comb, "setter method names must"
+ " terminate with %<:%>");
+ prop->parse_error = syntax_error = true;
+ }
+ else
+ {
+ attr_end = get_finish (c_parser_peek_token
+ (parser)->location);
+ c_parser_consume_token (parser);
+ }
+ attr_comb = make_location (attr_start, attr_start,
+ attr_end);
+ }
+ else
+ attr_comb = make_location (attr_start, attr_start,
+ attr_end);
+ prop->ident = meth_name;
+ /* Updated location including all that was successfully
+ parsed. */
+ prop->prop_loc = attr_comb;
+ break;
}
- if (syntax_error)
- break;
-
+ /* If we see a comma here, then keep going - even if we already
+ saw a syntax error. For simple mistakes e.g. (asign, getter=x)
+ this makes a more useful output and avoid spurious warnings about
+ missing attributes that are, in fact, specified after the one with
+ the syntax error. */
if (c_parser_next_token_is (parser, CPP_COMMA))
c_parser_consume_token (parser);
else
break;
}
parser->objc_property_attr_context = false;
- parens.skip_until_found_close (parser);
- }
- /* ... and the property declaration(s). */
- properties = c_parser_struct_declaration (parser);
- if (properties == error_mark_node)
- {
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- parser->error = false;
- return;
+ if (syntax_error && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
+ /* We don't really want to chew the whole of the file looking for a
+ matching closing parenthesis, so we will try to read the decl and
+ let the error handling for that close out the statement. */
+ ;
+ else
+ syntax_error = false, parens.skip_until_found_close (parser);
}
- if (properties == NULL_TREE)
- c_parser_error (parser, "expected identifier");
+ /* 'properties' is the list of properties that we read. Usually a
+ single one, but maybe more (eg, in "@property int a, b, c;" there
+ are three). */
+ tree properties = c_parser_struct_declaration (parser);
+
+ if (properties == error_mark_node)
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
else
{
- /* Comma-separated properties are chained together in
- reverse order; add them one by one. */
- properties = nreverse (properties);
-
- for (; properties; properties = TREE_CHAIN (properties))
- objc_add_property_declaration (loc, copy_node (properties),
- property_readonly, property_readwrite,
- property_assign, property_retain,
- property_copy, property_nonatomic,
- property_getter_ident, property_setter_ident);
+ if (properties == NULL_TREE)
+ c_parser_error (parser, "expected identifier");
+ else
+ {
+ /* Comma-separated properties are chained together in reverse order;
+ add them one by one. */
+ properties = nreverse (properties);
+ for (; properties; properties = TREE_CHAIN (properties))
+ objc_add_property_declaration (loc, copy_node (properties),
+ prop_attr_list);
+ }
+ c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
+ while (!prop_attr_list.is_empty())
+ delete prop_attr_list.pop ();
+ prop_attr_list.release ();
parser->error = false;
}
@@ -12641,6 +12610,8 @@ c_parser_omp_clause_name (c_parser *parser)
case 'a':
if (!strcmp ("aligned", p))
result = PRAGMA_OMP_CLAUSE_ALIGNED;
+ else if (!strcmp ("allocate", p))
+ result = PRAGMA_OMP_CLAUSE_ALLOCATE;
else if (!strcmp ("async", p))
result = PRAGMA_OACC_CLAUSE_ASYNC;
else if (!strcmp ("attach", p))
@@ -15150,6 +15121,62 @@ c_parser_omp_clause_aligned (c_parser *parser, tree list)
return nl;
}
+/* OpenMP 5.0:
+ allocate ( variable-list )
+ allocate ( expression : variable-list ) */
+
+static tree
+c_parser_omp_clause_allocate (c_parser *parser, tree list)
+{
+ location_t clause_loc = c_parser_peek_token (parser)->location;
+ tree nl, c;
+ tree allocator = NULL_TREE;
+
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ return list;
+
+ if ((c_parser_next_token_is_not (parser, CPP_NAME)
+ && c_parser_next_token_is_not (parser, CPP_KEYWORD))
+ || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
+ && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
+ {
+ location_t expr_loc = c_parser_peek_token (parser)->location;
+ c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
+ allocator = expr.value;
+ allocator = c_fully_fold (allocator, false, NULL);
+ tree orig_type
+ = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
+ orig_type = TYPE_MAIN_VARIANT (orig_type);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
+ || TREE_CODE (orig_type) != ENUMERAL_TYPE
+ || TYPE_NAME (orig_type) != get_identifier ("omp_allocator_handle_t"))
+ {
+ error_at (clause_loc, "%<allocate%> clause allocator expression "
+ "has type %qT rather than "
+ "%<omp_allocator_handle_t%>",
+ TREE_TYPE (allocator));
+ allocator = NULL_TREE;
+ }
+ if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
+ {
+ parens.skip_until_found_close (parser);
+ return list;
+ }
+ }
+
+ nl = c_parser_omp_variable_list (parser, clause_loc,
+ OMP_CLAUSE_ALLOCATE, list);
+
+ if (allocator)
+ for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+
+ parens.skip_until_found_close (parser);
+ return nl;
+}
+
/* OpenMP 4.0:
linear ( variable-list )
linear ( variable-list : expression )
@@ -16392,6 +16419,10 @@ c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
clauses = c_parser_omp_clause_aligned (parser, clauses);
c_name = "aligned";
break;
+ case PRAGMA_OMP_CLAUSE_ALLOCATE:
+ clauses = c_parser_omp_clause_allocate (parser, clauses);
+ c_name = "allocate";
+ break;
case PRAGMA_OMP_CLAUSE_LINEAR:
clauses = c_parser_omp_clause_linear (parser, clauses);
c_name = "linear";
@@ -17280,7 +17311,7 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
LOC is the location of the #pragma token. */
static void
-c_parser_omp_atomic (location_t loc, c_parser *parser)
+c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
{
tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE;
tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
@@ -17319,6 +17350,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
new_code = OMP_ATOMIC;
else if (!strcmp (p, "capture"))
new_code = OMP_ATOMIC_CAPTURE_NEW;
+ else if (openacc)
+ {
+ p = NULL;
+ error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
+ "or %<capture%> clause");
+ }
else if (!strcmp (p, "seq_cst"))
new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
else if (!strcmp (p, "acq_rel"))
@@ -17346,7 +17383,12 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
{
if (new_code != ERROR_MARK)
{
- if (code != ERROR_MARK)
+ /* OpenACC permits 'update capture'. */
+ if (openacc
+ && code == OMP_ATOMIC
+ && new_code == OMP_ATOMIC_CAPTURE_NEW)
+ code = new_code;
+ else if (code != ERROR_MARK)
error_at (cloc, "too many atomic clauses");
else
code = new_code;
@@ -17368,7 +17410,9 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
if (code == ERROR_MARK)
code = OMP_ATOMIC;
- if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
+ if (openacc)
+ memory_order = OMP_MEMORY_ORDER_RELAXED;
+ else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
{
omp_requires_mask
= (enum omp_requires) (omp_requires_mask
@@ -17424,6 +17468,7 @@ c_parser_omp_atomic (location_t loc, c_parser *parser)
}
break;
case OMP_ATOMIC:
+ /* case OMP_ATOMIC_CAPTURE_NEW: - or update to OpenMP 5.1 */
if (memory_order == OMP_MEMORY_ORDER_ACQ_REL
|| memory_order == OMP_MEMORY_ORDER_ACQUIRE)
{
@@ -18572,6 +18617,7 @@ c_parser_omp_simd (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
static tree
@@ -18863,6 +18909,7 @@ c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
@@ -18917,6 +18964,7 @@ c_parser_omp_sections (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
static tree
@@ -19058,6 +19106,7 @@ c_parser_omp_parallel (location_t loc, c_parser *parser,
( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
static tree
@@ -19092,6 +19141,7 @@ c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
static tree
@@ -19162,7 +19212,8 @@ c_parser_omp_taskyield (c_parser *parser)
*/
#define OMP_TASKGROUP_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
+ ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
static tree
c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
@@ -19263,6 +19314,7 @@ c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
@@ -19352,6 +19404,7 @@ c_parser_omp_distribute (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
static tree
@@ -19458,6 +19511,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
"#pragma omp target data");
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -19475,6 +19529,7 @@ c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -19598,6 +19653,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
"#pragma omp target enter data");
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -19611,6 +19667,7 @@ c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -19682,7 +19739,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
tree clauses
= c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
"#pragma omp target exit data");
-
+ c_omp_adjust_map_clauses (clauses, false);
int map_seen = 0;
for (tree *pc = &clauses; *pc;)
{
@@ -19697,6 +19754,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
break;
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
map_seen |= 1;
@@ -19739,6 +19797,7 @@ c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR))
@@ -19906,6 +19965,8 @@ c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
OMP_TARGET_CLAUSES (stmt)
= c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
"#pragma omp target");
+ c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
+
pc = &OMP_TARGET_CLAUSES (stmt);
keep_next_level ();
block = c_begin_compound_stmt (true);
@@ -19930,6 +19991,7 @@ check_clauses:
case GOMP_MAP_ALLOC:
case GOMP_MAP_FIRSTPRIVATE_POINTER:
case GOMP_MAP_ALWAYS_POINTER:
+ case GOMP_MAP_ATTACH_DETACH:
break;
default:
error_at (OMP_CLAUSE_LOCATION (*pc),
@@ -21369,6 +21431,7 @@ c_finish_taskloop_clauses (tree clauses)
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
+ | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
@@ -21455,7 +21518,7 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
switch (p_kind)
{
case PRAGMA_OACC_ATOMIC:
- c_parser_omp_atomic (loc, parser);
+ c_parser_omp_atomic (loc, parser, true);
return;
case PRAGMA_OACC_CACHE:
strcpy (p_name, "#pragma acc");
@@ -21482,7 +21545,7 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
stmt = c_parser_oacc_wait (loc, parser, p_name);
break;
case PRAGMA_OMP_ATOMIC:
- c_parser_omp_atomic (loc, parser);
+ c_parser_omp_atomic (loc, parser, false);
return;
case PRAGMA_OMP_CRITICAL:
stmt = c_parser_omp_critical (loc, parser, if_p);
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index 287b1df..1f783db 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -675,6 +675,7 @@ extern location_t c_last_sizeof_loc;
extern struct c_switch *c_switch_stack;
+extern bool char_type_p (tree);
extern tree c_objc_common_truthvalue_conversion (location_t, tree);
extern tree require_complete_type (location_t, tree);
extern bool same_translation_unit_p (const_tree, const_tree);
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index dd3e309..df1dad4 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -1407,7 +1407,7 @@ free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
const struct tagged_tu_seen_cache *const tu1
= (const struct tagged_tu_seen_cache *) tu;
tu = tu1->next;
- free (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
+ XDELETE (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
}
tagged_tu_seen_base = tu_til;
}
@@ -3014,7 +3014,8 @@ build_function_call (location_t loc, tree function, tree params)
static void
inform_declaration (tree decl)
{
- if (decl && (TREE_CODE (decl) != FUNCTION_DECL || !DECL_IS_BUILTIN (decl)))
+ if (decl && (TREE_CODE (decl) != FUNCTION_DECL
+ || !DECL_IS_UNDECLARED_BUILTIN (decl)))
inform (DECL_SOURCE_LOCATION (decl), "declared here");
}
@@ -3719,7 +3720,7 @@ parser_build_unary_op (location_t loc, enum tree_code code, struct c_expr arg)
/* Returns true if TYPE is a character type, *not* including wchar_t. */
-static bool
+bool
char_type_p (tree type)
{
return (type == char_type_node
@@ -5490,6 +5491,82 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
return ret;
}
+/* EXPR is an expression, location LOC, whose result is discarded.
+ Warn if it is a call to a nodiscard function (or a COMPOUND_EXPR
+ whose right-hand operand is such a call, possibly recursively). */
+
+static void
+maybe_warn_nodiscard (location_t loc, tree expr)
+{
+ if (VOID_TYPE_P (TREE_TYPE (expr)))
+ return;
+ while (TREE_CODE (expr) == COMPOUND_EXPR)
+ {
+ expr = TREE_OPERAND (expr, 1);
+ if (EXPR_HAS_LOCATION (expr))
+ loc = EXPR_LOCATION (expr);
+ }
+ if (TREE_CODE (expr) != CALL_EXPR)
+ return;
+ tree fn = CALL_EXPR_FN (expr);
+ if (!fn)
+ return;
+ tree attr;
+ if (TREE_CODE (fn) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
+ && (attr = lookup_attribute ("nodiscard",
+ DECL_ATTRIBUTES (TREE_OPERAND (fn, 0)))))
+ {
+ fn = TREE_OPERAND (fn, 0);
+ tree args = TREE_VALUE (attr);
+ if (args)
+ args = TREE_VALUE (args);
+ auto_diagnostic_group d;
+ int warned;
+ if (args)
+ warned = warning_at (loc, OPT_Wunused_result,
+ "ignoring return value of %qD, declared with "
+ "attribute %<nodiscard%>: %E", fn, args);
+ else
+ warned = warning_at (loc, OPT_Wunused_result,
+ "ignoring return value of %qD, declared with "
+ "attribute %<nodiscard%>", fn);
+ if (warned)
+ inform (DECL_SOURCE_LOCATION (fn), "declared here");
+ }
+ else
+ {
+ tree rettype = TREE_TYPE (TREE_TYPE (TREE_TYPE (fn)));
+ attr = lookup_attribute ("nodiscard", TYPE_ATTRIBUTES (rettype));
+ if (!attr)
+ return;
+ tree args = TREE_VALUE (attr);
+ if (args)
+ args = TREE_VALUE (args);
+ auto_diagnostic_group d;
+ int warned;
+ if (args)
+ warned = warning_at (loc, OPT_Wunused_result,
+ "ignoring return value of type %qT, declared "
+ "with attribute %<nodiscard%>: %E",
+ rettype, args);
+ else
+ warned = warning_at (loc, OPT_Wunused_result,
+ "ignoring return value of type %qT, declared "
+ "with attribute %<nodiscard%>", rettype);
+ if (warned)
+ {
+ if (TREE_CODE (fn) == ADDR_EXPR)
+ {
+ fn = TREE_OPERAND (fn, 0);
+ if (TREE_CODE (fn) == FUNCTION_DECL)
+ inform (DECL_SOURCE_LOCATION (fn),
+ "in call to %qD, declared here", fn);
+ }
+ }
+ }
+}
+
/* Return a compound expression that performs two expressions and
returns the value of the second of them.
@@ -5561,6 +5638,8 @@ build_compound_expr (location_t loc, tree expr1, tree expr2)
else if (warn_unused_value)
warn_if_unused_value (expr1, loc);
+ maybe_warn_nodiscard (loc, expr1);
+
if (expr2 == error_mark_node)
return error_mark_node;
@@ -6500,7 +6579,7 @@ inform_for_arg (tree fundecl, location_t ploc, int parmnum,
tree expected_type, tree actual_type)
{
location_t loc;
- if (fundecl && !DECL_IS_BUILTIN (fundecl))
+ if (fundecl && !DECL_IS_UNDECLARED_BUILTIN (fundecl))
loc = get_fndecl_argument_location (fundecl, parmnum - 1);
else
loc = ploc;
@@ -6750,7 +6829,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
if (pedwarn (expr_loc, OPT_Wc___compat, "enum conversion when "
"passing argument %d of %qE is invalid in C++",
parmnum, rname))
- inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
+ inform ((fundecl && !DECL_IS_UNDECLARED_BUILTIN (fundecl))
? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
"expected %qT but argument is of type %qT",
type, rhstype);
@@ -7161,7 +7240,8 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
case ic_argpass:
/* Do not warn for built-in functions, for example memcpy, since we
control how they behave and they can be useful in this area. */
- if (TREE_CODE (rname) != FUNCTION_DECL || !DECL_IS_BUILTIN (rname))
+ if (TREE_CODE (rname) != FUNCTION_DECL
+ || !DECL_IS_UNDECLARED_BUILTIN (rname))
warning_at (location, OPT_Wscalar_storage_order,
"passing argument %d of %qE from incompatible "
"scalar storage order", parmnum, rname);
@@ -8314,13 +8394,13 @@ finish_init (void)
{
struct constructor_stack *q = constructor_stack;
constructor_stack = q->next;
- free (q);
+ XDELETE (q);
}
gcc_assert (!constructor_range_stack);
/* Pop back to the data of the outer initializer (if any). */
- free (spelling_base);
+ XDELETE (spelling_base);
constructor_decl = p->decl;
require_constant_value = p->require_constant_value;
@@ -8333,7 +8413,7 @@ finish_init (void)
spelling_size = p->spelling_size;
constructor_top_level = p->top_level;
initializer_stack = p->next;
- free (p);
+ XDELETE (p);
}
/* Call here when we see the initializer is surrounded by braces.
@@ -8864,7 +8944,7 @@ pop_init_level (location_t loc, int implicit,
RESTORE_SPELLING_DEPTH (constructor_depth);
constructor_stack = p->next;
- free (p);
+ XDELETE (p);
if (ret.value == NULL_TREE && constructor_stack == 0)
ret.value = error_mark_node;
@@ -11072,6 +11152,9 @@ c_finish_bc_stmt (location_t loc, tree label, bool is_break)
static void
emit_side_effect_warnings (location_t loc, tree expr)
{
+ maybe_warn_nodiscard (loc, expr);
+ if (!warn_unused_value)
+ return;
if (expr == error_mark_node)
;
else if (!TREE_SIDE_EFFECTS (expr))
@@ -11127,7 +11210,7 @@ c_process_expr_stmt (location_t loc, tree expr)
Warnings for statement expressions will be emitted later, once we figure
out which is the result. */
if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
- && warn_unused_value)
+ && (warn_unused_value || warn_unused_result))
emit_side_effect_warnings (EXPR_LOC_OR_LOC (expr, loc), expr);
exprv = expr;
@@ -11221,7 +11304,7 @@ c_finish_stmt_expr (location_t loc, tree body)
/* If we're supposed to generate side effects warnings, process
all of the statements except the last. */
- if (warn_unused_value)
+ if (warn_unused_value || warn_unused_result)
{
for (tree_stmt_iterator i = tsi_start (last);
tsi_stmt (i) != tsi_stmt (l); tsi_next (&i))
@@ -13501,11 +13584,7 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort)
if (ort != C_ORT_OMP && ort != C_ORT_ACC)
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_POINTER);
else if (TREE_CODE (t) == COMPONENT_REF)
- {
- gomp_map_kind k = (ort == C_ORT_ACC) ? GOMP_MAP_ATTACH_DETACH
- : GOMP_MAP_ALWAYS_POINTER;
- OMP_CLAUSE_SET_MAP_KIND (c2, k);
- }
+ OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH);
else
OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER);
if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER
@@ -13795,6 +13874,7 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
/* 1 if normal/task reduction has been seen, -1 if inscan reduction
has been seen, -2 if mixed inscan/normal reduction diagnosed. */
int reduction_seen = 0;
+ bool allocate_seen = false;
bitmap_obstack_initialize (NULL);
bitmap_initialize (&generic_head, &bitmap_default_obstack);
@@ -14344,6 +14424,29 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
bitmap_set_bit (&oacc_reduction_head, DECL_UID (t));
break;
+ case OMP_CLAUSE_ALLOCATE:
+ t = OMP_CLAUSE_DECL (c);
+ if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qE is not a variable in %<allocate%> clause", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&aligned_head, DECL_UID (t)))
+ {
+ warning_at (OMP_CLAUSE_LOCATION (c), 0,
+ "%qE appears more than once in %<allocate%> clauses",
+ t);
+ remove = true;
+ }
+ else
+ {
+ bitmap_set_bit (&aligned_head, DECL_UID (t));
+ if (!OMP_CLAUSE_ALLOCATE_COMBINED (c))
+ allocate_seen = true;
+ }
+ break;
+
case OMP_CLAUSE_DEPEND:
t = OMP_CLAUSE_DECL (c);
if (t == NULL_TREE)
@@ -14604,7 +14707,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
break;
if (VAR_P (t) || TREE_CODE (t) == PARM_DECL)
{
- if (bitmap_bit_p (&map_field_head, DECL_UID (t)))
+ if (bitmap_bit_p (&map_field_head, DECL_UID (t))
+ || (ort == C_ORT_OMP
+ && bitmap_bit_p (&map_head, DECL_UID (t))))
break;
}
}
@@ -14673,7 +14778,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
else
bitmap_set_bit (&generic_head, DECL_UID (t));
}
- else if (bitmap_bit_p (&map_head, DECL_UID (t)))
+ else if (bitmap_bit_p (&map_head, DECL_UID (t))
+ && (ort != C_ORT_OMP
+ || !bitmap_bit_p (&map_field_head, DECL_UID (t))))
{
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP)
error_at (OMP_CLAUSE_LOCATION (c),
@@ -14687,7 +14794,13 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
}
else if (bitmap_bit_p (&generic_head, DECL_UID (t))
- || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
+ && ort == C_ORT_ACC)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD appears more than once in data clauses", t);
+ remove = true;
+ }
+ else if (bitmap_bit_p (&firstprivate_head, DECL_UID (t)))
{
if (ort == C_ORT_ACC)
error_at (OMP_CLAUSE_LOCATION (c),
@@ -15041,10 +15154,40 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
reduction_seen = -2;
}
- if (linear_variable_step_check || reduction_seen == -2)
+ if (linear_variable_step_check || reduction_seen == -2 || allocate_seen)
for (pc = &clauses, c = clauses; c ; c = *pc)
{
bool remove = false;
+ if (allocate_seen)
+ switch (OMP_CLAUSE_CODE (c))
+ {
+ case OMP_CLAUSE_REDUCTION:
+ case OMP_CLAUSE_IN_REDUCTION:
+ case OMP_CLAUSE_TASK_REDUCTION:
+ if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF)
+ {
+ t = TREE_OPERAND (OMP_CLAUSE_DECL (c), 0);
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ t = TREE_OPERAND (t, 0);
+ if (TREE_CODE (t) == ADDR_EXPR
+ || TREE_CODE (t) == INDIRECT_REF)
+ t = TREE_OPERAND (t, 0);
+ if (DECL_P (t))
+ bitmap_clear_bit (&aligned_head, DECL_UID (t));
+ break;
+ }
+ /* FALLTHRU */
+ case OMP_CLAUSE_PRIVATE:
+ case OMP_CLAUSE_FIRSTPRIVATE:
+ case OMP_CLAUSE_LASTPRIVATE:
+ case OMP_CLAUSE_LINEAR:
+ if (DECL_P (OMP_CLAUSE_DECL (c)))
+ bitmap_clear_bit (&aligned_head,
+ DECL_UID (OMP_CLAUSE_DECL (c)));
+ break;
+ default:
+ break;
+ }
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR
&& OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c)
&& !bitmap_bit_p (&map_head,
@@ -15065,6 +15208,25 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
pc = &OMP_CLAUSE_CHAIN (c);
}
+ if (allocate_seen)
+ for (pc = &clauses, c = clauses; c ; c = *pc)
+ {
+ bool remove = false;
+ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE
+ && !OMP_CLAUSE_ALLOCATE_COMBINED (c)
+ && bitmap_bit_p (&aligned_head, DECL_UID (OMP_CLAUSE_DECL (c))))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%qD specified in %<allocate%> clause but not in "
+ "an explicit privatization clause", OMP_CLAUSE_DECL (c));
+ remove = true;
+ }
+ if (remove)
+ *pc = OMP_CLAUSE_CHAIN (c);
+ else
+ pc = &OMP_CLAUSE_CHAIN (c);
+ }
+
if (nogroup_seen && reduction_seen)
{
error_at (OMP_CLAUSE_LOCATION (*nogroup_seen),