From ba12ea31b1c211d2aa9d3f9c35f34156adbe5634 Mon Sep 17 00:00:00 2001
From: jakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Thu, 17 Aug 2006 11:52:26 +0000
Subject: [PATCH] 	PR c/28744 	* cgraph.h (struct cgraph_node):
 Remove externally_visible 	bitfield. 	* cgraphunit.c
 (process_function_and_variable_attributes): Set 
 local.externally_visible rather than externally_visible.

	PR c/28744
	* c-common.c (handle_externally_visible_attribute): First look
	at TREE_CODE and only if it is function or var decl, check for
	non-public objects.  Don't warn for DECL_EXTERNAL.
	* cgraphunit.c (process_function_and_variable_attributes): Warn
	if externally_visible attribute is used on non-public object.

	* gcc.dg/attr-externally-visible-1.c: New test.
	* gcc.dg/attr-externally-visible-2.c: New test.
	* g++.dg/parse/attr-externally-visible-1.C: New test.
	* g++.dg/parse/attr-externally-visible-2.C: New test.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@116222 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                                 | 15 ++++++
 gcc/c-common.c                                | 16 +++----
 gcc/cgraph.h                                  |  2 -
 gcc/cgraphunit.c                              | 26 +++++++---
 gcc/testsuite/ChangeLog                       |  8 ++++
 .../g++.dg/parse/attr-externally-visible-1.C  | 48 +++++++++++++++++++
 .../g++.dg/parse/attr-externally-visible-2.C  | 38 +++++++++++++++
 .../gcc.dg/attr-externally-visible-1.c        | 48 +++++++++++++++++++
 .../gcc.dg/attr-externally-visible-2.c        | 33 +++++++++++++
 9 files changed, 218 insertions(+), 16 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C
 create mode 100644 gcc/testsuite/g++.dg/parse/attr-externally-visible-2.C
 create mode 100644 gcc/testsuite/gcc.dg/attr-externally-visible-1.c
 create mode 100644 gcc/testsuite/gcc.dg/attr-externally-visible-2.c

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6b36ab8a95fc..61d5fe0d7e88 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,18 @@
+2006-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/28744
+	* cgraph.h (struct cgraph_node): Remove externally_visible
+	bitfield.
+	* cgraphunit.c (process_function_and_variable_attributes): Set
+	local.externally_visible rather than externally_visible.
+
+	PR c/28744
+	* c-common.c (handle_externally_visible_attribute): First look
+	at TREE_CODE and only if it is function or var decl, check for
+	non-public objects.  Don't warn for DECL_EXTERNAL.
+	* cgraphunit.c (process_function_and_variable_attributes): Warn
+	if externally_visible attribute is used on non-public object.
+
 2006-08-17  Jan Hubicka  <jh@suse.cz>
 
 	PR tree-optimization/27865
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 17643f0b5abc..a6b329997b4d 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -4301,16 +4301,16 @@ handle_externally_visible_attribute (tree *pnode, tree name,
 {
   tree node = *pnode;
 
-  if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL)
-      || !TREE_PUBLIC (node))
+  if (TREE_CODE (node) == FUNCTION_DECL || TREE_CODE (node) == VAR_DECL)
     {
-      warning (OPT_Wattributes,
-	       "%qE attribute have effect only on public objects", name);
-      *no_add_attrs = true;
+      if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL
+	   && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node))
+	{
+	  warning (OPT_Wattributes,
+		   "%qE attribute have effect only on public objects", name);
+	  *no_add_attrs = true;
+	}
     }
-  else if (TREE_CODE (node) == FUNCTION_DECL
-	   || TREE_CODE (node) == VAR_DECL)
-    ;
   else
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 31ddfe37d0ae..7b69611ddcd0 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -160,8 +160,6 @@ struct cgraph_node GTY((chain_next ("%h.next"), chain_prev ("%h.previous")))
   unsigned analyzed : 1;
   /* Set when function is scheduled to be assembled.  */
   unsigned output : 1;
