Author: vsapsai Date: Mon Jan 22 14:29:24 2018 New Revision: 323156 URL: http://llvm.org/viewvc/llvm-project?rev=323156&view=rev Log: Reland "[CodeGen] Fix crash when a function taking transparent union is redeclared."
When a function taking transparent union is declared as taking one of union members earlier in the translation unit, clang would hit an "Invalid cast" assertion during EmitFunctionProlog. This case corresponds to function f1 in test/CodeGen/transparent-union-redecl.c. We decided to cast i32 to union because after merging function declarations function parameter type becomes int, CGFunctionInfo::ArgInfo type matches with ABIArgInfo type, so we decide it is a trivial case. But these types should also be castable to parameter declaration type which is not the case here. Now the fix is in converting from ABIArgInfo type to VarDecl type and using argument demotion when necessary. Additional tests in Sema/transparent-union.c capture current behavior and make sure there are no regressions. rdar://problem/34949329 Reviewers: rjmccall, rafael Reviewed By: rjmccall Subscribers: aemerson, cfe-commits, kristof.beyls, ahatanak Differential Revision: https://reviews.llvm.org/D41311 Added: cfe/trunk/test/CodeGen/transparent-union-redecl.c Modified: cfe/trunk/lib/CodeGen/CGCall.cpp cfe/trunk/test/CodeGen/kr-func-promote.c cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp cfe/trunk/test/Sema/transparent-union.c Modified: cfe/trunk/lib/CodeGen/CGCall.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=323156&r1=323155&r2=323156&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGCall.cpp (original) +++ cfe/trunk/lib/CodeGen/CGCall.cpp Mon Jan 22 14:29:24 2018 @@ -2251,11 +2251,16 @@ void CodeGenFunction::EmitFunctionProlog for (FunctionArgList::const_iterator i = Args.begin(), e = Args.end(); i != e; ++i, ++info_it, ++ArgNo) { const VarDecl *Arg = *i; - QualType Ty = info_it->type; const ABIArgInfo &ArgI = info_it->info; bool isPromoted = isa<ParmVarDecl>(Arg) && cast<ParmVarDecl>(Arg)->isKNRPromoted(); + // We are converting from ABIArgInfo type to VarDecl type directly, unless + // the parameter is promoted. In this case we convert to + // CGFunctionInfo::ArgInfo type with subsequent argument demotion. + QualType Ty = isPromoted ? info_it->type : Arg->getType(); + assert(hasScalarEvaluationKind(Ty) == + hasScalarEvaluationKind(Arg->getType())); unsigned FirstIRArg, NumIRArgs; std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); Modified: cfe/trunk/test/CodeGen/kr-func-promote.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/kr-func-promote.c?rev=323156&r1=323155&r2=323156&view=diff ============================================================================== --- cfe/trunk/test/CodeGen/kr-func-promote.c (original) +++ cfe/trunk/test/CodeGen/kr-func-promote.c Mon Jan 22 14:29:24 2018 @@ -1,6 +1,12 @@ // RUN: %clang_cc1 -triple i386-unknown-unknown %s -emit-llvm -o - | FileCheck %s -// CHECK: i32 @a(i32) +// CHECK: i32 @a(i32 int a(); int a(x) short x; {return x;} +// CHECK: void @b(double +// CHECK: %[[ADDR:.*]] = alloca float, align 4 +// CHECK: %[[TRUNC:.*]] = fptrunc double %0 to float +// CHECK: store float %[[TRUNC]], float* %[[ADDR]], align 4 +void b(); +void b(f) float f; {} Added: cfe/trunk/test/CodeGen/transparent-union-redecl.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/transparent-union-redecl.c?rev=323156&view=auto ============================================================================== --- cfe/trunk/test/CodeGen/transparent-union-redecl.c (added) +++ cfe/trunk/test/CodeGen/transparent-union-redecl.c Mon Jan 22 14:29:24 2018 @@ -0,0 +1,44 @@ +// RUN: %clang_cc1 -Werror -triple i386-linux -emit-llvm -o - %s | FileCheck %s + +// Test that different order of declarations is acceptable and that +// implementing different redeclarations is acceptable. +// rdar://problem/34949329 + +typedef union { + int i; + float f; +} TU __attribute__((transparent_union)); + +// CHECK-LABEL: define void @f0(i32 %tu.coerce) +// CHECK: %tu = alloca %union.TU, align 4 +// CHECK: %coerce.dive = getelementptr inbounds %union.TU, %union.TU* %tu, i32 0, i32 0 +// CHECK: store i32 %tu.coerce, i32* %coerce.dive, align 4 +void f0(TU tu) {} +void f0(int i); + +// CHECK-LABEL: define void @f1(i32 %tu.coerce) +// CHECK: %tu = alloca %union.TU, align 4 +// CHECK: %coerce.dive = getelementptr inbounds %union.TU, %union.TU* %tu, i32 0, i32 0 +// CHECK: store i32 %tu.coerce, i32* %coerce.dive, align 4 +void f1(int i); +void f1(TU tu) {} + +// CHECK-LABEL: define void @f2(i32 %i) +// CHECK: %i.addr = alloca i32, align 4 +// CHECK: store i32 %i, i32* %i.addr, align 4 +void f2(TU tu); +void f2(int i) {} + +// CHECK-LABEL: define void @f3(i32 %i) +// CHECK: %i.addr = alloca i32, align 4 +// CHECK: store i32 %i, i32* %i.addr, align 4 +void f3(int i) {} +void f3(TU tu); + +// Also test functions with parameters specified K&R style. +// CHECK-LABEL: define void @knrStyle(i32 %tu.coerce) +// CHECK: %tu = alloca %union.TU, align 4 +// CHECK: %coerce.dive = getelementptr inbounds %union.TU, %union.TU* %tu, i32 0, i32 0 +// CHECK: store i32 %tu.coerce, i32* %coerce.dive, align 4 +void knrStyle(int i); +void knrStyle(tu) TU tu; {} Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp?rev=323156&r1=323155&r2=323156&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp (original) +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-multiple-nonvirtual-inheritance.cpp Mon Jan 22 14:29:24 2018 @@ -88,8 +88,11 @@ void ChildOverride::right() { // ChildOverride::right gets 'this' cast to Right* in ECX (i.e. this+4) so we // need to adjust 'this' before use. // +// CHECK: %[[THIS_STORE:.*]] = alloca %struct.ChildOverride*, align 4 // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.ChildOverride*, align 4 -// CHECK: %[[THIS_INIT:.*]] = bitcast i8* %[[ECX:.*]] to %struct.ChildOverride* +// CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %[[ECX:.*]] to %struct.ChildOverride* +// CHECK: store %struct.ChildOverride* %[[COERCE_VAL]], %struct.ChildOverride** %[[THIS_STORE]], align 4 +// CHECK: %[[THIS_INIT:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_STORE]], align 4 // CHECK: store %struct.ChildOverride* %[[THIS_INIT]], %struct.ChildOverride** %[[THIS_ADDR]], align 4 // CHECK: %[[THIS_RELOAD:.*]] = load %struct.ChildOverride*, %struct.ChildOverride** %[[THIS_ADDR]] // CHECK: %[[THIS_i8:.*]] = bitcast %struct.ChildOverride* %[[THIS_RELOAD]] to i8* @@ -132,8 +135,11 @@ struct GrandchildOverride : ChildOverrid void GrandchildOverride::right() { // CHECK-LABEL: define x86_thiscallcc void @"\01?right@GrandchildOverride@@UAEXXZ"(i8* // +// CHECK: %[[THIS_STORE:.*]] = alloca %struct.GrandchildOverride*, align 4 // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.GrandchildOverride*, align 4 -// CHECK: %[[THIS_INIT:.*]] = bitcast i8* %[[ECX:.*]] to %struct.GrandchildOverride* +// CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %[[ECX:.*]] to %struct.GrandchildOverride* +// CHECK: store %struct.GrandchildOverride* %[[COERCE_VAL]], %struct.GrandchildOverride** %[[THIS_STORE]], align 4 +// CHECK: %[[THIS_INIT:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_STORE]], align 4 // CHECK: store %struct.GrandchildOverride* %[[THIS_INIT]], %struct.GrandchildOverride** %[[THIS_ADDR]], align 4 // CHECK: %[[THIS_RELOAD:.*]] = load %struct.GrandchildOverride*, %struct.GrandchildOverride** %[[THIS_ADDR]] // CHECK: %[[THIS_i8:.*]] = bitcast %struct.GrandchildOverride* %[[THIS_RELOAD]] to i8* Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp?rev=323156&r1=323155&r2=323156&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp (original) +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance-vtordisps.cpp Mon Jan 22 14:29:24 2018 @@ -25,6 +25,7 @@ D::D() {} // Forces vftable emission. // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPM@A@AEXXZ" // Note that the vtordisp is applied before really adjusting to D*. +// CHECK: %[[COERCE_LOAD:.*]] = load %struct.D*, %struct.D** %{{.*}} // CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4 @@ -36,6 +37,7 @@ D::D() {} // Forces vftable emission. // CHECK: ret void // CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@D@@$4PPPPPPPI@3AEXXZ" +// CHECK: %[[COERCE_LOAD:.*]] = load %struct.D*, %struct.D** %{{.*}} // CHECK: %[[ECX:.*]] = load %struct.D*, %struct.D** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.D* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -8 @@ -64,7 +66,8 @@ struct G : virtual F, virtual E { G::G() {} // Forces vftable emission. -// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8*) +// CHECK-LABEL: define linkonce_odr x86_thiscallcc void @"\01?f@E@@$R4BA@M@PPPPPPPM@7AEXXZ"(i8* +// CHECK: %[[COERCE_LOAD:.*]] = load %struct.E*, %struct.E** %{{.*}} // CHECK: %[[ECX:.*]] = load %struct.E*, %struct.E** %{{.*}} // CHECK: %[[ECX_i8:.*]] = bitcast %struct.E* %[[ECX]] to i8* // CHECK: %[[VTORDISP_PTR_i8:.*]] = getelementptr inbounds i8, i8* %[[ECX_i8]], i32 -4 Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp?rev=323156&r1=323155&r2=323156&view=diff ============================================================================== --- cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp (original) +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp Mon Jan 22 14:29:24 2018 @@ -115,9 +115,15 @@ void B::foo() { // B::foo gets 'this' cast to VBase* in ECX (i.e. this+8) so we // need to adjust 'this' before use. // -// Store initial this: +// Coerce this to correct type: +// CHECK: %[[THIS_STORE:.*]] = alloca %struct.B* // CHECK: %[[THIS_ADDR:.*]] = alloca %struct.B* -// CHECK: store %struct.B* %{{.*}}, %struct.B** %[[THIS_ADDR]], align 4 +// CHECK: %[[COERCE_VAL:.*]] = bitcast i8* %{{.*}} to %struct.B* +// CHECK: store %struct.B* %[[COERCE_VAL]], %struct.B** %[[THIS_STORE]], align 4 +// +// Store initial this: +// CHECK: %[[THIS_INIT:.*]] = load %struct.B*, %struct.B** %[[THIS_STORE]] +// CHECK: store %struct.B* %[[THIS_INIT]], %struct.B** %[[THIS_ADDR]], align 4 // // Reload and adjust the this parameter: // CHECK: %[[THIS_RELOAD:.*]] = load %struct.B*, %struct.B** %[[THIS_ADDR]] Modified: cfe/trunk/test/Sema/transparent-union.c URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/transparent-union.c?rev=323156&r1=323155&r2=323156&view=diff ============================================================================== --- cfe/trunk/test/Sema/transparent-union.c (original) +++ cfe/trunk/test/Sema/transparent-union.c Mon Jan 22 14:29:24 2018 @@ -43,6 +43,35 @@ void fi(int i) {} // expected-error{{con void fvpp(TU); // expected-note{{previous declaration is here}} void fvpp(void **v) {} // expected-error{{conflicting types}} +/* Test redeclaring a function taking a transparent_union arg more than twice. + Merging different declarations depends on their order, vary order too. */ + +void f_triple0(TU tu) {} +void f_triple0(int *); // expected-note{{previous declaration is here}} +void f_triple0(float *f); // expected-error{{conflicting types}} + +void f_triple1(int *); +void f_triple1(TU tu) {} // expected-note{{previous definition is here}} +void f_triple1(float *f); // expected-error{{conflicting types}} + +void f_triple2(int *); // expected-note{{previous declaration is here}} +void f_triple2(float *f); // expected-error{{conflicting types}} +void f_triple2(TU tu) {} + +/* Test calling redeclared function taking a transparent_union arg. */ + +void f_callee(TU); +void f_callee(int *i) {} // expected-note{{passing argument to parameter 'i' here}} + +void caller(void) { + TU tu; + f_callee(tu); // expected-error{{passing 'TU' to parameter of incompatible type 'int *'}} + + int *i; + f_callee(i); +} + + /* FIXME: we'd like to just use an "int" here and align it differently from the normal "int", but if we do so we lose the alignment information from the typedef within the compiler. */ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits