From: Anastasia Stulova Date: Thu, 4 Apr 2019 10:48:36 +0000 (+0000) Subject: [PR41276] Fixed incorrect generation of addr space cast for 'this' in C++. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5e1826201aa4e8e5d60c3f6b8c476dfa130b2022;p=clang [PR41276] Fixed incorrect generation of addr space cast for 'this' in C++. Improved classification of address space cast when qualification conversion is performed - prevent adding addr space cast for non-pointer and non-reference types. Take address space correctly from the pointee. Also pass correct address space from 'this' object using AggValueSlot when generating addrspacecast in the constructor call. Differential Revision: https://reviews.llvm.org/D59988 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@357682 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6c69ca31c0..cf488850d3 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1678,7 +1678,7 @@ bool CastExpr::CastConsistency() const { auto Ty = getType(); auto SETy = getSubExpr()->getType(); assert(getValueKindForType(Ty) == Expr::getValueKindForType(SETy)); - if (isRValue()) { + if (/*isRValue()*/ !Ty->getPointeeType().isNull()) { Ty = Ty->getPointeeType(); SETy = SETy->getPointeeType(); } diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index d4df3109fe..d16cae676d 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -1978,10 +1978,14 @@ void CodeGenFunction::EmitCXXAggrConstructorCall(const CXXConstructorDecl *ctor, pushRegularPartialArrayCleanup(arrayBegin, cur, type, eltAlignment, *destroyer); } - + auto currAVS = AggValueSlot::forAddr( + curAddr, type.getQualifiers(), AggValueSlot::IsDestructed, + AggValueSlot::DoesNotNeedGCBarriers, AggValueSlot::IsNotAliased, + AggValueSlot::DoesNotOverlap, AggValueSlot::IsNotZeroed, + NewPointerIsChecked ? AggValueSlot::IsSanitizerChecked + : AggValueSlot::IsNotSanitizerChecked); EmitCXXConstructorCall(ctor, Ctor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, curAddr, E, - AggValueSlot::DoesNotOverlap, NewPointerIsChecked); + /*Delegating=*/false, currAVS, E); } // Go to the next element. @@ -2015,16 +2019,16 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, - bool Delegating, Address This, - const CXXConstructExpr *E, - AggValueSlot::Overlap_t Overlap, - bool NewPointerIsChecked) { + bool Delegating, + AggValueSlot ThisAVS, + const CXXConstructExpr *E) { CallArgList Args; - - LangAS SlotAS = E->getType().getAddressSpace(); + Address This = ThisAVS.getAddress(); + LangAS SlotAS = ThisAVS.getQualifiers().getAddressSpace(); QualType ThisType = D->getThisType(); LangAS ThisAS = ThisType.getTypePtr()->getPointeeType().getAddressSpace(); llvm::Value *ThisPtr = This.getPointer(); + if (SlotAS != ThisAS) { unsigned TargetThisAS = getContext().getTargetAddressSpace(ThisAS); llvm::Type *NewType = @@ -2032,6 +2036,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, ThisPtr = getTargetHooks().performAddrSpaceCast(*this, This.getPointer(), ThisAS, SlotAS, NewType); } + // Push the this ptr. Args.add(RValue::get(ThisPtr), D->getThisType()); @@ -2045,7 +2050,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, LValue Src = EmitLValue(Arg); QualType DestTy = getContext().getTypeDeclType(D->getParent()); LValue Dest = MakeAddrLValue(This, DestTy); - EmitAggregateCopyCtor(Dest, Src, Overlap); + EmitAggregateCopyCtor(Dest, Src, ThisAVS.mayOverlap()); return; } @@ -2058,7 +2063,8 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, /*ParamsToSkip*/ 0, Order); EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args, - Overlap, E->getExprLoc(), NewPointerIsChecked); + ThisAVS.mayOverlap(), E->getExprLoc(), + ThisAVS.isSanitizerChecked()); } static bool canEmitDelegateCallArgs(CodeGenFunction &CGF, diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 161d6ed34e..cd49be4bd4 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -783,6 +783,8 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { RValue rvalue = RValue::getAggregate(valueAddr, atomicSlot.isVolatile()); return EmitFinalDestCopy(valueType, rvalue); } + case CK_AddressSpaceConversion: + return Visit(E->getSubExpr()); case CK_LValueToRValue: // If we're loading from a volatile type, force the destination @@ -794,6 +796,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { LLVM_FALLTHROUGH; + case CK_NoOp: case CK_UserDefinedConversion: case CK_ConstructorConversion: @@ -849,7 +852,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLOpaqueType: - case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: case CK_FixedPointCast: case CK_FixedPointToBoolean: diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 10ee829f65..b0078c22c8 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -614,12 +614,10 @@ CodeGenFunction::EmitCXXConstructExpr(const CXXConstructExpr *E, case CXXConstructExpr::CK_NonVirtualBase: Type = Ctor_Base; - } + } - // Call the constructor. - EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating, - Dest.getAddress(), E, Dest.mayOverlap(), - Dest.isSanitizerChecked()); + // Call the constructor. + EmitCXXConstructorCall(CD, Type, ForVirtualBase, Delegating, Dest, E); } } diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index c24fc77d6d..fddbe1443c 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -2503,16 +2503,13 @@ public: void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, - Address This, const CXXConstructExpr *E, - AggValueSlot::Overlap_t Overlap, - bool NewPointerIsChecked); + AggValueSlot ThisAVS, const CXXConstructExpr *E); void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, Address This, CallArgList &Args, AggValueSlot::Overlap_t Overlap, - SourceLocation Loc, - bool NewPointerIsChecked); + SourceLocation Loc, bool NewPointerIsChecked); /// Emit assumption load for all bases. Requires to be be called only on /// most-derived class and not under construction of the object. diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 24786886da..1ae18b90f8 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -7321,9 +7321,19 @@ ExprResult Sema::TemporaryMaterializationConversion(Expr *E) { ExprResult Sema::PerformQualificationConversion(Expr *E, QualType Ty, ExprValueKind VK, CheckedConversionKind CCK) { - CastKind CK = (Ty.getAddressSpace() != E->getType().getAddressSpace()) - ? CK_AddressSpaceConversion - : CK_NoOp; + + CastKind CK = CK_NoOp; + + if (VK == VK_RValue) { + auto PointeeTy = Ty->getPointeeType(); + auto ExprPointeeTy = E->getType()->getPointeeType(); + if (!PointeeTy.isNull() && + PointeeTy.getAddressSpace() != ExprPointeeTy.getAddressSpace()) + CK = CK_AddressSpaceConversion; + } else if (Ty.getAddressSpace() != E->getType().getAddressSpace()) { + CK = CK_AddressSpaceConversion; + } + return ImpCastExprToType(E, Ty, CK, VK, /*BasePath=*/nullptr, CCK); } diff --git a/test/CodeGenCXX/address-space-of-this.cpp b/test/CodeGenCXX/address-space-of-this.cpp new file mode 100644 index 0000000000..3a1e53ced0 --- /dev/null +++ b/test/CodeGenCXX/address-space-of-this.cpp @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 %s -std=c++14 -triple=spir -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -std=c++17 -triple=spir -emit-llvm -o - | FileCheck %s + +struct MyType { + MyType(int i) : i(i) {} + int i; +}; +//CHECK: call void @_ZN6MyTypeC1Ei(%struct.MyType* addrspacecast (%struct.MyType addrspace(10)* @m to %struct.MyType*), i32 123) +MyType __attribute__((address_space(10))) m = 123;