summaryrefslogtreecommitdiff
path: root/gcc/cp/decl2.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/decl2.c')
-rw-r--r--gcc/cp/decl2.c185
1 files changed, 111 insertions, 74 deletions
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 4ac9445ecc9..a094ff3b546 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -101,7 +101,6 @@ static GTY(()) vec<tree, va_gc> *no_linkage_decls;
/* Nonzero if we're done parsing and into end-of-file activities. */
int at_eof;
-
/* Return a member function type (a METHOD_TYPE), given FNTYPE (a
@@ -956,26 +955,6 @@ grokfield (const cp_declarator *declarator,
/* C++11 NSDMI, keep going. */;
else if (!VAR_P (value))
gcc_unreachable ();
- else if (!processing_template_decl)
- {
- if (TREE_CODE (init) == CONSTRUCTOR)
- init = digest_init (TREE_TYPE (value), init, tf_warning_or_error);
- init = maybe_constant_init (init);
-
- if (init != error_mark_node && !TREE_CONSTANT (init))
- {
- /* We can allow references to things that are effectively
- static, since references are initialized with the
- address. */
- if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
- || (TREE_STATIC (init) == 0
- && (!DECL_P (init) || DECL_EXTERNAL (init) == 0)))
- {
- error ("field initializer is not constant");
- init = error_mark_node;
- }
- }
- }
}
if (processing_template_decl && VAR_OR_FUNCTION_DECL_P (value))
@@ -1135,6 +1114,11 @@ is_late_template_attribute (tree attr, tree decl)
if (is_attribute_p ("unused", name))
return false;
+ /* #pragma omp declare simd attribute needs to be always deferred. */
+ if (flag_openmp
+ && is_attribute_p ("omp declare simd", name))
+ return true;
+
/* If any of the arguments are dependent expressions, we can't evaluate
the attribute until instantiation time. */
for (arg = args; arg; arg = TREE_CHAIN (arg))
@@ -1218,10 +1202,12 @@ splice_template_attributes (tree *attr_p, tree decl)
static void
save_template_attributes (tree *attr_p, tree *decl_p)
{
- tree late_attrs = splice_template_attributes (attr_p, *decl_p);
tree *q;
- tree old_attrs = NULL_TREE;
+ if (attr_p && *attr_p == error_mark_node)
+ return;
+
+ tree late_attrs = splice_template_attributes (attr_p, *decl_p);
if (!late_attrs)
return;
@@ -1230,7 +1216,7 @@ save_template_attributes (tree *attr_p, tree *decl_p)
else
q = &TYPE_ATTRIBUTES (*decl_p);
- old_attrs = *q;
+ tree old_attrs = *q;
/* Merge the late attributes at the beginning with the attribute
list. */
@@ -1318,6 +1304,9 @@ cp_reconstruct_complex_type (tree type, tree bottom)
static void
cp_check_const_attributes (tree attributes)
{
+ if (attributes == error_mark_node)
+ return;
+
tree attr;
for (attr = attributes; attr; attr = TREE_CHAIN (attr))
{
@@ -1331,6 +1320,34 @@ cp_check_const_attributes (tree attributes)
}
}
+/* Return true if TYPE is an OpenMP mappable type. */
+bool
+cp_omp_mappable_type (tree type)
+{
+ /* Mappable type has to be complete. */
+ if (type == error_mark_node || !COMPLETE_TYPE_P (type))
+ return false;
+ /* Arrays have mappable type if the elements have mappable type. */
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+ /* A mappable type cannot contain virtual members. */
+ if (CLASS_TYPE_P (type) && CLASSTYPE_VTABLES (type))
+ return false;
+ /* All data members must be non-static. */
+ if (CLASS_TYPE_P (type))
+ {
+ tree field;
+ for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == VAR_DECL)
+ return false;
+ /* All fields must have mappable types. */
+ else if (TREE_CODE (field) == FIELD_DECL
+ && !cp_omp_mappable_type (TREE_TYPE (field)))
+ return false;
+ }
+ return true;
+}
+
/* Like decl_attributes, but handle C++ complexity. */
void
@@ -1340,6 +1357,30 @@ cplus_decl_attributes (tree *decl, tree attributes, int flags)
|| *decl == error_mark_node)
return;
+ /* Add implicit "omp declare target" attribute if requested. */
+ if (scope_chain->omp_declare_target_attribute
+ && ((TREE_CODE (*decl) == VAR_DECL && TREE_STATIC (*decl))
+ || TREE_CODE (*decl) == FUNCTION_DECL))
+ {
+ if (TREE_CODE (*decl) == VAR_DECL
+ && DECL_CLASS_SCOPE_P (*decl))
+ error ("%q+D static data member inside of declare target directive",
+ *decl);
+ else if (TREE_CODE (*decl) == VAR_DECL
+ && (DECL_FUNCTION_SCOPE_P (*decl)
+ || (current_function_decl && !DECL_EXTERNAL (*decl))))
+ error ("%q+D in block scope inside of declare target directive",
+ *decl);
+ else if (!processing_template_decl
+ && TREE_CODE (*decl) == VAR_DECL
+ && !cp_omp_mappable_type (TREE_TYPE (*decl)))
+ error ("%q+D in declare target directive does not have mappable type",
+ *decl);
+ else
+ attributes = tree_cons (get_identifier ("omp declare target"),
+ NULL_TREE, attributes);
+ }
+
if (processing_template_decl)
{
if (check_for_bare_parameter_packs (attributes))
@@ -1706,7 +1747,7 @@ maybe_make_one_only (tree decl)
struct varpool_node *node = varpool_node_for_decl (decl);
DECL_COMDAT (decl) = 1;
/* Mark it needed so we don't forget to emit it. */
- node->symbol.forced_by_abi = true;
+ node->forced_by_abi = true;
TREE_USED (decl) = 1;
}
}
@@ -1804,7 +1845,7 @@ import_export_class (tree ctype)
static bool
var_finalized_p (tree var)
{
- return varpool_node_for_decl (var)->symbol.definition;
+ return varpool_node_for_decl (var)->definition;
}
/* DECL is a VAR_DECL or FUNCTION_DECL which, for whatever reason,
@@ -1821,14 +1862,14 @@ mark_needed (tree decl)
functions can be marked reachable, just use the external
definition. */
struct cgraph_node *node = cgraph_get_create_node (decl);
- node->symbol.forced_by_abi = true;
+ node->forced_by_abi = true;
}
else if (TREE_CODE (decl) == VAR_DECL)
{
struct varpool_node *node = varpool_node_for_decl (decl);
/* C++ frontend use mark_decl_references to force COMDAT variables
to be output that might appear dead otherwise. */
- node->symbol.forced_by_abi = true;
+ node->forced_by_abi = true;
}
}
@@ -1938,7 +1979,7 @@ maybe_emit_vtables (tree ctype)
{
current = varpool_node_for_decl (vtbl);
if (last)
- symtab_add_to_same_comdat_group ((symtab_node) current, (symtab_node) last);
+ symtab_add_to_same_comdat_group (current, last);
last = current;
}
}
@@ -2681,26 +2722,9 @@ import_export_decl (tree decl)
tree
build_cleanup (tree decl)
{
- tree temp;
- tree type = TREE_TYPE (decl);
-
- /* This function should only be called for declarations that really
- require cleanups. */
- gcc_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type));
-
- /* Treat all objects with destructors as used; the destructor may do
- something substantive. */
- mark_used (decl);
-
- if (TREE_CODE (type) == ARRAY_TYPE)
- temp = decl;
- else
- temp = build_address (decl);
- temp = build_delete (TREE_TYPE (temp), temp,
- sfk_complete_destructor,
- LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0,
- tf_warning_or_error);
- return temp;
+ tree clean = cxx_maybe_build_cleanup (decl, tf_warning_or_error);
+ gcc_assert (clean != NULL_TREE);
+ return clean;
}
/* Returns the initialization guard variable for the variable DECL,
@@ -3703,7 +3727,7 @@ collect_candidates_for_java_method_aliases (void)
FOR_EACH_FUNCTION (node)
{
- tree fndecl = node->symbol.decl;
+ tree fndecl = node->decl;
if (DECL_CLASS_SCOPE_P (fndecl)
&& TYPE_FOR_JAVA (DECL_CONTEXT (fndecl))
@@ -3736,7 +3760,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
FOR_EACH_FUNCTION (node)
{
- tree fndecl = node->symbol.decl;
+ tree fndecl = node->decl;
if (TREE_ASM_WRITTEN (fndecl)
&& pointer_set_contains (candidates, fndecl))
@@ -3765,7 +3789,7 @@ build_java_method_aliases (struct pointer_set_t *candidates)
/* Return C++ property of T, based on given operation OP. */
static int
-cpp_check (tree t, cpp_operation op)
+cpp_check (const_tree t, cpp_operation op)
{
switch (op)
{
@@ -3779,6 +3803,8 @@ cpp_check (tree t, cpp_operation op)
return DECL_COPY_CONSTRUCTOR_P (t);
case IS_TEMPLATE:
return TREE_CODE (t) == TEMPLATE_DECL;
+ case IS_TRIVIAL:
+ return trivial_type_p (t);
default:
return 0;
}
@@ -3917,7 +3943,7 @@ collect_all_refs (const char *source_file)
static bool
clear_decl_external (struct cgraph_node *node, void * /*data*/)
{
- DECL_EXTERNAL (node->symbol.decl) = 0;
+ DECL_EXTERNAL (node->decl) = 0;
return false;
}
@@ -3980,6 +4006,22 @@ handle_tls_init (void)
expand_or_defer_fn (finish_function (0));
}
+/* The entire file is now complete. If requested, dump everything
+ to a file. */
+
+static void
+dump_tu (void)
+{
+ int flags;
+ FILE *stream = dump_begin (TDI_tu, &flags);
+
+ if (stream)
+ {
+ dump_node (global_namespace, flags & ~TDF_SLIM, stream);
+ dump_end (TDI_tu, stream);
+ }
+}
+
/* This routine is called at the end of compilation.
Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction
@@ -4010,6 +4052,7 @@ cp_write_global_declarations (void)
if (pch_file)
{
c_common_write_pch ();
+ dump_tu ();
return;
}
@@ -4218,7 +4261,7 @@ cp_write_global_declarations (void)
struct cgraph_node *node, *next;
node = cgraph_get_node (decl);
- if (node->symbol.cpp_implicit_alias)
+ if (node->cpp_implicit_alias)
node = cgraph_alias_target (node);
cgraph_for_node_and_aliases (node, clear_decl_external,
@@ -4226,10 +4269,10 @@ cp_write_global_declarations (void)
/* If we mark !DECL_EXTERNAL one of the symbols in some comdat
group, we need to mark all symbols in the same comdat group
that way. */
- if (node->symbol.same_comdat_group)
- for (next = cgraph (node->symbol.same_comdat_group);
+ if (node->same_comdat_group)
+ for (next = cgraph (node->same_comdat_group);
next != node;
- next = cgraph (next->symbol.same_comdat_group))
+ next = cgraph (next->same_comdat_group))
cgraph_for_node_and_aliases (next, clear_decl_external,
NULL, true);
}
@@ -4241,7 +4284,7 @@ cp_write_global_declarations (void)
if (!DECL_EXTERNAL (decl)
&& decl_needed_p (decl)
&& !TREE_ASM_WRITTEN (decl)
- && !cgraph_get_node (decl)->symbol.definition)
+ && !cgraph_get_node (decl)->definition)
{
/* We will output the function; no longer consider it in this
loop. */
@@ -4396,16 +4439,7 @@ cp_write_global_declarations (void)
/* The entire file is now complete. If requested, dump everything
to a file. */
- {
- int flags;
- FILE *stream = dump_begin (TDI_tu, &flags);
-
- if (stream)
- {
- dump_node (global_namespace, flags & ~TDF_SLIM, stream);
- dump_end (TDI_tu, stream);
- }
- }
+ dump_tu ();
if (flag_detailed_statistics)
{
@@ -4618,13 +4652,16 @@ mark_used (tree decl, tsubst_flags_t complain)
or a constexpr function, we need it right now because a reference to
such a data member or a call to such function is not value-dependent.
For a function that uses auto in the return type, we need to instantiate
- it to find out its type. */
- if ((decl_maybe_constant_var_p (decl)
- || (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_DECLARED_CONSTEXPR_P (decl))
- || undeduced_auto_decl (decl))
- && DECL_LANG_SPECIFIC (decl)
+ it to find out its type. For OpenMP user defined reductions, we need
+ them instantiated for reduction clauses which inline them by hand
+ directly. */
+ if (DECL_LANG_SPECIFIC (decl)
&& DECL_TEMPLATE_INFO (decl)
+ && (decl_maybe_constant_var_p (decl)
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && (DECL_DECLARED_CONSTEXPR_P (decl)
+ || DECL_OMP_DECLARE_REDUCTION_P (decl)))
+ || undeduced_auto_decl (decl))
&& !uses_template_parms (DECL_TI_ARGS (decl)))
{
/* Instantiating a function will result in garbage collection. We