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.
Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog 2020-02-13 Jason Merrill <ja...@redhat.com> PR c++/93643 PR c++/91476 * tree.c (decl_linkage): Always lk_none for locals. --- gcc/cp/tree.c | 9 +++---- .../g++.dg/lookup/extern-c-static1.C | 27 +++++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/extern-c-static1.C diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 736ef6fe667..72b3a720ee8 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 00000000000..0ba8d67ba15 --- /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(); +} base-commit: 613c932f5e5c0cc2e4b88e21d9870fa7b1a6ce5d -- 2.18.1