From a28542df4d069d9937070b5456a54d5e10bcfe56 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Fri, 25 Sep 2020 06:53:06 -0700 Subject: [PATCH] c++: DECL_BUILTIN_P for builtins We currently detect builtin decls via DECL_ARTIFICIAL && !DECL_HIDDEN_FUNCTION_P, which, besides being clunky, is a problem as hiddenness is a property of the symbol table -- not the decl being hidden. This adds DECL_BUILTIN_P, which just looks at the SOURCE_LOCATION -- we have a magic one for builtins. One of the consequential changes is to make function-scope omp udrs have function context (needed because otherwise duplicate-decls thinks the types don't match at the point we check). This is also morally better, because that's what they are -- nested functions, stop lying. (That's actually my plan for all DECL_LOCAL_DECL_P decls, as they are distinct decls to the namespace-scope decl they alias.) gcc/cp/ * cp-tree.h (DECL_BUILTIN_P): New. * decl.c (duplicate_decls): Use it. Do not treat omp-udr as a builtin. * name-lookup.c (anticipated_builtin): Use it. (set_decl_context_in_fn): Function-scope OMP UDRs have function context. (do_nonmember_using_decl): Use DECL_BUILTIN_P. * parser.c (cp_parser_omp_declare_reduction): Function-scope OMP UDRs have function context. Assert we never find a valid duplicate. * pt.c (tsubst_expr): Function-scope OMP UDRs have function context. libcc1/ * libcp1plugin.cc (supplement_binding): Use DECL_BULTIN_P. --- gcc/cp/cp-tree.h | 4 ++++ gcc/cp/decl.c | 24 ++++++++++++------------ gcc/cp/name-lookup.c | 15 +++++++++------ gcc/cp/parser.c | 6 ++++-- gcc/cp/pt.c | 11 +++-------- libcc1/libcp1plugin.cc | 2 +- 6 files changed, 33 insertions(+), 29 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3ae4874..bd78f00 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4040,6 +4040,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define FNDECL_USED_AUTO(NODE) \ TREE_LANG_FLAG_2 (FUNCTION_DECL_CHECK (NODE)) +/* True if NODE is a builtin decl. */ +#define DECL_BUILTIN_P(NODE) \ + (DECL_SOURCE_LOCATION(NODE) == BUILTINS_LOCATION) + /* Nonzero if NODE is a DECL which we know about but which has not been explicitly declared, such as a built-in function or a friend declared inside a class. In the latter case DECL_HIDDEN_FRIEND_P diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6019051..1709dd9 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1464,9 +1464,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) /* Check for redeclaration and other discrepancies. */ if (TREE_CODE (olddecl) == FUNCTION_DECL - && DECL_ARTIFICIAL (olddecl) - /* A C++20 implicit friend operator== uses the normal path (94462). */ - && !DECL_HIDDEN_FRIEND_P (olddecl)) + && DECL_BUILTIN_P (olddecl)) { if (TREE_CODE (newdecl) != FUNCTION_DECL) { @@ -1508,15 +1506,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) "declaration %q#D", newdecl, olddecl); return NULL_TREE; } - else if (DECL_OMP_DECLARE_REDUCTION_P (olddecl)) - { - gcc_assert (DECL_OMP_DECLARE_REDUCTION_P (newdecl)); - error_at (newdecl_loc, - "redeclaration of %"); - inform (olddecl_loc, - "previous % declaration"); - return error_mark_node; - } else if (!types_match) { /* Avoid warnings redeclaring built-ins which have not been @@ -1816,6 +1805,17 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) } } else if (TREE_CODE (newdecl) == FUNCTION_DECL + && DECL_OMP_DECLARE_REDUCTION_P (newdecl)) + { + /* OMP UDRs are never duplicates. */ + gcc_assert (DECL_OMP_DECLARE_REDUCTION_P (olddecl)); + error_at (newdecl_loc, + "redeclaration of %"); + inform (olddecl_loc, + "previous % declaration"); + return error_mark_node; + } + else if (TREE_CODE (newdecl) == FUNCTION_DECL && ((DECL_TEMPLATE_SPECIALIZATION (olddecl) && (!DECL_TEMPLATE_INFO (newdecl) || (DECL_TI_TEMPLATE (newdecl) diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index e7764ab..dbc6cc3 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2119,10 +2119,10 @@ anticipated_builtin_p (tree ovl) tree fn = OVL_FUNCTION (ovl); gcc_checking_assert (DECL_ANTICIPATED (fn)); - if (DECL_HIDDEN_FRIEND_P (fn)) - return false; + if (DECL_BUILTIN_P (fn)) + return true; - return true; + return false; } /* BINDING records an existing declaration for a name in the current scope. @@ -2857,9 +2857,12 @@ set_decl_context_in_fn (tree ctx, tree decl) { if (TREE_CODE (decl) == FUNCTION_DECL || (VAR_P (decl) && DECL_EXTERNAL (decl))) - /* Make sure local externs are marked as such. */ + /* Make sure local externs are marked as such. OMP UDRs really + are nested functions. */ gcc_checking_assert (DECL_LOCAL_DECL_P (decl) - && DECL_NAMESPACE_SCOPE_P (decl)); + && (DECL_NAMESPACE_SCOPE_P (decl) + || (TREE_CODE (decl) == FUNCTION_DECL + && DECL_OMP_DECLARE_REDUCTION_P (decl)))); if (!DECL_CONTEXT (decl) /* When parsing the parameter list of a function declarator, @@ -3934,7 +3937,7 @@ do_nonmember_using_decl (name_lookup &lookup, bool fn_scope_p, } else if (old.using_p ()) continue; /* This is a using decl. */ - else if (old.hidden_p () && !DECL_HIDDEN_FRIEND_P (old_fn)) + else if (old.hidden_p () && DECL_BUILTIN_P (old_fn)) continue; /* This is an anticipated builtin. */ else if (!matching_fn_p (new_fn, old_fn)) continue; /* Parameters do not match. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index fba3fcc..ccfae78 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -42567,7 +42567,7 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, if (current_function_decl) { block_scope = true; - DECL_CONTEXT (fndecl) = global_namespace; + DECL_CONTEXT (fndecl) = current_function_decl; DECL_LOCAL_DECL_P (fndecl) = true; if (!processing_template_decl) pushdecl (fndecl); @@ -42592,7 +42592,9 @@ cp_parser_omp_declare_reduction (cp_parser *parser, cp_token *pragma_tok, else { DECL_CONTEXT (fndecl) = current_namespace; - pushdecl (fndecl); + tree d = pushdecl (fndecl); + /* We should never meet a matched duplicate decl. */ + gcc_checking_assert (d == error_mark_node || d == fndecl); } if (!block_scope) start_preparsed_function (fndecl, NULL_TREE, SF_PRE_PARSED); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6f8dbc3..a4530db 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -18109,16 +18109,11 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, else if (DECL_IMPLICIT_TYPEDEF_P (t)) /* We already did a pushtag. */; else if (TREE_CODE (decl) == FUNCTION_DECL - && DECL_OMP_DECLARE_REDUCTION_P (decl) - && DECL_FUNCTION_SCOPE_P (pattern_decl)) + && DECL_LOCAL_DECL_P (decl) + && DECL_OMP_DECLARE_REDUCTION_P (decl)) { - /* We pretend this is regular local extern decl of - a namespace-scope fn. Then we make it really - local, it is a nested function. */ - gcc_checking_assert (DECL_LOCAL_DECL_P (decl)); - DECL_CONTEXT (decl) = global_namespace; - pushdecl (decl); DECL_CONTEXT (decl) = current_function_decl; + pushdecl (decl); if (cp_check_omp_declare_reduction (decl)) instantiate_body (pattern_decl, args, decl, true); } diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc index 279bb84..3fe310d 100644 --- a/libcc1/libcp1plugin.cc +++ b/libcc1/libcp1plugin.cc @@ -354,7 +354,7 @@ supplement_binding (cxx_binding *binding, tree decl) declared, pretend it is not there at all. */ || (TREE_CODE (target_bval) == FUNCTION_DECL && DECL_ANTICIPATED (target_bval) - && !DECL_HIDDEN_FRIEND_P (target_bval))) + && DECL_BUILTIN_P (target_bval))) binding->value = decl; else if (TREE_CODE (target_bval) == TYPE_DECL && DECL_ARTIFICIAL (target_bval) -- 2.7.4