aboutsummaryrefslogtreecommitdiff
path: root/gcc/c
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2021-01-03 21:40:04 +0100
committerThomas Koenig <tkoenig@gcc.gnu.org>2021-01-03 21:40:04 +0100
commitafae4a55ccaa0de95ea11e5f634084db6ab2f444 (patch)
treed632cc867d10410ba9fb750523be790b86846ac4 /gcc/c
parent9d9a82ec8478ff52c7a9d61f58cd2a7b6295b5f9 (diff)
parentd2eb616a0f7bea78164912aa438c29fe1ef5774a (diff)
downloadgcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.zip
gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.gz
gcc-afae4a55ccaa0de95ea11e5f634084db6ab2f444.tar.bz2
Merge branch 'master' into devel/coarray_native
Diffstat (limited to 'gcc/c')
-rw-r--r--gcc/c/ChangeLog200
-rw-r--r--gcc/c/Make-lang.in3
-rw-r--r--gcc/c/c-aux-info.c1
-rw-r--r--gcc/c/c-decl.c52
-rw-r--r--gcc/c/c-parser.c646
-rw-r--r--gcc/c/c-typeck.c235
-rw-r--r--gcc/c/gimple-parser.c2
7 files changed, 817 insertions, 322 deletions
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 8c6893b..b5cf1a7 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,203 @@
+2020-12-16 Martin Uecker <muecker@gwdg.de>
+
+ PR c/98047
+ * c-typeck.c (build_modify_expr): Drop qualifiers.
+
+2020-12-16 Martin Uecker <muecker@gwdg.de>
+
+ PR c/98260
+ * c-parser.c (c_parser_expression): Look into
+ nop expression when marking expressions as read.
+
+2020-12-14 Martin Liska <mliska@suse.cz>
+
+ PR sanitizer/98204
+ * c-typeck.c (pointer_diff): Do not emit a top-level
+ sanitization.
+ (build_binary_op): Likewise.
+
+2020-12-09 Tobias Burnus <tobias@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_allocate): New.
+ (c_parser_omp_construct): Call it.
+
+2020-12-09 Richard Biener <rguenther@suse.de>
+
+ PR c/98200
+ * gimple-parser.c (c_parser_gimple_postfix_expression): Return
+ early on error.
+
+2020-12-07 Martin Uecker <muecker@gwdg.de>
+
+ PR c/97981
+ * c-typeck.c (convert_lvalue_to_rvalue): Move the code
+ that drops qualifiers to the end of the function.
+
+2020-11-26 Martin Uecker <muecker@gwdg.de>
+
+ PR c/65455
+ PR c/92935
+ * c-parser.c (c_parser_declaration_or_fndef): Remove
+ redundant code to drop qualifiers of _Atomic types for __auto_type.
+ (c_parser_typeof_specifier): Do not drop qualifiers of _Atomic
+ types for __typeof__.
+
+2020-11-24 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97958
+ * c-parser.c (c_parser_binary_expression): For omp atomic binary
+ expressions, use make_node instead of build2 to avoid checking build2
+ performs.
+
+2020-11-23 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/95630
+ * c-typeck.c (build_binary_op): Use pedwarn_c99 with OPT_Wpedantic
+ for comparisons of complete and incomplete pointers.
+
+2020-11-21 Aaron Sawdey <acsawdey@linux.ibm.com>
+
+ * c-aux-info.c (gen_type): Support opaque types.
+
+2020-11-20 Martin Sebor <msebor@redhat.com>
+
+ PR middle-end/97879
+ * c-decl.c (start_function): Set ATTR_FLAG_INTERNAL in flags.
+
+2020-11-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR other/97911
+ * Make-lang.in (c.serial): Change from goal to a variable.
+ (.PHONY): Drop c.serial.
+
+2020-11-20 Martin Uecker <muecker@gwdg.de>
+
+ * c-typeck.c (convert_lvalue_to_rvalue): Drop qualifiers.
+
+2020-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c/97860
+ * c-decl.c (get_parm_array_spec): Bail out of nelts is
+ error_operand_p.
+
+2020-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * Make-lang.in (c.serial): New goal.
+ (.PHONY): Add c.serial c.prev.
+ (cc1$(exeext)): Call LINK_PROGRESS.
+
+2020-11-13 Vladimir N. Makarov <vmakarov@redhat.com>
+
+ * c-parser.c (c_parser_asm_statement): Parse outputs for asm
+ goto too.
+ * c-typeck.c (build_asm_expr): Remove an assert checking output
+ absence for asm goto.
+
+2020-11-13 Jakub Jelinek <jakub@redhat.com>
+
+ * c-typeck.c (c_finish_omp_clauses): Don't clear
+ OMP_CLAUSE_REDUCTION_INSCAN unless reduction_seen == -2.
+
+2020-11-13 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR objc/77404
+ * c-parser.c (c_parser_objc_class_definition): Pass the
+ location of the class name to the interface declaration.
+
+2020-11-10 Strager Neds <strager.nds@gmail.com>
+
+ * c-decl.c (merge_decls): Use new overload of
+ set_decl_section_name.
+
+2020-11-10 Chung-Lin Tang <cltang@codesourcery.com>
+
+ * c-parser.c (c_parser_omp_target_data): Add use of
+ new c_omp_adjust_map_clauses function. Add GOMP_MAP_ATTACH_DETACH as
+ handled map clause kind.
+ (c_parser_omp_target_enter_data): Likewise.
+ (c_parser_omp_target_exit_data): Likewise.
+ (c_parser_omp_target): Likewise.
+ * c-typeck.c (handle_omp_array_sections): Adjust COMPONENT_REF case to
+ use GOMP_MAP_ATTACH_DETACH map kind for C_ORT_OMP region type.
+ (c_finish_omp_clauses): Adjust bitmap checks to allow struct decl and
+ same struct field access to co-exist on OpenMP construct.
+
+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
diff --git a/gcc/c/Make-lang.in b/gcc/c/Make-lang.in
index 7efc7c2..4b2e616 100644
--- a/gcc/c/Make-lang.in
+++ b/gcc/c/Make-lang.in
@@ -37,6 +37,7 @@
#
# Define the names for selecting c in LANGUAGES.
c: cc1$(exeext)
+c.serial = cc1$(exeext)
# Tell GNU make to ignore these if they exist.
.PHONY: c gcc
@@ -82,8 +83,10 @@ cc1-checksum.c : build/genchecksum$(build_exeext) checksum-options \
fi
cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
+ @$(call LINK_PROGRESS,$(INDEX.c),start)
+$(LLINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ @$(call LINK_PROGRESS,$(INDEX.c),end)
cc1.fda: ../stage1-gcc/cc1$(exeext) ../prev-gcc/$(PERF_DATA)
$(CREATE_GCOV) -binary ../stage1-gcc/cc1$(exeext) -gcov cc1.fda -profile ../prev-gcc/$(PERF_DATA) -gcov_version 1
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
index ffc8099..bdeef52 100644
--- a/gcc/c/c-aux-info.c
+++ b/gcc/c/c-aux-info.c
@@ -409,6 +409,7 @@ gen_type (const char *ret_val, tree t, formals_style style)
data_type = concat ("unsigned ", data_type, NULL);
break;
+ case OPAQUE_TYPE:
case REAL_TYPE:
data_type = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)));
break;
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 1673b95..27f7722 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;
@@ -2884,7 +2884,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
|| TREE_PUBLIC (olddecl)
|| TREE_STATIC (olddecl))
&& DECL_SECTION_NAME (newdecl) != NULL)
- set_decl_section_name (olddecl, DECL_SECTION_NAME (newdecl));
+ set_decl_section_name (olddecl, newdecl);
/* This isn't quite correct for something like
int __thread x attribute ((tls_model ("local-exec")));
@@ -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 }
};
@@ -5748,6 +5775,8 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
type = TREE_TYPE (type))
{
tree nelts = array_type_nelts (type);
+ if (error_operand_p (nelts))
+ return attrs;
if (TREE_CODE (nelts) != INTEGER_CST)
{
/* Each variable VLA bound is represented by the dollar
@@ -9569,7 +9598,8 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
current_function_decl = pushdecl (decl1);
if (tree access = build_attr_access_from_parms (parms, false))
- decl_attributes (&current_function_decl, access, 0, old_decl);
+ decl_attributes (&current_function_decl, access, ATTR_FLAG_INTERNAL,
+ old_decl);
push_scope ();
declare_parm_level ();
@@ -9630,7 +9660,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. */
@@ -10471,7 +10503,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. */
@@ -12105,12 +12137,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 b6a7ef4..b9fdc90 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);
@@ -2224,10 +2224,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
" initializer");
init = convert_lvalue_to_rvalue (init_loc, init, true, true);
tree init_type = TREE_TYPE (init.value);
- /* As with typeof, remove all qualifiers from atomic types. */
- if (init_type != error_mark_node && TYPE_ATOMIC (init_type))
- init_type
- = c_build_qualified_type (init_type, TYPE_UNQUALIFIED);
bool vm_type = variably_modified_type_p (init_type,
NULL_TREE);
if (vm_type)
@@ -3743,11 +3739,6 @@ c_parser_typeof_specifier (c_parser *parser)
if (was_vm)
ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
pop_maybe_used (was_vm);
- /* For use in macros such as those in <stdatomic.h>, remove all
- qualifiers from atomic types. (const can be an issue for more macros
- using typeof than just the <stdatomic.h> ones.) */
- if (ret.spec != error_mark_node && TYPE_ATOMIC (ret.spec))
- ret.spec = c_build_qualified_type (ret.spec, TYPE_UNQUALIFIED);
}
parens.skip_until_found_close (parser);
return ret;
@@ -4950,7 +4941,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 +4952,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 +4968,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 +4993,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 +5514,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 +5525,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after,
block-item-list block-item
block-item:
+ label
nested-declaration
statement
@@ -5724,7 +5666,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 +5677,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 +5684,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 +5791,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 +5807,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 +5851,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 +5902,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 +5916,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);
}
}
@@ -7225,10 +7135,7 @@ c_parser_asm_statement (c_parser *parser)
switch (section)
{
case 0:
- /* For asm goto, we don't allow output operands, but reserve
- the slot for a future extension that does allow them. */
- if (!is_goto)
- outputs = c_parser_asm_operands (parser);
+ outputs = c_parser_asm_operands (parser);
break;
case 1:
inputs = c_parser_asm_operands (parser);
@@ -7949,9 +7856,13 @@ c_parser_binary_expression (c_parser *parser, struct c_expr *after,
&& stack[1].expr.value != error_mark_node \
&& (c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
|| c_tree_equal (stack[1].expr.value, omp_atomic_lhs))) \
- stack[0].expr.value \
- = build2 (stack[1].op, TREE_TYPE (stack[0].expr.value), \
- stack[0].expr.value, stack[1].expr.value); \
+ { \
+ tree t = make_node (stack[1].op); \
+ TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
+ TREE_OPERAND (t, 0) = stack[0].expr.value; \
+ TREE_OPERAND (t, 1) = stack[1].expr.value; \
+ stack[0].expr.value = t; \
+ } \
else \
stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
stack[sp].op, \
@@ -10704,8 +10615,14 @@ c_parser_expression (c_parser *parser)
c_parser_consume_token (parser);
expr_loc = c_parser_peek_token (parser)->location;
lhsval = expr.value;
- while (TREE_CODE (lhsval) == COMPOUND_EXPR)
- lhsval = TREE_OPERAND (lhsval, 1);
+ while (TREE_CODE (lhsval) == COMPOUND_EXPR
+ || TREE_CODE (lhsval) == NOP_EXPR)
+ {
+ if (TREE_CODE (lhsval) == COMPOUND_EXPR)
+ lhsval = TREE_OPERAND (lhsval, 1);
+ else
+ lhsval = TREE_OPERAND (lhsval, 0);
+ }
if (DECL_P (lhsval) || handled_component_p (lhsval))
mark_exp_read (lhsval);
next = c_parser_expr_no_commas (parser, NULL);
@@ -10882,6 +10799,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes)
return;
}
id1 = c_parser_peek_token (parser)->value;
+ location_t loc1 = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
{
@@ -10941,7 +10859,7 @@ c_parser_objc_class_definition (c_parser *parser, tree attributes)
tree proto = NULL_TREE;
if (c_parser_next_token_is (parser, CPP_LESS))
proto = c_parser_objc_protocol_refs (parser);
- objc_start_class_interface (id1, superclass, proto, attributes);
+ objc_start_class_interface (id1, loc1, superclass, proto, attributes);
}
else
objc_start_class_implementation (id1, superclass);
@@ -12008,158 +11926,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;
}
@@ -12653,6 +12609,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))
@@ -15162,6 +15120,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 )
@@ -16404,6 +16418,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";
@@ -17238,6 +17256,55 @@ c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
return stmt;
}
+/* OpenMP 5.0:
+ # pragma omp allocate (list) [allocator(allocator)] */
+
+static void
+c_parser_omp_allocate (location_t loc, c_parser *parser)
+{
+ tree allocator = NULL_TREE;
+ tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE);
+ if (c_parser_next_token_is (parser, CPP_NAME))
+ {
+ matching_parens parens;
+ const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ if (strcmp ("allocator", p) != 0)
+ error_at (c_parser_peek_token (parser)->location,
+ "expected %<allocator%>");
+ else if (parens.require_open (parser))
+ {
+ 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 (expr_loc, "%<allocator%> clause allocator expression "
+ "has type %qT rather than "
+ "%<omp_allocator_handle_t%>",
+ TREE_TYPE (allocator));
+ allocator = NULL_TREE;
+ }
+ parens.skip_until_found_close (parser);
+ }
+ }
+ c_parser_skip_to_pragma_eol (parser);
+
+ if (allocator)
+ for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
+ OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
+
+ sorry_at (loc, "%<#pragma omp allocate%> not yet supported");
+}
+
/* OpenMP 2.5:
# pragma omp atomic new-line
expression-stmt
@@ -17292,7 +17359,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;
@@ -17331,6 +17398,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"))
@@ -17358,7 +17431,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;
@@ -17380,7 +17458,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
@@ -17436,6 +17516,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)
{
@@ -18584,6 +18665,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
@@ -18875,6 +18957,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
@@ -18929,6 +19012,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
@@ -19070,6 +19154,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
@@ -19104,6 +19189,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
@@ -19174,7 +19260,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)
@@ -19275,6 +19362,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
@@ -19364,6 +19452,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
@@ -19470,6 +19559,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;)
{
@@ -19487,6 +19577,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;
@@ -19610,6 +19701,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;)
{
@@ -19623,6 +19715,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;
@@ -19694,7 +19787,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;)
{
@@ -19709,6 +19802,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;
@@ -19751,6 +19845,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))
@@ -19918,6 +20013,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);
@@ -19942,6 +20039,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),
@@ -21381,6 +21479,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))
@@ -21467,7 +21566,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");
@@ -21493,8 +21592,11 @@ c_parser_omp_construct (c_parser *parser, bool *if_p)
strcpy (p_name, "#pragma wait");
stmt = c_parser_oacc_wait (loc, parser, p_name);
break;
+ case PRAGMA_OMP_ALLOCATE:
+ c_parser_omp_allocate (loc, parser);
+ return;
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-typeck.c b/gcc/c/c-typeck.c
index 459090e..f68cb01 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;
}
@@ -2116,6 +2116,9 @@ convert_lvalue_to_rvalue (location_t loc, struct c_expr exp,
exp.value = build4 (TARGET_EXPR, nonatomic_type, tmp, func_call,
NULL_TREE, NULL_TREE);
}
+ if (convert_p && !error_operand_p (exp.value)
+ && (TREE_CODE (TREE_TYPE (exp.value)) != ARRAY_TYPE))
+ exp.value = convert (build_qualified_type (TREE_TYPE (exp.value), TYPE_UNQUALIFIED), exp.value);
return exp;
}
@@ -3014,7 +3017,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");
}
@@ -3945,10 +3949,9 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr)
pedwarn (loc, OPT_Wpointer_arith,
"pointer to a function used in subtraction");
- if (sanitize_flags_p (SANITIZE_POINTER_SUBTRACT))
+ if (current_function_decl != NULL_TREE
+ && sanitize_flags_p (SANITIZE_POINTER_SUBTRACT))
{
- gcc_assert (current_function_decl != NULL_TREE);
-
op0 = save_expr (op0);
op1 = save_expr (op1);
@@ -5490,6 +5493,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 +5640,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;
@@ -6194,16 +6275,9 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
"enum conversion in assignment is invalid in C++");
}
- /* If the lhs is atomic, remove that qualifier. */
- if (is_atomic_op)
- {
- lhstype = build_qualified_type (lhstype,
- (TYPE_QUALS (lhstype)
- & ~TYPE_QUAL_ATOMIC));
- olhstype = build_qualified_type (olhstype,
- (TYPE_QUALS (lhstype)
- & ~TYPE_QUAL_ATOMIC));
- }
+ /* Remove qualifiers. */
+ lhstype = build_qualified_type (lhstype, TYPE_UNQUALIFIED);
+ olhstype = build_qualified_type (olhstype, TYPE_UNQUALIFIED);
/* Convert new value to destination type. Fold it first, then
restore any excess precision information, for the sake of
@@ -6500,7 +6574,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 +6824,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 +7235,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 +8389,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 +8408,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 +8939,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;
@@ -10586,10 +10661,6 @@ build_asm_expr (location_t loc, tree string, tree outputs, tree inputs,
TREE_VALUE (tail) = input;
}
- /* ASMs with labels cannot have outputs. This should have been
- enforced by the parser. */
- gcc_assert (outputs == NULL || labels == NULL);
-
args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, labels);
/* asm statements without outputs, including simple ones, are treated
@@ -11072,6 +11143,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 +11201,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 +11295,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))
@@ -12184,8 +12258,8 @@ build_binary_op (location_t location, enum tree_code code,
result_type = common_pointer_type (type0, type1);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
- pedwarn (location, 0,
- "comparison of complete and incomplete pointers");
+ pedwarn_c99 (location, OPT_Wpedantic,
+ "comparison of complete and incomplete pointers");
else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
pedwarn (location, OPT_Wpedantic, "ISO C forbids "
"ordered comparisons of pointers to functions");
@@ -12242,6 +12316,7 @@ build_binary_op (location_t location, enum tree_code code,
}
if ((code0 == POINTER_TYPE || code1 == POINTER_TYPE)
+ && current_function_decl != NULL_TREE
&& sanitize_flags_p (SANITIZE_POINTER_COMPARE))
{
op0 = save_expr (op0);
@@ -13501,11 +13576,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 +13866,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 +14416,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 +14699,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 +14770,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 +14786,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 +15146,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,
@@ -15056,7 +15191,8 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
OMP_CLAUSE_LINEAR_STEP (c));
remove = true;
}
- else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && reduction_seen == -2)
OMP_CLAUSE_REDUCTION_INSCAN (c) = 0;
if (remove)
@@ -15065,6 +15201,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),
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index 5c0ed82..473cb90 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -1700,6 +1700,8 @@ c_parser_gimple_postfix_expression (gimple_parser &parser)
expr.set_error ();
break;
}
+ if (expr.value == error_mark_node)
+ return expr;
return c_parser_gimple_postfix_expression_after_primary
(parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
}