Segfault on mangling names in 11.0.1?

Hello –

I’m working on a tool that dumps a C++ AST to Coq and, to avoid the complexities of overload resolution, I mangle all names before outputting them. Here’s essentially the code that I’m using (available here:

ClangPrinter::printGlobalName(const NamedDecl *decl, CoqPrinter &print, bool raw) {
if (auto fd = dyn_cast(decl)) {
if (fd->getLanguageLinkage() == LanguageLinkage::CLanguageLinkage) {
print.output() << fd->getNameAsString();
} else {
mangleContext_->mangleCXXName(decl, print.output().nobreak());
} else {
mangleContext_->mangleCXXName(decl, print.output().nobreak());

This code works on clang 10 (and a patched version works on clang 11.0.0 released on manjaro/arch, though that code is still under development), but fails on the nightly build (which our CI server is using) by segfaulting. Here’s the top of the stack trace.

#0 0x000055e6c2b79ea0 in (anonymous namespace)::getEffectiveDeclContext(clang::Decl const*) ()
#1 0x000055e6c2b7b85a in (anonymous namespace)::CXXNameMangler::mangleNameWithAbiTags(clang::GlobalDecl, llvm::SmallVector<llvm::StringRef, 4u> const*) ()
#2 0x000055e6c2b77574 in (anonymous namespace)::ItaniumMangleContextImpl::mangleCXXName(clang::GlobalDecl, llvm::raw_ostream&) ()
#3 0x000055e6c2da2094 in ClangPrinter::printGlobalName (this=0x7fff716d1540, decl=0x55e6c521fc10, print=…, raw=false) at /home/coq/cpp2v-core/src/ClangPrinter.cpp:56

I’ve tracked down segfaults to the following:

  • implicit declarations, e.g. __NSConstantString_tag
  • enumerations
  • enum constants
  • locally declared struct (maybe all structures)

Is this intended? I know that some of these don’t really ever need to be mangled, but the previous name mangler seemed to handle those transparently. I did note that shouldMangleCXXName does return true on at least the implicit declaration __NSConstantString_tag.

I’ve also tracked down a different seg fault when printing the name of constructors.

#0 __GI_raise (sig=sig@entry=6) at …/sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007f8514fbc535 in __GI_abort () at abort.c:79
#2 0x00007f8514fbc40f in __assert_fail_base (fmt=0x7f851511eee0 “%s%s%s:%u: %s%sAssertion `%s’ failed.\n%n”, assertion=0x56390e19d1a8 “!isa(D) && “Use other ctor with ctor decls!””,
file=0x56390e19d178 “/usr/lib/llvm-11/include/clang/AST/GlobalDecl.h”, line=59, function=) at assert.c:92
#3 0x00007f8514fca102 in __GI___assert_fail (assertion=0x56390e19d1a8 “!isa(D) && “Use other ctor with ctor decls!””, file=0x56390e19d178 “/usr/lib/llvm-11/include/clang/AST/GlobalDecl.h”, line=59,
function=0x56390e19d980 <clang::GlobalDecl::Init(clang::Decl const*)::PRETTY_FUNCTION> “void clang::GlobalDecl::Init(const clang::Decl*)”) at assert.c:101
#4 0x000056390df90d50 in clang::GlobalDecl::Init (this=0x7ffe827e72e0, D=0x56390ea1ebd0) at /usr/lib/llvm-11/include/clang/AST/GlobalDecl.h:59
#5 0x000056390df90e1e in clang::GlobalDecl::GlobalDecl (this=0x7ffe827e72e0, D=0x56390ea1ebd0) at /usr/lib/llvm-11/include/clang/AST/GlobalDecl.h:81
#6 0x000056390df8ff80 in ClangPrinter::printGlobalName (this=0x7ffe827e7590, decl=0x56390ea1ebd0, print=…, raw=false) at /home/coq/cpp2v-core/src/ClangPrinter.cpp:47

Is there some invariant that I am possibly breaking? Or is this a bug? I checked the delta between my version and the 11.0.0 release and didn’t find anything that seems like it would affect this. The latest code does use the Sema object to generate implicit declarations, so it puts the parser in incremental mode to start with and then calls ActOnEndOfTranslationUnit before invoking these functions. I’m not sure if there is more stuff that I need to do in more recent versions.

Thanks in advance for any pointers.