-  /* Set when function is visible by other units.  */
-  unsigned externally_visible : 1;
   /* Set for aliases once they got through assemble_alias.  */
   unsigned alias : 1;
 
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index ddaecd3aa1c6..64b3891df7bc 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -985,9 +985,16 @@ process_function_and_variable_attributes (struct cgraph_node *first,
 	}
       if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
 	{
-	  if (node->local.finalized)
-	    cgraph_mark_needed_node (node);
-	  node->externally_visible = true;
+	  if (! TREE_PUBLIC (node->decl))
+	    warning (OPT_Wattributes,
+		     "%J%<externally_visible%> attribute have effect only on public objects",
+		     node->decl);
+	  else
+	    {
+	      if (node->local.finalized)
+		cgraph_mark_needed_node (node);
+	      node->local.externally_visible = true;
+	    }
 	}
     }
   for (vnode = cgraph_varpool_nodes; vnode != first_var; vnode = vnode->next)
@@ -1001,9 +1008,16 @@ process_function_and_variable_attributes (struct cgraph_node *first,
 	}
       if (lookup_attribute ("externally_visible", DECL_ATTRIBUTES (decl)))
 	{
-	  if (vnode->finalized)
-	    cgraph_varpool_mark_needed_node (vnode);
-	  vnode->externally_visible = true;
+	  if (! TREE_PUBLIC (vnode->decl))
+	    warning (OPT_Wattributes,
+		     "%J%<externally_visible%> attribute have effect only on public objects",
+		     vnode->decl);
+	  else
+	    {
+	      if (vnode->finalized)
+		cgraph_varpool_mark_needed_node (vnode);
+	      vnode->externally_visible = true;
+	    }
 	}
     }
 }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3ccd52def7b9..3c65908443f9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2006-08-17  Jakub Jelinek  <jakub@redhat.com>
+
+	PR c/28744
+	* gcc.dg/attr-externally-visible-1.c: New test.
+	* gcc.dg/attr-externally-visible-2.c: New test.
+	* g++.dg/parse/attr-externally-visible-1.C: New test.
+	* g++.dg/parse/attr-externally-visible-2.C: New test.
+
 2006-08-17  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
 	PR c++/28606
