[clang] 5b3247b - [tbaa] Handle base classes in struct tbaa
Author: Bruno De Fraine Date: 2022-07-06T14:37:59+02:00 New Revision: 5b3247bf9f715cc1b399af1e17540b3a3ce9cdec URL: https://github.com/llvm/llvm-project/commit/5b3247bf9f715cc1b399af1e17540b3a3ce9cdec DIFF: https://github.com/llvm/llvm-project/commit/5b3247bf9f715cc1b399af1e17540b3a3ce9cdec.diff LOG: [tbaa] Handle base classes in struct tbaa This is a fix for the miscompilation reported in https://github.com/llvm/llvm-project/issues/55384 Not adding a new test case since existing test cases already cover base classes (including new-struct-path tbaa). Reviewed By: jeroen.dobbelaere Differential Revision: https://reviews.llvm.org/D126956 Added: Modified: clang/lib/CodeGen/CodeGenTBAA.cpp clang/test/CodeGen/tbaa-class.cpp clang/unittests/CodeGen/TBAAMetadataTest.cpp Removed: diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 95763d8e18b70..0cb63fbbe9e5c 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -335,7 +335,42 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) { if (auto *TTy = dyn_cast(Ty)) { const RecordDecl *RD = TTy->getDecl()->getDefinition(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); -SmallVector Fields; +using TBAAStructField = llvm::MDBuilder::TBAAStructField; +SmallVector Fields; +if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { + // Handle C++ base classes. Non-virtual bases can treated a a kind of + // field. Virtual bases are more complex and omitted, but avoid an + // incomplete view for NewStructPathTBAA. + if (CodeGenOpts.NewStructPathTBAA && CXXRD->getNumVBases() != 0) +return BaseTypeMetadataCache[Ty] = nullptr; + for (const CXXBaseSpecifier &B : CXXRD->bases()) { +if (B.isVirtual()) + continue; +QualType BaseQTy = B.getType(); +const CXXRecordDecl *BaseRD = BaseQTy->getAsCXXRecordDecl(); +if (BaseRD->isEmpty()) + continue; +llvm::MDNode *TypeNode = isValidBaseType(BaseQTy) + ? getBaseTypeInfo(BaseQTy) + : getTypeInfo(BaseQTy); +if (!TypeNode) + return BaseTypeMetadataCache[Ty] = nullptr; +uint64_t Offset = Layout.getBaseClassOffset(BaseRD).getQuantity(); +uint64_t Size = +Context.getASTRecordLayout(BaseRD).getDataSize().getQuantity(); +Fields.push_back( +llvm::MDBuilder::TBAAStructField(Offset, Size, TypeNode)); + } + // The order in which base class subobjects are allocated is unspecified, + // so may diff er from declaration order. In particular, Itanium ABI will + // allocate a primary base first. + // Since we exclude empty subobjects, the objects are not overlapping and + // their offsets are unique. + llvm::sort(Fields, + [](const TBAAStructField &A, const TBAAStructField &B) { + return A.Offset < B.Offset; + }); +} for (FieldDecl *Field : RD->fields()) { if (Field->isZeroSize(Context) || Field->isUnnamedBitfield()) continue; diff --git a/clang/test/CodeGen/tbaa-class.cpp b/clang/test/CodeGen/tbaa-class.cpp index 7f413a6f323c2..8e485f7c1cb8f 100644 --- a/clang/test/CodeGen/tbaa-class.cpp +++ b/clang/test/CodeGen/tbaa-class.cpp @@ -51,6 +51,25 @@ class StructS2 : public StructS uint32_t f32_2; }; +class StructT { +public: + uint32_t f32_2; + void foo(); +}; +class StructM1 : public StructS, public StructT { +public: + uint16_t f16_2; +}; +class StructDyn { +public: + uint32_t f32_2; + virtual void foo(); +}; +class StructM2 : public StructS, public StructDyn { +public: + uint16_t f16_2; +}; + uint32_t g(uint32_t *s, StructA *A, uint64_t count) { // CHECK-LABEL: define{{.*}} i32 @_Z1g // CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa [[TAG_i32:!.*]] @@ -199,6 +218,30 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) { return b1->a.f32; } +uint32_t g13(StructM1 *M, StructS *S) { + // CHECK-LABEL: define{{.*}} i32 @_Z3g13 + // CHECK: store i16 1, i16* %{{.*}}, align 4, !tbaa [[TAG_i16]] + // CHECK: store i16 4, i16* %{{.*}}, align 4, !tbaa [[TAG_i16]] + // PATH-LABEL: define{{.*}} i32 @_Z3g13 + // PATH: store i16 1, i16* %{{.*}}, align 4, !tbaa [[TAG_S_f16]] + // PATH: store i16 4, i16* %{{.*}}, align 4, !tbaa [[TAG_M1_f16_2:!.*]] + S->f16 = 1; + M->f16_2 = 4; + return S->f16; +} + +uint32_t g14(StructM2 *M, StructS *S) { + // CHECK-LABEL: define{{.*}} i32 @_Z3g14 + // CHECK: store i16 1, i16* %{{.*}}, align 4, !tbaa [[TAG_i16]] + // CHECK: store i16 4, i16* %{{.*}}, align 4, !tbaa [[TAG_i16]] + // PATH-LABEL: define{{.*}} i32 @_Z3g14 + // PATH: store i16 1, i16* %{{.*}}, align 4, !tbaa [[TAG_S_f16]] + // PATH: store i16 4, i16* %{{.*}},
[clang] 2b9a834 - [InlineFunction] Use llvm.experimental.noalias.scope.decl for noalias arguments.
Author: Jeroen Dobbelaere Date: 2021-01-23T12:10:57+01:00 New Revision: 2b9a834c43cb1f93d33958c14b695896bb4e9c1e URL: https://github.com/llvm/llvm-project/commit/2b9a834c43cb1f93d33958c14b695896bb4e9c1e DIFF: https://github.com/llvm/llvm-project/commit/2b9a834c43cb1f93d33958c14b695896bb4e9c1e.diff LOG: [InlineFunction] Use llvm.experimental.noalias.scope.decl for noalias arguments. Insert a llvm.experimental.noalias.scope.decl intrinsic that identifies where a noalias argument was inlined. This patch includes some refactorings from D90104. Reviewed By: nikic Differential Revision: https://reviews.llvm.org/D93040 Added: llvm/test/Transforms/Inline/noalias-calls2.ll Modified: clang/test/CodeGen/aarch64-ls64.c llvm/lib/Transforms/Utils/InlineFunction.cpp llvm/test/Transforms/Coroutines/ArgAddr.ll llvm/test/Transforms/Coroutines/coro-retcon-resume-values.ll llvm/test/Transforms/Coroutines/coro-retcon-value.ll llvm/test/Transforms/Coroutines/coro-retcon.ll llvm/test/Transforms/Coroutines/ex2.ll llvm/test/Transforms/Coroutines/ex3.ll llvm/test/Transforms/Coroutines/ex4.ll llvm/test/Transforms/Inline/launder.invariant.group.ll llvm/test/Transforms/Inline/noalias-calls-always.ll llvm/test/Transforms/Inline/noalias-calls.ll llvm/test/Transforms/Inline/noalias-cs.ll llvm/test/Transforms/Inline/noalias.ll llvm/test/Transforms/Inline/noalias2.ll llvm/test/Transforms/PhaseOrdering/inlining-alignment-assumptions.ll llvm/test/Transforms/PhaseOrdering/instcombine-sroa-inttoptr.ll llvm/test/Transforms/PhaseOrdering/pr39282.ll Removed: diff --git a/clang/test/CodeGen/aarch64-ls64.c b/clang/test/CodeGen/aarch64-ls64.c index 77e4b41fbd58..17fce0094ac9 100644 --- a/clang/test/CodeGen/aarch64-ls64.c +++ b/clang/test/CodeGen/aarch64-ls64.c @@ -21,6 +21,7 @@ uint64_t status; // CHECK-NEXT:[[__ADDR_ADDR_I:%.*]] = alloca i8*, align 8 // CHECK-NEXT:[[REF_TMP:%.*]] = alloca [[STRUCT_DATA512_T:%.*]], align 8 // CHECK-NEXT:[[TMP0:%.*]] = load i8*, i8** @addr, align 8 +// CHECK-NEXT:call void @llvm.experimental.noalias.scope.decl(metadata !6) // CHECK-NEXT:store i8* [[TMP0]], i8** [[__ADDR_ADDR_I]], align 8, !noalias !6 // CHECK-NEXT:[[TMP1:%.*]] = load i8*, i8** [[__ADDR_ADDR_I]], align 8, !noalias !6 // CHECK-NEXT:[[VAL_I:%.*]] = getelementptr inbounds [[STRUCT_DATA512_T]], %struct.data512_t* [[REF_TMP]], i32 0, i32 0 diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp index 65bf6a3b32dc..abdd2b2361b7 100644 --- a/llvm/lib/Transforms/Utils/InlineFunction.cpp +++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp @@ -79,6 +79,12 @@ EnableNoAliasConversion("enable-noalias-to-md-conversion", cl::init(true), cl::Hidden, cl::desc("Convert noalias attributes to metadata during inlining.")); +static cl::opt +UseNoAliasIntrinsic("use-noalias-intrinsic-during-inlining", cl::Hidden, +cl::ZeroOrMore, cl::init(true), +cl::desc("Use the llvm.experimental.noalias.scope.decl " + "intrinsic during inlining.")); + // Disabled by default, because the added alignment assumptions may increase // compile-time and block optimizations. This option is not suitable for use // with frontends that emit comprehensive parameter alignment annotations. @@ -821,91 +827,119 @@ static void PropagateCallSiteMetadata(CallBase &CB, ValueToValueMapTy &VMap) { } } -/// When inlining a function that contains noalias scope metadata, -/// this metadata needs to be cloned so that the inlined blocks -/// have diff erent "unique scopes" at every call site. Were this not done, then -/// aliasing scopes from a function inlined into a caller multiple times could -/// not be diff erentiated (and this would lead to miscompiles because the -/// non-aliasing property communicated by the metadata could have -/// call-site-specific control dependencies). -static void CloneAliasScopeMetadata(CallBase &CB, ValueToValueMapTy &VMap) { - const Function *CalledFunc = CB.getCalledFunction(); +/// Utility for cloning !noalias and !alias.scope metadata. When a code region +/// using scoped alias metadata is inlined, the aliasing relationships may not +/// hold between the two version. It is necessary to create a deep clone of the +/// metadata, putting the two versions in separate scope domains. +class ScopedAliasMetadataDeepCloner { + using MetadataMap = DenseMap; SetVector MD; - - // Note: We could only clone the metadata if it is already used in the - // caller. I'm omitting that check here because it might confuse - // inter-procedural alias analysis passes. We can revisit this if it becomes - // an efficiency or overhead problem. - - for (const BasicBlock &I : *CalledFunc) -for (const Instruction &J : I) {
[clang] 46757cc - [clang] functions with the 'const' or 'pure' attribute must always return.
Author: Jeroen Dobbelaere Date: 2021-02-18T17:29:46+01:00 New Revision: 46757ccb49ab88da54ca8ddd43665d5255ee80f7 URL: https://github.com/llvm/llvm-project/commit/46757ccb49ab88da54ca8ddd43665d5255ee80f7 DIFF: https://github.com/llvm/llvm-project/commit/46757ccb49ab88da54ca8ddd43665d5255ee80f7.diff LOG: [clang] functions with the 'const' or 'pure' attribute must always return. As described in * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-pure-function-attribute * https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-const-function-attribute An `__attribute__((pure))` function must always return, as well as an `__attribute__((const))` function. Reviewed By: jdoerfert Differential Revision: https://reviews.llvm.org/D96960 Added: Modified: clang/lib/CodeGen/CGCall.cpp clang/test/CodeGen/complex-builtins.c clang/test/CodeGen/complex-libcalls.c clang/test/CodeGen/function-attributes.c clang/test/CodeGenCXX/2009-05-04-PureConstNounwind.cpp clang/test/Sema/libbuiltins-ctype-powerpc64.c clang/test/Sema/libbuiltins-ctype-x86_64.c Removed: diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 405b4d2e1980..992e87319943 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1994,9 +1994,14 @@ void CodeGenModule::ConstructAttributeList( if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ReadNone); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + // gcc specifies that 'const' functions have greater restrictions than + // 'pure' functions, so they also cannot have infinite loops. + FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ReadOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); + // gcc specifies that 'pure' functions cannot have infinite loops. + FuncAttrs.addAttribute(llvm::Attribute::WillReturn); } else if (TargetDecl->hasAttr()) { FuncAttrs.addAttribute(llvm::Attribute::ArgMemOnly); FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); diff --git a/clang/test/CodeGen/complex-builtins.c b/clang/test/CodeGen/complex-builtins.c index 96c0e7117016..6fea8a9f028c 100644 --- a/clang/test/CodeGen/complex-builtins.c +++ b/clang/test/CodeGen/complex-builtins.c @@ -133,7 +133,7 @@ void foo(float f) { // NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] // HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] -// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[WILLRETURN_NOT_READNONE:#[0-9]+]] __builtin_cpow(f,f); __builtin_cpowf(f,f); __builtin_cpowl(f,f); @@ -202,3 +202,4 @@ void foo(float f) { // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } diff --git a/clang/test/CodeGen/complex-libcalls.c b/clang/test/CodeGen/complex-libcalls.c index 9bd419a83821..44d6849c0a71 100644 --- a/clang/test/CodeGen/complex-libcalls.c +++ b/clang/test/CodeGen/complex-libcalls.c @@ -133,7 +133,7 @@ void foo(float f) { // NO__ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] // HAS_ERRNO: declare { double, double } @cproj(double, double) [[READNONE:#[0-9]+]] // HAS_ERRNO: declare <2 x float> @cprojf(<2 x float>) [[READNONE]] -// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[NOT_READNONE]] +// HAS_ERRNO: declare { x86_fp80, x86_fp80 } @cprojl({ x86_fp80, x86_fp80 }* byval({ x86_fp80, x86_fp80 }) align 16) [[WILLRETURN_NOT_READNONE:#[0-9]+]] cpow(f,f); cpowf(f,f); cpowl(f,f); @@ -202,3 +202,4 @@ void foo(float f) { // HAS_ERRNO: attributes [[NOT_READNONE]] = { nounwind {{.*}} } // HAS_ERRNO: attributes [[READNONE]] = { {{.*}}readnone{{.*}} } +// HAS_ERRNO: attributes [[WILLRETURN_NOT_READNONE]] = { nounwind willreturn {{.*}} } diff --git a/clang/test/CodeGen/function-attributes.c b/clang/test/CodeGen/function-attributes.c index ffb86a6cd272..f14f24801006 100644 --- a/clang/test/CodeGen/function-attributes.c +++ b/clang/test/CodeGen/function-attributes.c @@ -115,5 +115,5 @@ void f20(void) { // CHECK: attributes [[SR]] = { nounwind optsize{{.*}} "stackrealign"{{.*}} } // CHECK:
[clang] 4d8871a - PR50767: clear non-distinct debuginfo for function with nodebug definition after undecorated declaration
Author: Bruno De Fraine Date: 2021-06-29T10:26:45+02:00 New Revision: 4d8871a898b30f11c905b27954c18d826c0953c9 URL: https://github.com/llvm/llvm-project/commit/4d8871a898b30f11c905b27954c18d826c0953c9 DIFF: https://github.com/llvm/llvm-project/commit/4d8871a898b30f11c905b27954c18d826c0953c9.diff LOG: PR50767: clear non-distinct debuginfo for function with nodebug definition after undecorated declaration Fix suggested by Yuanfang Chen: Non-distinct debuginfo is attached to the function due to the undecorated declaration. Later, when seeing the function definition and `nodebug` attribute, the non-distinct debuginfo should be cleared. Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D104777 Added: clang/test/CodeGen/attr-nodebug2.c Modified: clang/lib/CodeGen/CodeGenFunction.cpp Removed: diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 0ca94657e815..578b8a811817 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -1304,8 +1304,14 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, QualType ResTy = BuildFunctionArgList(GD, Args); // Check if we should generate debug info for this function. - if (FD->hasAttr()) -DebugInfo = nullptr; // disable debug info indefinitely for this function + if (FD->hasAttr()) { +// Clear non-distinct debug info that was possibly attached to the function +// due to an earlier declaration without the nodebug attribute +if (Fn) + Fn->setSubprogram(nullptr); +// Disable debug info indefinitely for this function +DebugInfo = nullptr; + } // The function might not have a body if we're generating thunks for a // function declaration. diff --git a/clang/test/CodeGen/attr-nodebug2.c b/clang/test/CodeGen/attr-nodebug2.c new file mode 100644 index ..fd6eca1f7432 --- /dev/null +++ b/clang/test/CodeGen/attr-nodebug2.c @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -x c -debug-info-kind=limited -debugger-tuning=gdb -dwarf-version=4 -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -x c++ -debug-info-kind=limited -debugger-tuning=gdb -dwarf-version=4 -O -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s + +#ifdef __cplusplus +extern "C" { +#endif + +void t1(); + +void use() { t1(); } + +__attribute__((nodebug)) void t1() { + int a = 10; + a++; +} + +#ifdef __cplusplus +} +#endif + +// CHECK-LABEL: define{{.*}} void @use() +// CHECK-SAME: !dbg +// CHECK-SAME: { +// CHECK: !dbg +// CHECK: } + +// PR50767 Function __attribute__((nodebug)) inconsistency causes crash +// illegal (non-distinct) !dbg metadata was being added to _Z2t1v definition + +// CHECK-LABEL: define{{.*}} void @t1() +// CHECK-NOT: !dbg +// CHECK-SAME: { +// CHECK-NOT: !dbg +// CHECK: } ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] 0c047a8 - [Sema] check PseudoObject when rebuilding CXXOperatorCallExpr in template instantiation
Author: Jeroen Dobbelaere Date: 2021-12-01T11:02:28+01:00 New Revision: 0c047a8e13320fb8e9dabbf7a3c6a00fe81198c7 URL: https://github.com/llvm/llvm-project/commit/0c047a8e13320fb8e9dabbf7a3c6a00fe81198c7 DIFF: https://github.com/llvm/llvm-project/commit/0c047a8e13320fb8e9dabbf7a3c6a00fe81198c7.diff LOG: [Sema] check PseudoObject when rebuilding CXXOperatorCallExpr in template instantiation The invocation of a unary or binary operator for type-dependent expressions is represented as a CXXOperatorCallExpr. Upon template instantiation, TreeTransform::RebuildCXXOperatorCallExpr checks for the case of an overloaded operator, but not for a (non-ObjC) PseudoObject, and will directly create a UnaryOperator or BinaryOperator. Generalizing commit 0f99537ecac40 from @akyrtzi to handle non-ObjC pseudo objects (and also handle the case of unary pseudo object inc/dec). This fixes https://bugs.llvm.org/show_bug.cgi?id=51855 Reviewed By: rnk Differential Revision: https://reviews.llvm.org/D111639 Added: clang/test/SemaCXX/PR51855.cpp Modified: clang/lib/Sema/TreeTransform.h clang/test/SemaObjCXX/instantiate-property-access.mm Removed: diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7f3326c13263f..152feac4041c4 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -14630,18 +14630,28 @@ TreeTransform::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, Expr *Callee = OrigCallee->IgnoreParenCasts(); bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus); - if (First->getObjectKind() == OK_ObjCProperty) { -BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); -if (BinaryOperator::isAssignmentOp(Opc)) - return SemaRef.checkPseudoObjectAssignment(/*Scope=*/nullptr, OpLoc, Opc, - First, Second); + if (const BuiltinType *pty = First->getType()->getAsPlaceholderType()) { +if (Second && !isPostIncDec) { + BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); + if (pty->getKind() == BuiltinType::PseudoObject && + BinaryOperator::isAssignmentOp(Opc)) +return SemaRef.checkPseudoObjectAssignment(/*Scope=*/nullptr, OpLoc, + Opc, First, Second); +} else { + UnaryOperatorKind Opc = + UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); + if (pty->getKind() == BuiltinType::PseudoObject && + UnaryOperator::isIncrementDecrementOp(Opc)) +return SemaRef.checkPseudoObjectIncDec(/*Scope=*/nullptr, OpLoc, Opc, + First); +} ExprResult Result = SemaRef.CheckPlaceholderExpr(First); if (Result.isInvalid()) return ExprError(); First = Result.get(); } - if (Second && Second->getObjectKind() == OK_ObjCProperty) { + if (Second && Second->getType()->isPlaceholderType()) { ExprResult Result = SemaRef.CheckPlaceholderExpr(Second); if (Result.isInvalid()) return ExprError(); diff --git a/clang/test/SemaCXX/PR51855.cpp b/clang/test/SemaCXX/PR51855.cpp new file mode 100644 index 0..6ace3bf085aa5 --- /dev/null +++ b/clang/test/SemaCXX/PR51855.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -S -triple %itanium_abi_triple -fms-extensions -emit-llvm %s -o - | FileCheck %s + +struct F {}; + +F operator*=(F &lhs, int rhs); + +F operator++(F &lhs); + +struct S { + short _m; + S(short _m) : _m(_m) {} + + void putM(short rhs) { _m = rhs; } + short getM() { return _m; } + + __declspec(property(get = getM, put = putM)) short theData; +}; + +int test1a(int i) { + S tmp(i); + tmp.theData *= 2; + return tmp.theData; +} + +// CHECK-LABEL: define {{.*}} @_Z6test1ai( +// CHECK: call {{.*}} @_ZN1SC1Es( +// CHECK: call {{.*}} @_ZN1S4getMEv( +// CHECK: call {{.*}} @_ZN1S4putMEs( +// CHECK: call {{.*}} @_ZN1S4getMEv( + +template +int test1b(int i) { + T tmp(i); + tmp.theData *= 2; + return tmp.theData; +} + +template int test1b(int); + +// CHECK-LABEL: define {{.*}} @_Z6test1bI1SEii( +// CHECK: call {{.*}} @_ZN1SC1Es( +// CHECK: call {{.*}} @_ZN1S4getMEv( +// CHECK: call {{.*}} @_ZN1S4putMEs( +// CHECK: call {{.*}} @_ZN1S4getMEv( + +int test2a(int i) { + S tmp(i); + ++tmp.theData; + return tmp.theData; +} + +// CHECK-LABEL: define {{.*}} i32 @_Z6test2ai( +// CHECK: call {{.*}} @_ZN1SC1Es( +// CHECK: call {{.*}} @_ZN1S4getMEv( +// CHECK: call {{.*}} @_ZN1S4putMEs( +// CHECK: call {{.*}} @_ZN1S4getMEv( + +template +int test2b(int i) { + T tmp(i); + ++tmp.theData; + return tmp.theData; +} + +template int test2b(int); + +// CHECK-LABEL: define {{.*}} i32 @_Z6test2bI1SEii( +// CHECK: call void @_ZN1SC1Es( +// CHECK: call {{.*}} @_ZN1S4getMEv( +// CHECK: call {{.*}} @_ZN1S4putMEs( +// CHECK: call {{.*}} @_ZN1S4getMEv( diff --git a/clang/test/Sema
[clang] a4fbae2 - Revert "[Sema] check PseudoObject when rebuilding CXXOperatorCallExpr in template instantiation"
Author: Jeroen Dobbelaere Date: 2021-12-01T11:18:30+01:00 New Revision: a4fbae268f67a6737b86c47f555f95a4a44462d2 URL: https://github.com/llvm/llvm-project/commit/a4fbae268f67a6737b86c47f555f95a4a44462d2 DIFF: https://github.com/llvm/llvm-project/commit/a4fbae268f67a6737b86c47f555f95a4a44462d2.diff LOG: Revert "[Sema] check PseudoObject when rebuilding CXXOperatorCallExpr in template instantiation" This reverts commit 0c047a8e13320fb8e9dabbf7a3c6a00fe81198c7. A number of buildbots started failing. Reverting for now. Added: Modified: clang/lib/Sema/TreeTransform.h clang/test/SemaObjCXX/instantiate-property-access.mm Removed: clang/test/SemaCXX/PR51855.cpp diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 152feac4041c4..7f3326c13263f 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -14630,28 +14630,18 @@ TreeTransform::RebuildCXXOperatorCallExpr(OverloadedOperatorKind Op, Expr *Callee = OrigCallee->IgnoreParenCasts(); bool isPostIncDec = Second && (Op == OO_PlusPlus || Op == OO_MinusMinus); - if (const BuiltinType *pty = First->getType()->getAsPlaceholderType()) { -if (Second && !isPostIncDec) { - BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); - if (pty->getKind() == BuiltinType::PseudoObject && - BinaryOperator::isAssignmentOp(Opc)) -return SemaRef.checkPseudoObjectAssignment(/*Scope=*/nullptr, OpLoc, - Opc, First, Second); -} else { - UnaryOperatorKind Opc = - UnaryOperator::getOverloadedOpcode(Op, isPostIncDec); - if (pty->getKind() == BuiltinType::PseudoObject && - UnaryOperator::isIncrementDecrementOp(Opc)) -return SemaRef.checkPseudoObjectIncDec(/*Scope=*/nullptr, OpLoc, Opc, - First); -} + if (First->getObjectKind() == OK_ObjCProperty) { +BinaryOperatorKind Opc = BinaryOperator::getOverloadedOpcode(Op); +if (BinaryOperator::isAssignmentOp(Opc)) + return SemaRef.checkPseudoObjectAssignment(/*Scope=*/nullptr, OpLoc, Opc, + First, Second); ExprResult Result = SemaRef.CheckPlaceholderExpr(First); if (Result.isInvalid()) return ExprError(); First = Result.get(); } - if (Second && Second->getType()->isPlaceholderType()) { + if (Second && Second->getObjectKind() == OK_ObjCProperty) { ExprResult Result = SemaRef.CheckPlaceholderExpr(Second); if (Result.isInvalid()) return ExprError(); diff --git a/clang/test/SemaCXX/PR51855.cpp b/clang/test/SemaCXX/PR51855.cpp deleted file mode 100644 index 6ace3bf085aa5..0 --- a/clang/test/SemaCXX/PR51855.cpp +++ /dev/null @@ -1,71 +0,0 @@ -// RUN: %clang_cc1 -S -triple %itanium_abi_triple -fms-extensions -emit-llvm %s -o - | FileCheck %s - -struct F {}; - -F operator*=(F &lhs, int rhs); - -F operator++(F &lhs); - -struct S { - short _m; - S(short _m) : _m(_m) {} - - void putM(short rhs) { _m = rhs; } - short getM() { return _m; } - - __declspec(property(get = getM, put = putM)) short theData; -}; - -int test1a(int i) { - S tmp(i); - tmp.theData *= 2; - return tmp.theData; -} - -// CHECK-LABEL: define {{.*}} @_Z6test1ai( -// CHECK: call {{.*}} @_ZN1SC1Es( -// CHECK: call {{.*}} @_ZN1S4getMEv( -// CHECK: call {{.*}} @_ZN1S4putMEs( -// CHECK: call {{.*}} @_ZN1S4getMEv( - -template -int test1b(int i) { - T tmp(i); - tmp.theData *= 2; - return tmp.theData; -} - -template int test1b(int); - -// CHECK-LABEL: define {{.*}} @_Z6test1bI1SEii( -// CHECK: call {{.*}} @_ZN1SC1Es( -// CHECK: call {{.*}} @_ZN1S4getMEv( -// CHECK: call {{.*}} @_ZN1S4putMEs( -// CHECK: call {{.*}} @_ZN1S4getMEv( - -int test2a(int i) { - S tmp(i); - ++tmp.theData; - return tmp.theData; -} - -// CHECK-LABEL: define {{.*}} i32 @_Z6test2ai( -// CHECK: call {{.*}} @_ZN1SC1Es( -// CHECK: call {{.*}} @_ZN1S4getMEv( -// CHECK: call {{.*}} @_ZN1S4putMEs( -// CHECK: call {{.*}} @_ZN1S4getMEv( - -template -int test2b(int i) { - T tmp(i); - ++tmp.theData; - return tmp.theData; -} - -template int test2b(int); - -// CHECK-LABEL: define {{.*}} i32 @_Z6test2bI1SEii( -// CHECK: call void @_ZN1SC1Es( -// CHECK: call {{.*}} @_ZN1S4getMEv( -// CHECK: call {{.*}} @_ZN1S4putMEs( -// CHECK: call {{.*}} @_ZN1S4getMEv( diff --git a/clang/test/SemaObjCXX/instantiate-property-access.mm b/clang/test/SemaObjCXX/instantiate-property-access.mm index e792825facf46..8d5c201a80a19 100644 --- a/clang/test/SemaObjCXX/instantiate-property-access.mm +++ b/clang/test/SemaObjCXX/instantiate-property-access.mm @@ -1,5 +1,4 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -// RUN: %clang_cc1 -fsyntax-only -DDEPENDENT -verify %s // expected-no-diagnostics class C {}; @@ -10,10 +9,6 @@ C operator += (C c1, C c2); -C operator+
[clang] cdc59e2 - [tbaa] Handle base classes in struct tbaa
Author: Bruno De Fraine Date: 2022-06-23T13:39:49+02:00 New Revision: cdc59e2202c11a6a5dfd2ec83531523c58eaae45 URL: https://github.com/llvm/llvm-project/commit/cdc59e2202c11a6a5dfd2ec83531523c58eaae45 DIFF: https://github.com/llvm/llvm-project/commit/cdc59e2202c11a6a5dfd2ec83531523c58eaae45.diff LOG: [tbaa] Handle base classes in struct tbaa This is a fix for the miscompilation reported in https://github.com/llvm/llvm-project/issues/55384 Not adding a new test case since existing test cases already cover base classes (including new-struct-path tbaa). Reviewed By: jeroen.dobbelaere Differential Revision: https://reviews.llvm.org/D126956 Added: Modified: clang/lib/CodeGen/CodeGenTBAA.cpp clang/test/CodeGen/tbaa-class.cpp clang/unittests/CodeGen/TBAAMetadataTest.cpp Removed: diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 95763d8e18b70..2904bd5a244fe 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -336,6 +336,30 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) { const RecordDecl *RD = TTy->getDecl()->getDefinition(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); SmallVector Fields; +if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { + // Handle C++ base classes. Non-virtual bases can treated a a kind of + // field. Virtual bases are more complex and omitted, but avoid an + // incomplete view for NewStructPathTBAA. + if (CodeGenOpts.NewStructPathTBAA && CXXRD->getNumVBases() != 0) +return BaseTypeMetadataCache[Ty] = nullptr; + for (const CXXBaseSpecifier &B : CXXRD->bases()) { +if (B.isVirtual()) + continue; +QualType BaseQTy = B.getType(); +const CXXRecordDecl *BaseRD = BaseQTy->getAsCXXRecordDecl(); +if (BaseRD->isEmpty()) + continue; +llvm::MDNode *TypeNode = isValidBaseType(BaseQTy) + ? getBaseTypeInfo(BaseQTy) + : getTypeInfo(BaseQTy); +if (!TypeNode) + return BaseTypeMetadataCache[Ty] = nullptr; +uint64_t Offset = Layout.getBaseClassOffset(BaseRD).getQuantity(); +uint64_t Size = Context.getTypeSizeInChars(BaseQTy).getQuantity(); +Fields.push_back( +llvm::MDBuilder::TBAAStructField(Offset, Size, TypeNode)); + } +} for (FieldDecl *Field : RD->fields()) { if (Field->isZeroSize(Context) || Field->isUnnamedBitfield()) continue; diff --git a/clang/test/CodeGen/tbaa-class.cpp b/clang/test/CodeGen/tbaa-class.cpp index 7f413a6f323c2..38558b0415a7a 100644 --- a/clang/test/CodeGen/tbaa-class.cpp +++ b/clang/test/CodeGen/tbaa-class.cpp @@ -222,7 +222,7 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) { // OLD-PATH: [[TYPE_S]] = !{!"_ZTS7StructS", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4} // OLD-PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0} // OLD-PATH: [[TAG_S2_f32_2]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 12} -// OLD-PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12} +// OLD-PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_S]], i64 0, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12} // OLD-PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12} // OLD-PATH: [[TYPE_C]] = !{!"_ZTS7StructC", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28} // OLD-PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12} @@ -244,7 +244,7 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) { // NEW-PATH: [[TYPE_S]] = !{[[TYPE_CHAR]], i64 8, !"_ZTS7StructS", [[TYPE_SHORT]], i64 0, i64 2, [[TYPE_INT]], i64 4, i64 4} // NEW-PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0, i64 2} // NEW-PATH: [[TAG_S2_f32_2]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 12, i64 4} -// NEW-PATH: [[TYPE_S2]] = !{[[TYPE_CHAR]], i64 16, !"_ZTS8StructS2", [[TYPE_SHORT]], i64 8, i64 2, [[TYPE_INT]], i64 12, i64 4} +// NEW-PATH: [[TYPE_S2]] = !{[[TYPE_CHAR]], i64 16, !"_ZTS8StructS2", [[TYPE_S]], i64 0, i64 8, [[TYPE_SHORT]], i64 8, i64 2, [[TYPE_INT]], i64 12, i64 4} // NEW-PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12, i64 4} // NEW-PATH: [[TYPE_C]] = !{[[TYPE_CHAR]], i64 32, !"_ZTS7StructC", [[TYPE_SHORT]], i64 0, i64 2, [[TYPE_B]], i64 4, i64 24, [[TYPE_INT]], i64 28, i64 4} // NEW-PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12, i64 4} diff --git a/clang/unittests/CodeGen/TBAAMetadataTest.cpp b/clang/unittests/CodeGen/TBAAMetadataTest.cpp index 149a8e074b692..2919a35c8cedf 100644 --- a/clang/unittests/CodeGen/TBAAMetadataTest.cpp +++ b/clang/unittests/CodeGen/TBAAMetadataTest.cpp @@ -968,13 +968,10 @@ TEST(TBAAMetadataTest, BaseClass) { MConstInt(0)), MConstInt(0)); - auto ClassDerived = MMTup
[clang] 8999b74 - Revert "[tbaa] Handle base classes in struct tbaa"
Author: Jeroen Dobbelaere Date: 2022-06-23T14:18:49+02:00 New Revision: 8999b745bc4ecae5ac74f5c4d06f40e317ddb12c URL: https://github.com/llvm/llvm-project/commit/8999b745bc4ecae5ac74f5c4d06f40e317ddb12c DIFF: https://github.com/llvm/llvm-project/commit/8999b745bc4ecae5ac74f5c4d06f40e317ddb12c.diff LOG: Revert "[tbaa] Handle base classes in struct tbaa" This reverts commit cdc59e2202c11a6a5dfd2ec83531523c58eaae45. The Verifier finds a problem in a stage2 build. Reverting so Bruno can investigate. Added: Modified: clang/lib/CodeGen/CodeGenTBAA.cpp clang/test/CodeGen/tbaa-class.cpp clang/unittests/CodeGen/TBAAMetadataTest.cpp Removed: diff --git a/clang/lib/CodeGen/CodeGenTBAA.cpp b/clang/lib/CodeGen/CodeGenTBAA.cpp index 2904bd5a244f..95763d8e18b7 100644 --- a/clang/lib/CodeGen/CodeGenTBAA.cpp +++ b/clang/lib/CodeGen/CodeGenTBAA.cpp @@ -336,30 +336,6 @@ llvm::MDNode *CodeGenTBAA::getBaseTypeInfoHelper(const Type *Ty) { const RecordDecl *RD = TTy->getDecl()->getDefinition(); const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); SmallVector Fields; -if (const CXXRecordDecl *CXXRD = dyn_cast(RD)) { - // Handle C++ base classes. Non-virtual bases can treated a a kind of - // field. Virtual bases are more complex and omitted, but avoid an - // incomplete view for NewStructPathTBAA. - if (CodeGenOpts.NewStructPathTBAA && CXXRD->getNumVBases() != 0) -return BaseTypeMetadataCache[Ty] = nullptr; - for (const CXXBaseSpecifier &B : CXXRD->bases()) { -if (B.isVirtual()) - continue; -QualType BaseQTy = B.getType(); -const CXXRecordDecl *BaseRD = BaseQTy->getAsCXXRecordDecl(); -if (BaseRD->isEmpty()) - continue; -llvm::MDNode *TypeNode = isValidBaseType(BaseQTy) - ? getBaseTypeInfo(BaseQTy) - : getTypeInfo(BaseQTy); -if (!TypeNode) - return BaseTypeMetadataCache[Ty] = nullptr; -uint64_t Offset = Layout.getBaseClassOffset(BaseRD).getQuantity(); -uint64_t Size = Context.getTypeSizeInChars(BaseQTy).getQuantity(); -Fields.push_back( -llvm::MDBuilder::TBAAStructField(Offset, Size, TypeNode)); - } -} for (FieldDecl *Field : RD->fields()) { if (Field->isZeroSize(Context) || Field->isUnnamedBitfield()) continue; diff --git a/clang/test/CodeGen/tbaa-class.cpp b/clang/test/CodeGen/tbaa-class.cpp index 38558b0415a7..7f413a6f323c 100644 --- a/clang/test/CodeGen/tbaa-class.cpp +++ b/clang/test/CodeGen/tbaa-class.cpp @@ -222,7 +222,7 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) { // OLD-PATH: [[TYPE_S]] = !{!"_ZTS7StructS", [[TYPE_SHORT]], i64 0, [[TYPE_INT]], i64 4} // OLD-PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0} // OLD-PATH: [[TAG_S2_f32_2]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 12} -// OLD-PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_S]], i64 0, [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12} +// OLD-PATH: [[TYPE_S2]] = !{!"_ZTS8StructS2", [[TYPE_SHORT]], i64 8, [[TYPE_INT]], i64 12} // OLD-PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12} // OLD-PATH: [[TYPE_C]] = !{!"_ZTS7StructC", [[TYPE_SHORT]], i64 0, [[TYPE_B]], i64 4, [[TYPE_INT]], i64 28} // OLD-PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12} @@ -244,7 +244,7 @@ uint32_t g12(StructC *C, StructD *D, uint64_t count) { // NEW-PATH: [[TYPE_S]] = !{[[TYPE_CHAR]], i64 8, !"_ZTS7StructS", [[TYPE_SHORT]], i64 0, i64 2, [[TYPE_INT]], i64 4, i64 4} // NEW-PATH: [[TAG_S_f16]] = !{[[TYPE_S]], [[TYPE_SHORT]], i64 0, i64 2} // NEW-PATH: [[TAG_S2_f32_2]] = !{[[TYPE_S2:!.*]], [[TYPE_INT]], i64 12, i64 4} -// NEW-PATH: [[TYPE_S2]] = !{[[TYPE_CHAR]], i64 16, !"_ZTS8StructS2", [[TYPE_S]], i64 0, i64 8, [[TYPE_SHORT]], i64 8, i64 2, [[TYPE_INT]], i64 12, i64 4} +// NEW-PATH: [[TYPE_S2]] = !{[[TYPE_CHAR]], i64 16, !"_ZTS8StructS2", [[TYPE_SHORT]], i64 8, i64 2, [[TYPE_INT]], i64 12, i64 4} // NEW-PATH: [[TAG_C_b_a_f32]] = !{[[TYPE_C:!.*]], [[TYPE_INT]], i64 12, i64 4} // NEW-PATH: [[TYPE_C]] = !{[[TYPE_CHAR]], i64 32, !"_ZTS7StructC", [[TYPE_SHORT]], i64 0, i64 2, [[TYPE_B]], i64 4, i64 24, [[TYPE_INT]], i64 28, i64 4} // NEW-PATH: [[TAG_D_b_a_f32]] = !{[[TYPE_D:!.*]], [[TYPE_INT]], i64 12, i64 4} diff --git a/clang/unittests/CodeGen/TBAAMetadataTest.cpp b/clang/unittests/CodeGen/TBAAMetadataTest.cpp index 2919a35c8ced..149a8e074b69 100644 --- a/clang/unittests/CodeGen/TBAAMetadataTest.cpp +++ b/clang/unittests/CodeGen/TBAAMetadataTest.cpp @@ -968,10 +968,13 @@ TEST(TBAAMetadataTest, BaseClass) { MConstInt(0)), MConstInt(0)); - auto ClassDerived = - MMTuple(MMString("_ZTS7Derived"), ClassBase, MConstInt(0), - MMTuple(MMString("short"), OmnipotentCharCXX, MConstInt(0)), -