% cat test.ii namespace std { inline namespace { int to_string(); void to_string(int); } void to_string(); } int std::to_string(); % clang++ -c test.ii clang-5.0: /home/markus/llvm/clang/lib/AST/Decl.cpp:1383: static clang::LinkageInfo clang::LinkageComputer::getLVForDecl(const clang::NamedDecl*, LVComputationKind): Assertion `!Old || Old->getCachedLinkage() == D->getCachedLinkage()' failed. #0 0x00007f38fcde263a llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/usr/local/bin/../lib/libLLVMSupport.so.5+0x11663a) #1 0x00007f38fcde01c6 llvm::sys::RunSignalHandlers() (/usr/local/bin/../lib/libLLVMSupport.so.5+0x1141c6) #2 0x00007f38fcde052a SignalHandler(int) (/usr/local/bin/../lib/libLLVMSupport.so.5+0x11452a) #3 0x00007f38fc72f750 __restore_rt (/lib/libpthread.so.0+0x12750) #4 0x00007f38fb3ff44e __GI_raise /home/markus/glibc/signal/../sysdeps/unix/sysv/linux/raise.c:51:0 #5 0x00007f38fb400fd6 __GI_abort /home/markus/glibc/stdlib/abort.c:92:0 #6 0x00007f38fb3f795c __assert_fail_base /home/markus/glibc/assert/assert.c:89:0 #7 0x00007f38fb3f79e2 (/lib/libc.so.6+0x2e9e2) #8 0x00007f38fa52a3df clang::LinkageComputer::getLVForDecl(clang::NamedDecl const*, LVComputationKind) (/usr/local/bin/../lib/../lib/libclangAST.so.5+0x1ac3df) #9 0x00007f38fa52ac6e clang::NamedDecl::getLinkageInternal() const (/usr/local/bin/../lib/../lib/libclangAST.so.5+0x1acc6e) #10 0x00007f38f97ffa68 clang::Sema::ActOnFunctionDeclarator(clang::Scope*, clang::Declarator&, clang::DeclContext*, clang::TypeSourceInfo*, clang::LookupResult&, llvm::MutableArrayRef<clang::TemplateParameterList*>, bool&) (/usr/local/bin/../lib/../lib/libclangSema.so.5+0x24fa68) #11 0x00007f38f980462a clang::Sema::HandleDeclarator(clang::Scope*, clang::Declarator&, llvm::MutableArrayRef<clang::TemplateParameterList*>) (/usr/local/bin/../lib/../lib/libclangSema.so.5+0x25462a) #12 0x00007f38f9804e1a clang::Sema::ActOnDeclarator(clang::Scope*, clang::Declarator&) (/usr/local/bin/../lib/../lib/libclangSema.so.5+0x254e1a) #13 0x00007f38f9f0bc2d clang::Parser::ParseDeclarationAfterDeclaratorAndAttributes(clang::Declarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::ForRangeInit*) (/usr/local/bin/../lib/../lib/libclangParse.so.5+0x3bc2d) #14 0x00007f38f9f1bf30 clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, unsigned int, clang::SourceLocation*, clang::Parser::ForRangeInit*) (/usr/local/bin/../lib/../lib/libclangParse.so.5+0x4bf30) #15 0x00007f38f9f9b779 clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec&, clang::AccessSpecifier) (/usr/local/bin/../lib/../lib/libclangParse.so.5+0xcb779) #16 0x00007f38f9f9bd91 clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*, clang::AccessSpecifier) [clone .part.167] (/usr/local/bin/../lib/../lib/libclangParse.so.5+0xcbd91) #17 0x00007f38f9fa141a clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) (/usr/local/bin/../lib/../lib/libclangParse.so.5+0xd141a) #18 0x00007f38f9fa22a0 clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) (/usr/local/bin/../lib/../lib/libclangParse.so.5+0xd22a0) #19 0x00007f38f9efdba2 clang::ParseAST(clang::Sema&, bool, bool) (/usr/local/bin/../lib/../lib/libclangParse.so.5+0x2dba2) #20 0x00007f38fc17ee80 clang::CodeGenAction::ExecuteAction() (/usr/local/bin/../lib/libclangCodeGen.so.5+0x293e80) #21 0x00007f38fbc9978e clang::FrontendAction::Execute() (/usr/local/bin/../lib/libclangFrontend.so.5+0xd278e) #22 0x00007f38fbc58eee clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) (/usr/local/bin/../lib/libclangFrontend.so.5+0x91eee) #23 0x00007f38ff26d931 clang::ExecuteCompilerInvocation(clang::CompilerInstance*) (/usr/local/bin/../lib/libclangFrontendTool.so.5+0x3931) #24 0x0000000000410278 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) (/usr/local/bin/clang-5.0+0x410278) #25 0x000000000040b978 main (/usr/local/bin/clang-5.0+0x40b978) #26 0x00007f38fb3e964c __libc_start_main /home/markus/glibc/csu/../csu/libc-start.c:335:0 #27 0x000000000040c53a _start /home/markus/glibc/csu/../sysdeps/x86_64/start.S:122:0 Stack dump: 0. Program arguments: /usr/local/bin/clang-5.0 -cc1 -triple x86_64-unknown-linux-gnu -emit-obj -mrelax-all -disable-free -main-file-name test.ii -mrelocation-model static -mthread-model posix -mdisable-fp-elim -fmath-errno -masm-verbose -mconstructor-aliases -munwind-tables -fuse-init-array -target-cpu x86-64 -dwarf-column-info -debugger-tuning=gdb -coverage-notes-file /tmp/test.gcno -resource-dir /usr/local/lib/clang/5.0.0 -fdeprecated-macro -fdebug-compilation-dir /tmp -ferror-limit 19 -fmessage-length 179 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -o test.o -x c++-cpp-output test.ii 1. test.ii:8:21: current parser token ';' clang-5.0: error: unable to execute command: Aborted clang-5.0: error: clang frontend command failed due to signal (use -v to see invocation) clang version 5.0.0 Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/local/bin clang-5.0: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script. clang-5.0: note: diagnostic msg: Error generating preprocessed source(s) - no preprocessable inputs.
The proper solution to fix this and the other similar 20 bugs reported is to delay linkage computation, as we discussed with Rafael in the past.
[Picking this bug, as it seems to be the most recent case of this assertion] This assertion popped up again in recent Firefox builds, see https://bugs.freebsd.org/222280 and https://bugzilla.mozilla.org/1399412, where some C source gets included into a C++ file, wrapped in an anonymous namespace. Reduces to: namespace { extern "C" union LZ4_stream_u *LZ4_createStream(); LZ4_stream_u *LZ4_createStream(); } Could we perhaps close bug 19995, bug 21854, bug 23090, and maybe others that report the same as duplicates? Also, is there any way of doing a minimal fix for this particular assertion? There seems to be no need to generate any warnings or errors for this construct: gcc has no problems at all with it, and does not complain even with -Wall -Wextra.
I don't see why lazy computation of linkage is relevant to this test case. Why is the linkage changing at all?
(In reply to John McCall from comment #3) > I don't see why lazy computation of linkage is relevant to this test case. > Why is the linkage changing at all? From extern-C to non-extern-C, in combination with an anonymous namespace, I think. Removing the namespace causes the assertion not to fire, e.g: extern "C" union a *b(); a *b(); works fine.
Sorry, I was looking at the original test case in this bug, but we can look at your new one, too. Even in your example, it seems to me that there shouldn't be a problem if the declaration is properly recognized as a redeclaration immediately, because otherwise a ton of other, simpler cases would break, like this one: static void test(); void test();
(In reply to John McCall from comment #5) > Sorry, I was looking at the original test case in this bug, but we can look > at your new one, too. Yes, these bugs seems to have the same root cause: a mismatch in linkage due to namespaces (or scope, I'm unsure). For example: extern "C" union foo *bar(); foo *bar(); compiles fine, while: namespace { extern "C" union LZ4_stream_u *LZ4_createStream(); LZ4_stream_u *LZ4_createStream(); } asserts. The example from this bug's description stops asserting if the anonymous namespace is removed: namespace std { //inline namespace { int to_string(); void to_string(int); //} void to_string(); } int std::to_string(); The example from bug 19995: inline namespace { template <typename T> int foo(T); } template <> int foo(int); obviously also stops asserting when the namespace is removed, but then the two declarations are completely equivalent. The only oddball case is that from bug 21854: void tpl_mem() { class A { void f(); }; void A::f(); void f(); } where it first prints a regular error, and only asserts after that: bug21854.cpp:5:11: error: out-of-line declaration of a member must be a definition void A::f(); ~~~^ > Even in your example, it seems to me that there > shouldn't be a problem if the declaration is properly recognized as a > redeclaration immediately, because otherwise a ton of other, simpler cases > would break, like this one: > > static void test(); > void test(); Indeed, this is pretty strange.
I found another reproducer without any namespaces: extern "C" { typedef struct { int x; } *ReturnStruct; ReturnStruct foo(int s); } ReturnStruct foo(int s) { }
The above sample is actually a regression after r313729, I will file a new release blocker PR
The original testcase reduces to: inline namespace { int to_string(); } int ::to_string(); ... which looks like it's asserting because we built a broken AST: the semantic DeclContext of the second to_string declaration is incorrectly set to the TU, whereas it should be the anonymous namespace. (That is, this is not a "linkage computed too early" problem.) That's fixed in r321770. The testcase in comment#2 passes at head, and is a duplicate of PR35697 (that test happens to tickle the same bug prior to the change in r313729 that exposed the bug more widely). Bug #19995 looks like a similar wrong-AST bug to this one (another case where inline namespaces can unexpectedly change the semantic context of a declaration), but not a duplicate. Bug #21854 is an unrelated bug, where error recovery has left us with a malformed AST. So this bug is fixed, and those two other bugs are distinct issues that simply happen to trip up the same assert. Of particular note: none of these would be fixed by delaying linkage calculation; they're all bugs in other parts of Clang.