aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-02-13 16:42:04 +0100
committerJason Merrill <jason@redhat.com>2020-02-13 22:29:25 +0100
commitabc79c6498a99e9c39e6056f432796c6dde3a887 (patch)
tree1093a665d33c96e5f27b37b70894361574830d42
parent613c932f5e5c0cc2e4b88e21d9870fa7b1a6ce5d (diff)
downloadgcc-abc79c6498a99e9c39e6056f432796c6dde3a887.zip
gcc-abc79c6498a99e9c39e6056f432796c6dde3a887.tar.gz
gcc-abc79c6498a99e9c39e6056f432796c6dde3a887.tar.bz2
c++: Fix static local vars in extern "C".
Since my patch for PR 91476 moved visibility determination sooner, a local static in a vague linkage function now gets TREE_PUBLIC set before retrofit_lang_decl calls set_decl_linkage, which was making decl_linkage think that it has external linkage. It still has no linkage according to the standard. gcc/cp/ChangeLog 2020-02-13 Jason Merrill <jason@redhat.com> PR c++/93643 PR c++/91476 * tree.c (decl_linkage): Always lk_none for locals.
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/tree.c9
-rw-r--r--gcc/testsuite/g++.dg/lookup/extern-c-static1.C27
3 files changed, 37 insertions, 5 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e0dd038..8d7d91c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2020-02-13 Jason Merrill <jason@redhat.com>
+
+ PR c++/93643
+ PR c++/91476
+ * tree.c (decl_linkage): Always lk_none for locals.
+
2020-02-12 Jason Merrill <jason@redhat.com>
PR c++/92583
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 736ef6f..72b3a72 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -5266,6 +5266,10 @@ decl_linkage (tree decl)
if (TREE_CODE (decl) == FIELD_DECL)
return lk_none;
+ /* Things in local scope do not have linkage. */
+ if (decl_function_context (decl))
+ return lk_none;
+
/* Things that are TREE_PUBLIC have external linkage. */
if (TREE_PUBLIC (decl))
return lk_external;
@@ -5285,11 +5289,6 @@ decl_linkage (tree decl)
if (TREE_CODE (decl) == CONST_DECL)
return decl_linkage (TYPE_NAME (DECL_CONTEXT (decl)));
- /* Things in local scope do not have linkage, if they don't have
- TREE_PUBLIC set. */
- if (decl_function_context (decl))
- return lk_none;
-
/* Members of the anonymous namespace also have TREE_PUBLIC unset, but
are considered to have external linkage for language purposes, as do
template instantiations on targets without weak symbols. DECLs really
diff --git a/gcc/testsuite/g++.dg/lookup/extern-c-static1.C b/gcc/testsuite/g++.dg/lookup/extern-c-static1.C
new file mode 100644
index 0000000..0ba8d67
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/extern-c-static1.C
@@ -0,0 +1,27 @@
+// PR c++/93643
+
+void* callback(const char* name);
+
+extern "C" {
+
+ inline void f1()
+ {
+ static void (*f)();
+ f = (void(*)()) callback("f1");
+ f();
+ }
+
+ inline void f2()
+ {
+ static void (*f)();
+ f = (void(*)()) callback("f2");
+ f();
+ }
+
+} // extern "C"
+
+int main()
+{
+ f1();
+ f2();
+}