From abc79c6498a99e9c39e6056f432796c6dde3a887 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 13 Feb 2020 16:42:04 +0100 Subject: [PATCH] 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 PR c++/93643 PR c++/91476 * tree.c (decl_linkage): Always lk_none for locals. --- gcc/cp/ChangeLog | 6 ++++++ gcc/cp/tree.c | 9 ++++----- gcc/testsuite/g++.dg/lookup/extern-c-static1.C | 27 ++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/extern-c-static1.C 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 + + PR c++/93643 + PR c++/91476 + * tree.c (decl_linkage): Always lk_none for locals. + 2020-02-12 Jason Merrill 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(); +} -- 2.7.4