Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang] crash in ItaniumMangler when using GNU anonymous union+struct as a non-type template parameter #54588

Closed
a2flo opened this issue Mar 27, 2022 · 7 comments
Labels
clang:codegen crash Prefer [crash-on-valid] or [crash-on-invalid]

Comments

@a2flo
Copy link

a2flo commented Mar 27, 2022

When using a non-zero-initialized class that contains a nested anonymous union+struct (GNU extension) as a C++17/20 auto/non-type template parameter, this crashes the Itanium mangler. I haven't tested this on the Microsoft mangler, but it's probably a good idea to test this as well.

Reduced repro code (build with -std=gnu++20):

template <typename T>
class wrapper {
public:
	union {
		struct {
			T val;
		};
	};
};

template <auto tparam> int dummy() { return 0; }

int main() {
	dummy<wrapper<int> {}>(); // succeeds due to "isZeroInitialized()"
	dummy<wrapper<int> { 42 }>(); // fails/crashes to due "FD->getIdentifier()" returning nullptr
	return 0;
}

Location where this crashes (5630 evaluates to false, leading to the call of FD->getIdentifier() which returns nullptr for the field):

case APValue::Union: {

Tested with clang 14.0.0, 13.0.1, Apple clang 13.1 and clang trunk on godbolt.

godbolt:
https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,selection:(endColumn:1,endLineNumber:19,positionColumn:1,positionLineNumber:19,selectionStartColumn:1,selectionStartLineNumber:19,startColumn:1,startLineNumber:19),source:'%0Atemplate+%3Ctypename+T%3E%0Aclass+wrapper+%7B%0Apublic:%0A%09union+%7B%0A%09%09struct+%7B%0A%09%09%09T+val%3B%0A%09%09%7D%3B%0A%09%7D%3B%0A%7D%3B%0A%0Atemplate+%3Cauto+tparam%3E+int+dummy()+%7B+return+0%3B+%7D%0A%0Aint+main()+%7B%0A%09dummy%3Cwrapper%3Cint%3E+%7B%7D%3E()%3B+//+succeeds+due+to+%22isZeroInitialized()%22%0A%09dummy%3Cwrapper%3Cint%3E+%7B+42+%7D%3E()%3B+//+fails/crashes+to+due+%22FD-%3EgetIdentifier()%22+returning+nullptr%0A%09return+0%3B%0A%7D%0A'),l:'5',n:'0',o:'C%2B%2B+source+%231',t:'0')),k:33.333333333333336,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:compiler,i:(compiler:clang_assertions_trunk,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:c%2B%2B,libs:!(),options:'-std%3Dgnu%2B%2B20',selection:(endColumn:45,endLineNumber:3,positionColumn:45,positionLineNumber:3,selectionStartColumn:45,selectionStartLineNumber:3,startColumn:45,startLineNumber:3),source:1,tree:'1'),l:'5',n:'0',o:'x86-64+clang+(assertions+trunk)+(C%2B%2B,+Editor+%231,+Compiler+%231)',t:'0')),k:33.333333333333336,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(compiler:1,editor:1,fontScale:14,fontUsePx:'0',tree:'1',wrap:'1'),l:'5',n:'0',o:'Output+of+x86-64+clang+(assertions+trunk)+(Compiler+%231)',t:'0')),k:33.33333333333333,l:'4',n:'0',o:'',s:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4

stack trace on Apple clang 13.1:

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000010
Exception Codes:       0x0000000000000001, 0x0000000000000010
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    Namespace SIGNAL, Code 11 Segmentation fault: 11
Terminating Process:   exc handler [26084]

VM Region Info: 0x10 is not in any region.  Bytes before following region: 4310499312
      REGION TYPE                    START - END         [ VSIZE] PRT/MAX SHRMOD  REGION DETAIL
      UNUSED SPACE AT START
