From 09d6ee765780837d5156ac81f968465bdcec73ba Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 9 Jun 2023 09:57:21 +0200 Subject: [PATCH] [Clang] Directly create opaque pointers In CGTypes, directly create opaque pointers, without computing the LLVM element type. This is not as straightforward as I though it would be, because apparently computing the LLVM type also causes a number of side effects. In particular, we no longer produce diagnostics like -Wpacked for typed (only) behind pointers, because we no longer depend on their layout. Differential Revision: https://reviews.llvm.org/D152505 --- clang/lib/CodeGen/CodeGenTypes.cpp | 25 ++---- .../test/CodeGenCXX/matrix-type-builtins.cpp | 10 +-- .../warn-all-padded-packed-packed-non-pod.cpp | 6 +- clang/test/Modules/compare-record.c | 5 +- clang/test/PCH/headersearch.cpp | 2 +- clang/test/Sema/ms_class_layout.cpp | 90 ++++++++----------- 6 files changed, 55 insertions(+), 83 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenTypes.cpp b/clang/lib/CodeGen/CodeGenTypes.cpp index 0ceab41cdd36..e4836c850a15 100644 --- a/clang/lib/CodeGen/CodeGenTypes.cpp +++ b/clang/lib/CodeGen/CodeGenTypes.cpp @@ -675,19 +675,15 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { case Type::RValueReference: { const ReferenceType *RTy = cast(Ty); QualType ETy = RTy->getPointeeType(); - llvm::Type *PointeeType = ConvertTypeForMem(ETy); unsigned AS = getTargetAddressSpace(ETy); - ResultType = llvm::PointerType::get(PointeeType, AS); + ResultType = llvm::PointerType::get(getLLVMContext(), AS); break; } case Type::Pointer: { const PointerType *PTy = cast(Ty); QualType ETy = PTy->getPointeeType(); - llvm::Type *PointeeType = ConvertTypeForMem(ETy); - if (PointeeType->isVoidTy()) - PointeeType = llvm::Type::getInt8Ty(getLLVMContext()); unsigned AS = getTargetAddressSpace(ETy); - ResultType = llvm::PointerType::get(PointeeType, AS); + ResultType = llvm::PointerType::get(getLLVMContext(), AS); break; } @@ -764,15 +760,9 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { break; } - case Type::ObjCObjectPointer: { - // Protocol qualifications do not influence the LLVM type, we just return a - // pointer to the underlying interface type. We don't need to worry about - // recursive conversion. - llvm::Type *T = - ConvertTypeForMem(cast(Ty)->getPointeeType()); - ResultType = T->getPointerTo(); + case Type::ObjCObjectPointer: + ResultType = llvm::PointerType::getUnqual(getLLVMContext()); break; - } case Type::Enum: { const EnumDecl *ED = cast(Ty)->getDecl(); @@ -786,18 +776,15 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) { } case Type::BlockPointer: { - const QualType FTy = cast(Ty)->getPointeeType(); - llvm::Type *PointeeType = CGM.getLangOpts().OpenCL - ? CGM.getGenericBlockLiteralType() - : ConvertTypeForMem(FTy); // Block pointers lower to function type. For function type, // getTargetAddressSpace() returns default address space for // function pointer i.e. program address space. Therefore, for block // pointers, it is important to pass the pointee AST address space when // calling getTargetAddressSpace(), to ensure that we get the LLVM IR // address space for data pointers and not function pointers. + const QualType FTy = cast(Ty)->getPointeeType(); unsigned AS = Context.getTargetAddressSpace(FTy.getAddressSpace()); - ResultType = llvm::PointerType::get(PointeeType, AS); + ResultType = llvm::PointerType::get(getLLVMContext(), AS); break; } diff --git a/clang/test/CodeGenCXX/matrix-type-builtins.cpp b/clang/test/CodeGenCXX/matrix-type-builtins.cpp index 24bf797ab94a..732fe1a18db3 100644 --- a/clang/test/CodeGenCXX/matrix-type-builtins.cpp +++ b/clang/test/CodeGenCXX/matrix-type-builtins.cpp @@ -31,20 +31,20 @@ void test_transpose_template1() { void test_transpose_template2(MyMatrix &M) { // CHECK-LABEL: define{{.*}} void @_Z24test_transpose_template2R8MyMatrixIdLj7ELj6EE( - // CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.2) align 8 %ref.tmp1, ptr noundef nonnull align 8 dereferenceable(336) %0) - // CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.1) align 8 %ref.tmp, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp1) - // CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.2) align 8 %M2_t, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp) + // CHECK: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.1) align 8 %ref.tmp1, ptr noundef nonnull align 8 dereferenceable(336) %0) + // CHECK-NEXT: call void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.2) align 8 %ref.tmp, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp1) + // CHECK-NEXT: call void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE(ptr sret(%struct.MyMatrix.1) align 8 %M2_t, ptr noundef nonnull align 8 dereferenceable(336) %ref.tmp) // CHECK-LABEL: define linkonce_odr void @_Z9transposeIdLj7ELj6EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE( // CHECK: [[M:%.*]] = load <42 x double>, ptr {{.*}}, align 8 // CHECK-NEXT: [[M_T:%.*]] = call <42 x double> @llvm.matrix.transpose.v42f64(<42 x double> [[M]], i32 7, i32 6) - // CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.2, ptr %agg.result, i32 0, i32 0 + // CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.1, ptr %agg.result, i32 0, i32 0 // CHECK-NEXT: store <42 x double> [[M_T]], ptr [[RES_ADDR]], align 8 // CHECK-LABEL: define linkonce_odr void @_Z9transposeIdLj6ELj7EE8MyMatrixIT_XT1_EXT0_EERKS0_IS1_XT0_EXT1_EE( // CHECK: [[M:%.*]] = load <42 x double>, ptr {{.*}}, align 8 // CHECK-NEXT: [[M_T:%.*]] = call <42 x double> @llvm.matrix.transpose.v42f64(<42 x double> [[M]], i32 6, i32 7) - // CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.1, ptr %agg.result, i32 0, i32 0 + // CHECK-NEXT: [[RES_ADDR:%.*]] = getelementptr inbounds %struct.MyMatrix.2, ptr %agg.result, i32 0, i32 0 // CHECK-NEXT: store <42 x double> [[M_T]], ptr [[RES_ADDR]], align 8 MyMatrix M2_t = transpose(transpose(transpose(M))); diff --git a/clang/test/CodeGenCXX/warn-all-padded-packed-packed-non-pod.cpp b/clang/test/CodeGenCXX/warn-all-padded-packed-packed-non-pod.cpp index 5402e21e3a5b..2a75498d8719 100644 --- a/clang/test/CodeGenCXX/warn-all-padded-packed-packed-non-pod.cpp +++ b/clang/test/CodeGenCXX/warn-all-padded-packed-packed-non-pod.cpp @@ -184,6 +184,6 @@ struct S30_use { // abi15-warning {{packed attribute is unnecessary for 'S30_use static_assert(sizeof(S30_use) == 3, ""); // The warnings are emitted when the layout of the structs is computed, so we have to use them. -void f(S1*, S2*, S3*, S4*, S5*, S6*, S7*, S8*, S9*, S10*, S11*, S12*, S13*, - S14*, S15*, S16*, S17*, S18*, S19*, S20*, S21*, S22*, S23*, S24*, S25*, - S26*, S27*, S28*, S29*){} +void f(S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, + S14, S15, S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, + S26, S27, S28, S29){} diff --git a/clang/test/Modules/compare-record.c b/clang/test/Modules/compare-record.c index a07843341296..c5ce285aa77e 100644 --- a/clang/test/Modules/compare-record.c +++ b/clang/test/Modules/compare-record.c @@ -423,9 +423,10 @@ struct CompareDifferentFieldInIndirectStruct compareIndirectStruct; // expected-error@second-nested-struct.h:* {{'IndirectStruct::mismatchingField' from module 'Second' is not present in definition of 'struct IndirectStruct' in module 'First.Hidden'}} // expected-note@first-nested-struct.h:* {{declaration of 'mismatchingField' does not match}} #elif defined(CASE3) +// This currently doesn't produce an error, because there is no dependency +// on the layout of DirectStruct. +// expected-no-diagnostics struct CompareIndirectStructPointer compareIndirectStructPointer; -// expected-error@second-nested-struct.h:* {{'IndirectStruct::mismatchingField' from module 'Second' is not present in definition of 'struct IndirectStruct' in module 'First.Hidden'}} -// expected-note@first-nested-struct.h:* {{declaration of 'mismatchingField' does not match}} #endif //--- include/first-anonymous.h diff --git a/clang/test/PCH/headersearch.cpp b/clang/test/PCH/headersearch.cpp index 3d16c3335341..f089bfd9ed1d 100644 --- a/clang/test/PCH/headersearch.cpp +++ b/clang/test/PCH/headersearch.cpp @@ -33,7 +33,7 @@ // RUN: not %clang_cc1 -triple %itanium_abi_triple -DINSTANTIATION -include-pch all.h.pch -I%t_moved -I%t_moved/sub2 -emit-llvm-only %s 2> %t.stderr // RUN: grep 'orig_sub2_1' %t.stderr -void qq(orig_sub*) {all();} +void qq(orig_sub) {all();} #ifdef REDECL float foo() {return 0;} diff --git a/clang/test/Sema/ms_class_layout.cpp b/clang/test/Sema/ms_class_layout.cpp index cd0f04abd139..73382a480f50 100644 --- a/clang/test/Sema/ms_class_layout.cpp +++ b/clang/test/Sema/ms_class_layout.cpp @@ -147,16 +147,16 @@ int main() { // This avoid "Can't yet mangle constructors!" for MS ABI. C* c; c->foo(); - DerivedStruct* v; - H* g; + DerivedStruct v; + H g; BaseStruct* u; - I* i; - N* n; - O* o; - P* p; - R* r; - sd *h; - EV *j; + I i; + N n; + O o; + P p; + R r; + sd h; + EV j; return 0; } @@ -206,15 +206,6 @@ int main() { // CHECK-NEXT: sizeof=80, align=8 // CHECK-NEXT: nvsize=64, nvalign=8 -// CHECK: %class.D = type { ptr, double } - -// CHECK: %class.B = type { ptr, i32 } - -// CHECK: %class.A = type { %class.B, i32, i8 } - -// CHECK: %class.C = type { %class.D, %class.B, ptr, double, i32, double, i32, [4 x i8], %class.A } -// CHECK: %class.C.base = type { %class.D, %class.B, ptr, double, i32, double, i32 } - // CHECK-LABEL: 0 | struct BaseStruct{{$}} // CHECK-NEXT: 0 | double v0 // CHECK-NEXT: 8 | float v1 @@ -239,8 +230,6 @@ int main() { // CHECK-NEXT: sizeof=96, align=8 // CHECK-NEXT: nvsize=96, nvalign=8 -// CHECK: %struct.BaseStruct = type { double, float, %class.C } - // CHECK-LABEL: 0 | struct DerivedStruct{{$}} // CHECK-NEXT: 0 | struct BaseStruct (base) // CHECK-NEXT: 0 | double v0 @@ -267,8 +256,6 @@ int main() { // CHECK-NEXT: sizeof=104, align=8 // CHECK-NEXT: nvsize=104, nvalign=8 -// CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 } - // CHECK-LABEL:0 | struct G // CHECK-NEXT: 0 | int g_field // CHECK-NEXT: sizeof=4, align=4 @@ -284,8 +271,6 @@ int main() { // CHECK-NEXT: sizeof=24, align=8 // CHECK-NEXT: nvsize=8, nvalign=8 -// CHECK: %struct.H = type { %struct.G, ptr, %class.D } - // CHECK-LABEL: 0 | struct I{{$}} // CHECK-NEXT: 0 | (I vftable pointer) // CHECK-NEXT: 8 | (I vbtable pointer) @@ -296,9 +281,6 @@ int main() { // CHECK-NEXT: sizeof=40, align=8 // CHECK-NEXT: nvsize=24, nvalign=8 -// CHECK: %struct.I = type { ptr, [4 x i8], ptr, double, %class.D } -// CHECK: %struct.I.base = type { ptr, [4 x i8], ptr, double } - // CHECK-LABEL: 0 | struct L{{$}} // CHECK-NEXT: 0 | int l // CHECK-NEXT: sizeof=4, align=4 @@ -316,9 +298,6 @@ int main() { // CHECK-NEXT: 8 | int k // CHECK-NEXT: sizeof=12, align=4 -//CHECK: %struct.M = type { ptr, i32, %struct.K } -//CHECK: %struct.M.base = type { ptr, i32 } - // CHECK-LABEL: 0 | struct N{{$}} // CHECK-NEXT: 0 | (N vftable pointer) // CHECK-NEXT: 4 | struct L (base) @@ -331,8 +310,6 @@ int main() { // CHECK-NEXT: sizeof=20, align=4 // CHECK-NEXT: nvsize=16, nvalign=4 -//CHECK: %struct.N = type { ptr, %struct.L, %struct.M.base, %struct.K } - // CHECK-LABEL: 0 | struct O{{$}} // CHECK-NEXT: 0 | (O vftable pointer) // CHECK-NEXT: 8 | struct H (base) @@ -347,9 +324,6 @@ int main() { // CHECK-NEXT: | [sizeof=40, align=8 // CHECK-NEXT: | nvsize=24, nvalign=8] -// CHECK: struct.O = type { ptr, [4 x i8], %struct.H.base, %struct.G, %class.D } -// CHECK: struct.O.base = type { ptr, [4 x i8], %struct.H.base, %struct.G, [4 x i8] } - // CHECK-LABEL: 0 | struct P{{$}} // CHECK-NEXT: 0 | struct M (base) // CHECK-NEXT: 0 | (M vbtable pointer) @@ -362,14 +336,10 @@ int main() { // CHECK-NEXT: sizeof=20, align=4 // CHECK-NEXT: nvsize=12, nvalign=4 -//CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L } - // CHECK-LABEL: 0 | struct R (empty){{$}} // CHECK-NEXT: sizeof=1, align=1 // CHECK-NEXT: nvsize=0, nvalign=1 -//CHECK: %struct.R = type { i8 } - // CHECK-LABEL: 0 | struct f{{$}} // CHECK-NEXT: 0 | (f vftable pointer) // CHECK-NEXT: sizeof=4, align=4 @@ -419,12 +389,6 @@ int main() { // CHECK-NEXT: sizeof=48, align=4 // CHECK-NEXT: nvsize=12, nvalign=4 -// CHECK: %struct.f = type { ptr } -// CHECK: %struct.s = type { ptr, ptr, i32, i32, %struct.f } -// CHECK: %class.IA = type { ptr } -// CHECK: %class.ICh = type { ptr, ptr, i32, %class.IA } -// CHECK: %struct.sd = type { ptr, i32, i8, i32, %struct.f, %struct.s.base, i32, %class.IA, %class.ICh.base } - // CHECK-LABEL: 0 | struct AV{{$}} // CHECK-NEXT: 0 | (AV vftable pointer) // CHECK-NEXT: sizeof=4, align=4 @@ -445,11 +409,6 @@ int main() { // CHECK-NEXT: sizeof=12, align=4 // CHECK-NEXT: nvsize=4, nvalign=4 -// CHECK: %struct.AV = type { ptr } -// CHECK: %struct.BV = type { %struct.AV } -// CHECK: %struct.CV = type { ptr, i32, %struct.BV } -// CHECK: %struct.CV.base = type { ptr } - // CHECK-LABEL: 0 | struct DV{{$}} // CHECK-NEXT: 0 | struct BV (primary base) // CHECK-NEXT: 0 | struct AV (primary base) @@ -457,8 +416,6 @@ int main() { // CHECK-NEXT: sizeof=4, align=4 // CHECK-NEXT: nvsize=4, nvalign=4 -// CHECK: %struct.DV = type { %struct.BV } - // CHECK-LABEL: 0 | struct EV{{$}} // CHECK-NEXT: 0 | struct DV (primary base) // CHECK-NEXT: 0 | struct BV (primary base) @@ -473,6 +430,33 @@ int main() { // CHECK-NEXT: sizeof=16, align=4 // CHECK-NEXT: nvsize=8, nvalign=4 +// CHECK: %class.D = type { ptr, double } +// CHECK: %class.B = type { ptr, i32 } +// CHECK: %class.A = type { %class.B, i32, i8 } +// CHECK: %class.C = type { %class.D, %class.B, ptr, double, i32, double, i32, [4 x i8], %class.A } +// CHECK: %class.C.base = type { %class.D, %class.B, ptr, double, i32, double, i32 } +// CHECK: %struct.BaseStruct = type { double, float, %class.C } +// CHECK: %struct.DerivedStruct = type { %struct.BaseStruct, i32 } +// CHECK: %struct.H = type { %struct.G, ptr, %class.D } +// CHECK: %struct.I = type { ptr, [4 x i8], ptr, double, %class.D } +// CHECK: %struct.I.base = type { ptr, [4 x i8], ptr, double } +// CHECK: %struct.M = type { ptr, i32, %struct.K } +// CHECK: %struct.M.base = type { ptr, i32 } +// CHECK: %struct.N = type { ptr, %struct.L, %struct.M.base, %struct.K } +// CHECK: %struct.O = type { ptr, [4 x i8], %struct.H.base, %struct.G, %class.D } +// CHECK: %struct.O.base = type { ptr, [4 x i8], %struct.H.base, %struct.G, [4 x i8] } +// CHECK: %struct.P = type { %struct.M.base, i32, %struct.K, %struct.L } +// CHECK: %struct.R = type { i8 } +// CHECK: %struct.f = type { ptr } +// CHECK: %struct.s = type { ptr, ptr, i32, i32, %struct.f } +// CHECK: %class.IA = type { ptr } +// CHECK: %class.ICh = type { ptr, ptr, i32, %class.IA } +// CHECK: %struct.sd = type { ptr, i32, i8, i32, %struct.f, %struct.s.base, i32, %class.IA, %class.ICh.base } +// CHECK: %struct.AV = type { ptr } +// CHECK: %struct.BV = type { %struct.AV } +// CHECK: %struct.CV = type { ptr, i32, %struct.BV } +// CHECK: %struct.CV.base = type { ptr } +// CHECK: %struct.DV = type { %struct.BV } // CHECK: %struct.EV = type { %struct.DV, %struct.CV.base, i32, %struct.BV } // CHECK: %struct.EV.base = type { %struct.DV, %struct.CV.base } @@ -482,7 +466,7 @@ namespace test1 { struct A { virtual void foo(); }; struct B : A {}; struct C : virtual A, virtual B { C(); virtual void foo(); }; - void test() { C *c; } + void test() { C c; } // CHECK-LABEL: 0 | struct test1::C{{$}} // CHECK-NEXT: 0 | (C vbtable pointer)