From: Jason Merrill Date: Tue, 13 Nov 2018 04:46:20 +0000 (-0500) Subject: decl2.c (min_vis_expr_r, [...]): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7c23c87c93f3eafa5c22d1f4f52711d97f3a4329;p=gcc.git decl2.c (min_vis_expr_r, [...]): New. * decl2.c (min_vis_expr_r, expr_visibility): New. We weren't properly constraining visibility based on names that appear in the mangled representation of expressions. This was made more obvious by the upcoming unevaluated lambdas patch. (min_vis_r): Call expr_visibility. (constrain_visibility_for_template): Likewise. From-SVN: r266054 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5497a0829e3..79c162c75b0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2018-11-12 Jason Merrill + * decl2.c (min_vis_expr_r, expr_visibility): New. + (min_vis_r): Call expr_visibility. + (constrain_visibility_for_template): Likewise. + Implement P0722R3, destroying operator delete. * call.c (std_destroying_delete_t_p, destroying_delete_p): New. (aligned_deallocation_fn_p, usual_deallocation_fn_p): Use diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 13c156b947d..74b9f4ee826 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2238,6 +2238,9 @@ maybe_emit_vtables (tree ctype) enum { VISIBILITY_ANON = VISIBILITY_INTERNAL+1 }; +static int expr_visibility (tree); +static int type_visibility (tree); + /* walk_tree helper function for type_visibility. */ static tree @@ -2257,9 +2260,55 @@ min_vis_r (tree *tp, int *walk_subtrees, void *data) else if (CLASS_TYPE_P (*tp) && CLASSTYPE_VISIBILITY (*tp) > *vis_p) *vis_p = CLASSTYPE_VISIBILITY (*tp); + else if (TREE_CODE (*tp) == ARRAY_TYPE + && uses_template_parms (TYPE_DOMAIN (*tp))) + { + int evis = expr_visibility (TYPE_MAX_VALUE (TYPE_DOMAIN (*tp))); + if (evis > *vis_p) + *vis_p = evis; + } return NULL; } +/* walk_tree helper function for expr_visibility. */ + +static tree +min_vis_expr_r (tree *tp, int */*walk_subtrees*/, void *data) +{ + int *vis_p = (int *)data; + int tpvis = VISIBILITY_DEFAULT; + + switch (TREE_CODE (*tp)) + { + case CAST_EXPR: + case IMPLICIT_CONV_EXPR: + case STATIC_CAST_EXPR: + case REINTERPRET_CAST_EXPR: + case CONST_CAST_EXPR: + case DYNAMIC_CAST_EXPR: + case NEW_EXPR: + case CONSTRUCTOR: + tpvis = type_visibility (TREE_TYPE (*tp)); + break; + + case VAR_DECL: + case FUNCTION_DECL: + if (! TREE_PUBLIC (*tp)) + tpvis = VISIBILITY_ANON; + else + tpvis = DECL_VISIBILITY (*tp); + break; + + default: + break; + } + + if (tpvis > *vis_p) + *vis_p = tpvis; + + return NULL_TREE; +} + /* Returns the visibility of TYPE, which is the minimum visibility of its component types. */ @@ -2271,6 +2320,18 @@ type_visibility (tree type) return vis; } +/* Returns the visibility of an expression EXPR that appears in the signature + of a function template, which is the minimum visibility of names that appear + in its mangling. */ + +static int +expr_visibility (tree expr) +{ + int vis = VISIBILITY_DEFAULT; + cp_walk_tree_without_duplicates (&expr, min_vis_expr_r, &vis); + return vis; +} + /* Limit the visibility of DECL to VISIBILITY, if not explicitly specified (or if VISIBILITY is static). If TMPL is true, this constraint is for a template argument, and takes precedence @@ -2329,21 +2390,7 @@ constrain_visibility_for_template (tree decl, tree targs) if (TYPE_P (arg)) vis = type_visibility (arg); else - { - if (REFERENCE_REF_P (arg)) - arg = TREE_OPERAND (arg, 0); - if (TREE_TYPE (arg)) - STRIP_NOPS (arg); - if (TREE_CODE (arg) == ADDR_EXPR) - arg = TREE_OPERAND (arg, 0); - if (VAR_OR_FUNCTION_DECL_P (arg)) - { - if (! TREE_PUBLIC (arg)) - vis = VISIBILITY_ANON; - else - vis = DECL_VISIBILITY (arg); - } - } + vis = expr_visibility (arg); if (vis) constrain_visibility (decl, vis, true); } diff --git a/gcc/testsuite/g++.dg/abi/no-linkage-expr1.C b/gcc/testsuite/g++.dg/abi/no-linkage-expr1.C new file mode 100644 index 00000000000..c3b1286ba4c --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/no-linkage-expr1.C @@ -0,0 +1,19 @@ +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler-not "weak.*_Z" } } + +using P = struct {}*; + +template +void f(int(*)[((P)0, N)]) {} + +template +struct A { }; + +template +void g(A<((P)0,N)>) {} + +int main() +{ + f<1>(0); + g<1>({}); +}