--->  
      __TEXT                      100ed0000-104a28000    [ 59.3M] r-x/r-x SM=COW  ...usr/bin/clang

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   clang                         	       0x1024f55b0 (anonymous namespace)::CXXNameMangler::mangleValueInTemplateArg(clang::QualType, clang::APValue const&, bool, bool) + 4964
1   clang                         	       0x1024f559c (anonymous namespace)::CXXNameMangler::mangleValueInTemplateArg(clang::QualType, clang::APValue const&, bool, bool) + 4944
2   clang                         	       0x1024f4cac (anonymous namespace)::CXXNameMangler::mangleValueInTemplateArg(clang::QualType, clang::APValue const&, bool, bool) + 2656
3   clang                         	       0x103c6c6f8 (anonymous namespace)::CXXNameMangler::mangleTemplateArg(clang::TemplateArgument, bool) (.cold.2) + 68
4   clang                         	       0x1024f26a8 (anonymous namespace)::CXXNameMangler::mangleTemplateArg(clang::TemplateArgument, bool) + 820
5   clang                         	       0x1024ea0bc (anonymous namespace)::CXXNameMangler::mangleNameWithAbiTags(clang::GlobalDecl, llvm::SmallVector<llvm::StringRef, 4u> const*) + 960
6   clang                         	       0x1024e8c94 (anonymous namespace)::CXXNameMangler::mangleFunctionEncoding(clang::GlobalDecl) + 540
7   clang                         	       0x1024e7f38 (anonymous namespace)::ItaniumMangleContextImpl::mangleCXXName(clang::GlobalDecl, llvm::raw_ostream&) + 324
8   clang                         	       0x101a1c4cc getMangledNameImpl(clang::CodeGen::CodeGenModule&, clang::GlobalDecl, clang::NamedDecl const*, bool) + 216
9   clang                         	       0x101a19b34 clang::CodeGen::CodeGenModule::getMangledName(clang::GlobalDecl) + 372
10  clang                         	       0x101a22e3c clang::CodeGen::CodeGenModule::GetAddrOfFunction(clang::GlobalDecl, llvm::Type*, bool, bool, clang::CodeGen::ForDefinition_t) + 128
11  clang                         	       0x1019b6a20 clang::CodeGen::CodeGenModule::getRawFunctionPointer(clang::GlobalDecl, llvm::Type*) + 84
12  clang                         	       0x1019b9440 EmitDirectCallee(clang::CodeGen::CodeGenFunction&, clang::GlobalDecl) + 128
13  clang                         	       0x1019b80dc clang::CodeGen::CodeGenFunction::EmitCallExpr(clang::CallExpr const*, clang::CodeGen::ReturnValueSlot) + 140
14  clang                         	       0x1019d377c (anonymous namespace)::ScalarExprEmitter::VisitCallExpr(clang::CallExpr const*) + 124
15  clang                         	       0x1019c9df0 clang::CodeGen::CodeGenFunction::EmitScalarExpr(clang::Expr const*, bool) + 108
16  clang                         	       0x1019a9520 clang::CodeGen::CodeGenFunction::EmitIgnoredExpr(clang::Expr const*) + 96
17  clang                         	       0x1019fd9f0 clang::CodeGen::CodeGenFunction::EmitStmt(clang::Stmt const*, llvm::ArrayRef<clang::Attr const*>) + 252
18  clang                         	       0x101a053c8 clang::CodeGen::CodeGenFunction::EmitCompoundStmtWithoutScope(clang::CompoundStmt const&, bool, clang::CodeGen::AggValueSlot) + 156
19  clang                         	       0x101a14e88 clang::CodeGen::CodeGenFunction::EmitFunctionBody(clang::Stmt const*) + 128
20  clang                         	       0x101a155b4 clang::CodeGen::CodeGenFunction::GenerateCode(clang::GlobalDecl, llvm::Function*, clang::CodeGen::CGFunctionInfo const&) + 668
21  clang                         	       0x101a21f30 clang::CodeGen::CodeGenModule::EmitGlobalFunctionDefinition(clang::GlobalDecl, llvm::GlobalValue*) + 252
22  clang                         	       0x101a1f864 clang::CodeGen::CodeGenModule::EmitGlobalDefinition(clang::GlobalDecl, llvm::GlobalValue*) + 408
23  clang                         	       0x101a23718 clang::CodeGen::CodeGenModule::EmitTopLevelDecl(clang::Decl*) + 168
24  clang                         	       0x101a3e02c (anonymous namespace)::CodeGeneratorImpl::HandleTopLevelDecl(clang::DeclGroupRef) + 132
25  clang                         	       0x101a0edcc clang::BackendConsumer::HandleTopLevelDecl(clang::DeclGroupRef) + 144
26  clang                         	       0x1021155e4 clang::ParseAST(clang::Sema&, bool, bool) + 260
27  clang                         	       0x101af3a80 clang::FrontendAction::Execute() + 60
28  clang                         	       0x101aa3a6c clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) + 200
29  clang                         	       0x101b1757c clang::ExecuteCompilerInvocation(clang::CompilerInstance*) + 1212
30  clang                         	       0x100ed3f28 cc1_main(llvm::ArrayRef<char const*>, char const*, void*) + 868
31  clang                         	       0x100ed30f8 ExecuteCC1Tool(llvm::SmallVectorImpl<char const*>&) + 588
32  clang                         	       0x100ed2df0 driver_main(int, char const**) + 3396
33  clang                         	       0x100ed2050 main + 188
34  dyld                          	       0x106ee1088 start + 516


Thread 0 crashed with ARM Thread State (64-bit):
    x0: 0x000000016ef281f0   x1: 0x0000000104759174   x2: 0x0000000000000000   x3: 0x000000016ef28273
    x4: 0x0000000000000000   x5: 0x0000000000000000   x6: 0x0000000000000069   x7: 0x000000016ef272f8
    x8: 0x0000000000000000   x9: 0x0000000000000000  x10: 0x0000000000000056  x11: 0x0000000156117f68
   x12: 0x0000000000000017  x13: 0xffffffffffffffff  x14: 0x0000000000000002  x15: 0x0000000000000002
   x16: 0x0000000194f950f0  x17: 0x00000000000008fd  x18: 0x0000000000000000  x19: 0x000000016ef28058
   x20: 0x0000000000000000  x21: 0x0000600002dc2110  x22: 0x0000000156117e50  x23: 0x0000000000000000
   x24: 0x0000000156118130  x25: 0x0000000000000048  x26: 0x0000000156043638  x27: 0x000000016ef27f08
   x28: 0x0000014900000099   fp: 0x000000016ef279c0   lr: 0x00000001024f559c
    sp: 0x000000016ef278c0   pc: 0x00000001024f55b0 cpsr: 0x40001000
   far: 0x0000000000000010  esr: 0x92000006 (Data Abort) byte read Translation fault