diff --git a/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C b/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C
new file mode 100644
index 000000000000..9016bc4225af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/attr-externally-visible-1.C
@@ -0,0 +1,48 @@
+// { dg-do compile }
+// { dg-options "-O3 -fwhole-program" }
+// { dg-final { scan-assembler "foo1" } }
+// { dg-final { scan-assembler "foo2" } }
+// { dg-final { scan-assembler "foo3" } }
+// { dg-final { scan-assembler "foo4" } }
+// { dg-final { scan-assembler "foo5" } }
+// { dg-final { scan-assembler-not "foo6" } }
+// { dg-final { scan-assembler "bar1" } }
+// { dg-final { scan-assembler "bar2" } }
+// { dg-final { scan-assembler "bar3" } }
+// { dg-final { scan-assembler "bar4" } }
+// { dg-final { scan-assembler "bar5" } }
+// { dg-final { scan-assembler-not "bar6" } }
+
+extern void foo1 (void) __attribute__((externally_visible));
+void foo1 (void) { }
+
+extern void foo2 (void) __attribute__((externally_visible));
+__attribute__((externally_visible)) void foo2 (void) { }
+
+extern void foo3 (void);
+__attribute__((externally_visible)) void foo3 (void) { }
+
+__attribute__((externally_visible)) void foo4 (void) { }
+
+void foo5 (void) { }
+extern void foo5 (void) __attribute__((externally_visible));
+
+void foo6 (void) { }
+
+extern char *bar1 __attribute__((externally_visible));
+char *bar1;
+
+extern char *bar2 __attribute__((externally_visible));
+char *bar2 __attribute__((externally_visible));
+
+extern char *bar3;
+char *bar3 __attribute__((externally_visible));
+
+char *bar4 __attribute__((externally_visible));
+
+char *bar5;
+extern char *bar5 __attribute__((externally_visible));
+
+char *bar6;
+
+int main (void) { }
diff --git a/gcc/testsuite/g++.dg/parse/attr-externally-visible-2.C b/gcc/testsuite/g++.dg/parse/attr-externally-visible-2.C
new file mode 100644
index 000000000000..d7feaabb2d11
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/attr-externally-visible-2.C
@@ -0,0 +1,38 @@
+// { dg-do compile }
+// { dg-options "-O -fwhole-program" }
+
+static void foo1 (void) { }					// { dg-warning "have effect only on public" }
+extern void foo1 (void) __attribute__((externally_visible));
+
+struct C
+{
+  __attribute__((externally_visible)) void foo3 (void) { }
+};
+
+__attribute__((externally_visible)) static void foo3 (void) { }	// { dg-warning "have effect only on public" }
+
+static int bar1;
+extern int bar1 __attribute__((externally_visible));		// { dg-warning "have effect only on public" }
+
+static int bar2 __attribute__((externally_visible));		// { dg-warning "have effect only on public" }
+
+void fn1 (void)
+{
+  static int bar3 __attribute__((externally_visible));		// { dg-warning "have effect only on public" }
+}
+
+void fn2 (void)
+{
+  int bar4 __attribute__((externally_visible));			// { dg-warning "have effect only on public" }
+}
+
+struct A
+{
+} __attribute__((externally_visible));				// { dg-warning "does not apply to types" }
+
+typedef int B __attribute__((externally_visible));		// { dg-warning "attribute ignored" }
+
+struct D
+{
+  static int d __attribute__((externally_visible));
+};
diff --git a/gcc/testsuite/gcc.dg/attr-externally-visible-1.c b/gcc/testsuite/gcc.dg/attr-externally-visible-1.c
new file mode 100644
index 000000000000..e1db6923a484
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-externally-visible-1.c
@@ -0,0 +1,48 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fwhole-program" } */
+/* { dg-final { scan-assembler "foo1" } } */
+/* { dg-final { scan-assembler "foo2" } } */
+/* { dg-final { scan-assembler "foo3" } } */
+/* { dg-final { scan-assembler "foo4" } } */
+/* { dg-final { scan-assembler "foo5" } } */
+/* { dg-final { scan-assembler-not "foo6" } } */
+/* { dg-final { scan-assembler "bar1" } } */
+/* { dg-final { scan-assembler "bar2" } } */
+/* { dg-final { scan-assembler "bar3" } } */
+/* { dg-final { scan-assembler "bar4" } } */
+/* { dg-final { scan-assembler "bar5" } } */
+/* { dg-final { scan-assembler-not "bar6" } } */
+
+extern void foo1 (void) __attribute__((externally_visible));
+void foo1 (void) { }
+
+extern void foo2 (void) __attribute__((externally_visible));
+__attribute__((externally_visible)) void foo2 (void) { }
+
+extern void foo3 (void);
+__attribute__((externally_visible)) void foo3 (void) { }
+
+__attribute__((externally_visible)) void foo4 (void) { }
+
+void foo5 (void) { }
+extern void foo5 (void) __attribute__((externally_visible));
+
+void foo6 (void) { }
+
+extern char *bar1 __attribute__((externally_visible));
+char *bar1;
+
+extern char *bar2 __attribute__((externally_visible));
+char *bar2 __attribute__((externally_visible));
+
+extern char *bar3;
+char *bar3 __attribute__((externally_visible));
+
+char *bar4 __attribute__((externally_visible));
+
+char *bar5;
+extern char *bar5 __attribute__((externally_visible));
+
+char *bar6;
+
+int main (void) { }
diff --git a/gcc/testsuite/gcc.dg/attr-externally-visible-2.c b/gcc/testsuite/gcc.dg/attr-externally-visible-2.c
new file mode 100644
index 000000000000..0a925bab3d94
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-externally-visible-2.c
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fwhole-program" } */
+
+static void foo1 (void) { }					/* { dg-warning "have effect only on public" } */
+extern void foo1 (void) __attribute__((externally_visible));
+
+void foo2 (void)
+{
+  __attribute__((externally_visible)) void foo3 (void) { }	/* { dg-warning "have effect only on public" } */
+}
+
+__attribute__((externally_visible)) static void foo3 (void) { }	/* { dg-warning "have effect only on public" } */
+
+static int bar1;
+extern int bar1 __attribute__((externally_visible));		/* { dg-warning "have effect only on public" } */
+
+static int bar2 __attribute__((externally_visible));		/* { dg-warning "have effect only on public" } */
+
+void fn1 (void)
+{
+  static int bar3 __attribute__((externally_visible));		/* { dg-warning "have effect only on public" } */
+}
+
+void fn2 (void)
+{
+  int bar4 __attribute__((externally_visible));			/* { dg-warning "have effect only on public" } */
+}
+
+struct A
+{
+} __attribute__((externally_visible));				/* { dg-warning "does not apply to types" } */
+
+typedef int B __attribute__((externally_visible));		/* { dg-warning "attribute ignored" } */
-- 
GitLab