diff mbox series

[C++] * decl2.c (min_vis_expr_r, expr_visibility): New.

Message ID 20181113044605.10799-1-jason@redhat.com
State New
Headers show
Series [C++] * decl2.c (min_vis_expr_r, expr_visibility): New. | expand

Commit Message

Jason Merrill Nov. 13, 2018, 4:46 a.m. UTC
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.

Tested x86_64-pc-linux-gnu, applying to trunk.

	(min_vis_r): Call expr_visibility.
	(constrain_visibility_for_template): Likewise.
---
 gcc/cp/decl2.c                              | 77 +++++++++++++++++----
 gcc/testsuite/g++.dg/abi/no-linkage-expr1.C | 19 +++++
 gcc/cp/ChangeLog                            |  4 ++
 3 files changed, 85 insertions(+), 15 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/no-linkage-expr1.C


base-commit: 76b94d4ba654e9af1882865933343d11f5c3b18b
diff mbox series

Patch

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 <int N>
+void f(int(*)[((P)0, N)]) {}
+
+template <int N>
+struct A { };
+
+template <int N>
+void g(A<((P)0,N)>) {}
+
+int main()
+{
+  f<1>(0);
+  g<1>({});
+}
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  <jason@redhat.com>
 
+	* 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