Binary Images:
       0x100ed0000 -        0x104a27fff clang (*) <f008b3b7-3624-3988-9818-6e2cc0141603> /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
       0x106edc000 -        0x106f3bfff dyld (*) <fbb89662-e6f2-3434-b542-f75185ac5e74> /usr/lib/dyld
               0x0 - 0xffffffffffffffff ??? (*) <00000000-0000-0000-0000-000000000000> ???
@EugeneZelenko EugeneZelenko added clang:codegen crash Prefer [crash-on-valid] or [crash-on-invalid] and removed new issue labels Mar 27, 2022
@llvmbot
Copy link
Collaborator

llvmbot commented Mar 27, 2022

@llvm/issue-subscribers-clang-codegen

@erichkeane
Copy link
Collaborator

@rjmccall @zygoloid :

The problem ends up being creating the initializer for the 'struct' field inside the union. The 'braced-expression' initialization here: https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.braced-expression
shows I think that we should be using the .name =expr version (which we do!). However, the problem is that this is unnamed, and thus crashes (since IdentifierInfo is null!).

I see that GCC has this same problem, so I suspect this might be an issue with the Itanium ABI.

Note that if I change the struct to have a field-name (FOO), we get:
_Z5dummyIXtl7wrapperIiEtlNS1_Ut_Edi3FOOtlNS2_Ut_ELi42EEEEEEiv
which demangles to :
int dummy<wrapper<int>{wrapper<int>::'unnamed'{.FOO = wrapper<int>::'unnamed'::'unnamed'{42}}}>()

I'll post an issue on the Itanium ABI github to see if they can guide the right solution here.

@rjmccall
Copy link
Contributor

We probably ought to just ignore anonymous members for the purposes of this mangling. You can't have a conflict in the enclosing scope between member names of different anonymous aggregates.

@erichkeane
Copy link
Collaborator

Sorry, I'm not getting what you mean? Are you saying if the 'union' has an unnamed-initialized-field, it should decompose the 'inner' type? So you'd expect it to be something more like:
int dummy<wrapper<int>{wrapper<int>::'unnamed'{Val = int{42}}}>()

This I think ends up being pretty awkward/weird (though perhaps implementable?) when you have a number of initialization at diferent levels. So you'd have something like:

template<typename T>
struct wrapper {
  union {
    struct {
        T Val;
        struct { T Val, T Val2} ;
    }
 }
}

with:
int dummy<wrapper<int>{wrapper<int>::'unnamed'{Val = int{42}, Val = int{43}, Val = int{44}}}>()
(or some similiar, though perhaps more clever issue?)

@rjmccall
Copy link
Contributor

Since this is primarily an Itanium ABI issue, let's focus the conversation there.

@erichkeane
Copy link
Collaborator

Discussion on the Itanium ABI gave me sufficient info to implement: https://reviews.llvm.org/D122820

erichkeane pushed a commit that referenced this issue Apr 1, 2022
As reported in #54588
and discussed in itanium-cxx-abi/cxx-abi#139

We are supposed to do a DFS, pre-order, decl-order search for a name for
the union in this case. Prevoiusly we crashed because the IdentiferInfo
pointer was nullptr, so this makes sure we have a name in the cases
described by the ABI.

I added an llvm-unreachable to cover an unexpected case at the end of
the new function with information/reference to the ABI in case we come
up with some way to get back to here.

Differential Revision: https://reviews.llvm.org/D122820
@erichkeane
Copy link
Collaborator

Fixed here: https://reviews.llvm.org/rG4cf98f973a13c5049322abff43f0dff3c214311b

Thank you very much for your help/patience on this one @rjmccall !

mem-frob pushed a commit to draperlaboratory/hope-llvm-project that referenced this issue Oct 7, 2022
As reported in llvm/llvm-project#54588
and discussed in itanium-cxx-abi/cxx-abi#139

We are supposed to do a DFS, pre-order, decl-order search for a name for
the union in this case. Prevoiusly we crashed because the IdentiferInfo
pointer was nullptr, so this makes sure we have a name in the cases
described by the ABI.

I added an llvm-unreachable to cover an unexpected case at the end of
the new function with information/reference to the ABI in case we come
up with some way to get back to here.

Differential Revision: https://reviews.llvm.org/D122820
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen crash Prefer [crash-on-valid] or [crash-on-invalid]
Projects
None yet
Development

No branches or pull requests

5 participants