diff options
Diffstat (limited to 'gcc/cp/decl2.c')
-rw-r--r-- | gcc/cp/decl2.c | 185 |
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 |