forked from OSchip/llvm-project
Revert r366422: [OpenCL] Improve destructor support in C++ for OpenCL
Reason: this commit causes crashes in the clang compiler when building LLVM Support with libc++, see https://bugs.llvm.org/show_bug.cgi?id=42665 for details. llvm-svn: 366429
This commit is contained in:
parent
8f5b44aead
commit
4f8dc16fcd
|
@ -2232,20 +2232,20 @@ public:
|
|||
|
||||
overridden_method_range overridden_methods() const;
|
||||
|
||||
/// Return the parent of this method declaration, which
|
||||
/// Returns the parent of this method declaration, which
|
||||
/// is the class in which this method is defined.
|
||||
const CXXRecordDecl *getParent() const {
|
||||
return cast<CXXRecordDecl>(FunctionDecl::getParent());
|
||||
}
|
||||
|
||||
/// Return the parent of this method declaration, which
|
||||
/// Returns the parent of this method declaration, which
|
||||
/// is the class in which this method is defined.
|
||||
CXXRecordDecl *getParent() {
|
||||
return const_cast<CXXRecordDecl *>(
|
||||
cast<CXXRecordDecl>(FunctionDecl::getParent()));
|
||||
}
|
||||
|
||||
/// Return the type of the \c this pointer.
|
||||
/// Returns the type of the \c this pointer.
|
||||
///
|
||||
/// Should only be called for instance (i.e., non-static) methods. Note
|
||||
/// that for the call operator of a lambda closure type, this returns the
|
||||
|
@ -2253,17 +2253,9 @@ public:
|
|||
/// 'this' type.
|
||||
QualType getThisType() const;
|
||||
|
||||
/// Return the type of the object pointed by \c this.
|
||||
///
|
||||
/// See getThisType() for usage restriction.
|
||||
QualType getThisObjectType() const;
|
||||
|
||||
static QualType getThisType(const FunctionProtoType *FPT,
|
||||
const CXXRecordDecl *Decl);
|
||||
|
||||
static QualType getThisObjectType(const FunctionProtoType *FPT,
|
||||
const CXXRecordDecl *Decl);
|
||||
|
||||
Qualifiers getMethodQualifiers() const {
|
||||
return getType()->getAs<FunctionProtoType>()->getMethodQuals();
|
||||
}
|
||||
|
|
|
@ -2253,23 +2253,12 @@ CXXMethodDecl::overridden_methods() const {
|
|||
return getASTContext().overridden_methods(this);
|
||||
}
|
||||
|
||||
static QualType getThisObjectType(ASTContext &C, const FunctionProtoType *FPT,
|
||||
const CXXRecordDecl *Decl) {
|
||||
QualType ClassTy = C.getTypeDeclType(Decl);
|
||||
return C.getQualifiedType(ClassTy, FPT->getMethodQuals());
|
||||
}
|
||||
|
||||
QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT,
|
||||
const CXXRecordDecl *Decl) {
|
||||
ASTContext &C = Decl->getASTContext();
|
||||
QualType ObjectTy = ::getThisObjectType(C, FPT, Decl);
|
||||
return C.getPointerType(ObjectTy);
|
||||
}
|
||||
|
||||
QualType CXXMethodDecl::getThisObjectType(const FunctionProtoType *FPT,
|
||||
const CXXRecordDecl *Decl) {
|
||||
ASTContext &C = Decl->getASTContext();
|
||||
return ::getThisObjectType(C, FPT, Decl);
|
||||
QualType ClassTy = C.getTypeDeclType(Decl);
|
||||
ClassTy = C.getQualifiedType(ClassTy, FPT->getMethodQuals());
|
||||
return C.getPointerType(ClassTy);
|
||||
}
|
||||
|
||||
QualType CXXMethodDecl::getThisType() const {
|
||||
|
@ -2284,14 +2273,6 @@ QualType CXXMethodDecl::getThisType() const {
|
|||
getParent());
|
||||
}
|
||||
|
||||
QualType CXXMethodDecl::getThisObjectType() const {
|
||||
// Ditto getThisType.
|
||||
assert(isInstance() && "No 'this' for static methods!");
|
||||
|
||||
return CXXMethodDecl::getThisObjectType(getType()->getAs<FunctionProtoType>(),
|
||||
getParent());
|
||||
}
|
||||
|
||||
bool CXXMethodDecl::hasInlineBody() const {
|
||||
// If this function is a template instantiation, look at the template from
|
||||
// which it was instantiated.
|
||||
|
|
|
@ -378,7 +378,7 @@ public:
|
|||
virtual void EmitDestructorCall(CodeGenFunction &CGF,
|
||||
const CXXDestructorDecl *DD, CXXDtorType Type,
|
||||
bool ForVirtualBase, bool Delegating,
|
||||
Address This, QualType ThisTy) = 0;
|
||||
Address This) = 0;
|
||||
|
||||
/// Emits the VTable definitions required for the given record type.
|
||||
virtual void emitVTableDefinitions(CodeGenVTables &CGVT,
|
||||
|
@ -421,15 +421,11 @@ public:
|
|||
llvm::Type *Ty,
|
||||
SourceLocation Loc) = 0;
|
||||
|
||||
using DeleteOrMemberCallExpr =
|
||||
llvm::PointerUnion<const CXXDeleteExpr *, const CXXMemberCallExpr *>;
|
||||
|
||||
/// Emit the ABI-specific virtual destructor call.
|
||||
virtual llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
|
||||
const CXXDestructorDecl *Dtor,
|
||||
CXXDtorType DtorType,
|
||||
Address This,
|
||||
DeleteOrMemberCallExpr E) = 0;
|
||||
virtual llvm::Value *
|
||||
EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor,
|
||||
CXXDtorType DtorType, Address This,
|
||||
const CXXMemberCallExpr *CE) = 0;
|
||||
|
||||
virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF,
|
||||
GlobalDecl GD,
|
||||
|
|
|
@ -3502,7 +3502,7 @@ struct DestroyUnpassedArg final : EHScopeStack::Cleanup {
|
|||
const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
|
||||
assert(!Dtor->isTrivial());
|
||||
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false,
|
||||
/*Delegating=*/false, Addr, Ty);
|
||||
/*Delegating=*/false, Addr);
|
||||
} else {
|
||||
CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Ty));
|
||||
}
|
||||
|
|
|
@ -491,15 +491,12 @@ namespace {
|
|||
cast<CXXMethodDecl>(CGF.CurCodeDecl)->getParent();
|
||||
|
||||
const CXXDestructorDecl *D = BaseClass->getDestructor();
|
||||
// We are already inside a destructor, so presumably the object being
|
||||
// destroyed should have the expected type.
|
||||
QualType ThisTy = D->getThisObjectType();
|
||||
Address Addr =
|
||||
CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(),
|
||||
DerivedClass, BaseClass,
|
||||
BaseIsVirtual);
|
||||
CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual,
|
||||
/*Delegating=*/false, Addr, ThisTy);
|
||||
/*Delegating=*/false, Addr);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1443,11 +1440,9 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
|
|||
if (DtorType == Dtor_Deleting) {
|
||||
RunCleanupsScope DtorEpilogue(*this);
|
||||
EnterDtorCleanups(Dtor, Dtor_Deleting);
|
||||
if (HaveInsertPoint()) {
|
||||
QualType ThisTy = Dtor->getThisObjectType();
|
||||
if (HaveInsertPoint())
|
||||
EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false,
|
||||
/*Delegating=*/false, LoadCXXThisAddress(), ThisTy);
|
||||
}
|
||||
/*Delegating=*/false, LoadCXXThisAddress());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1478,9 +1473,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
|
|||
EnterDtorCleanups(Dtor, Dtor_Complete);
|
||||
|
||||
if (!isTryBody) {
|
||||
QualType ThisTy = Dtor->getThisObjectType();
|
||||
EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false,
|
||||
/*Delegating=*/false, LoadCXXThisAddress(), ThisTy);
|
||||
/*Delegating=*/false, LoadCXXThisAddress());
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2019,7 +2013,7 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF,
|
|||
const CXXDestructorDecl *dtor = record->getDestructor();
|
||||
assert(!dtor->isTrivial());
|
||||
CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false,
|
||||
/*Delegating=*/false, addr, type);
|
||||
/*Delegating=*/false, addr);
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,
|
||||
|
@ -2369,11 +2363,8 @@ namespace {
|
|||
: Dtor(D), Addr(Addr), Type(Type) {}
|
||||
|
||||
void Emit(CodeGenFunction &CGF, Flags flags) override {
|
||||
// We are calling the destructor from within the constructor.
|
||||
// Therefore, "this" should have the expected type.
|
||||
QualType ThisTy = Dtor->getThisObjectType();
|
||||
CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false,
|
||||
/*Delegating=*/true, Addr, ThisTy);
|
||||
/*Delegating=*/true, Addr);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
@ -2411,32 +2402,31 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor
|
|||
void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,
|
||||
CXXDtorType Type,
|
||||
bool ForVirtualBase,
|
||||
bool Delegating, Address This,
|
||||
QualType ThisTy) {
|
||||
bool Delegating,
|
||||
Address This) {
|
||||
CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase,
|
||||
Delegating, This, ThisTy);
|
||||
Delegating, This);
|
||||
}
|
||||
|
||||
namespace {
|
||||
struct CallLocalDtor final : EHScopeStack::Cleanup {
|
||||
const CXXDestructorDecl *Dtor;
|
||||
Address Addr;
|
||||
QualType Ty;
|
||||
|
||||
CallLocalDtor(const CXXDestructorDecl *D, Address Addr, QualType Ty)
|
||||
: Dtor(D), Addr(Addr), Ty(Ty) {}
|
||||
CallLocalDtor(const CXXDestructorDecl *D, Address Addr)
|
||||
: Dtor(D), Addr(Addr) {}
|
||||
|
||||
void Emit(CodeGenFunction &CGF, Flags flags) override {
|
||||
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
|
||||
/*ForVirtualBase=*/false,
|
||||
/*Delegating=*/false, Addr, Ty);
|
||||
/*Delegating=*/false, Addr);
|
||||
}
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D,
|
||||
QualType T, Address Addr) {
|
||||
EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr, T);
|
||||
Address Addr) {
|
||||
EHStack.pushCleanup<CallLocalDtor>(NormalAndEHCleanup, D, Addr);
|
||||
}
|
||||
|
||||
void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) {
|
||||
|
@ -2446,7 +2436,7 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) {
|
|||
|
||||
const CXXDestructorDecl *D = ClassDecl->getDestructor();
|
||||
assert(D && D->isUsed() && "destructor not marked as used!");
|
||||
PushDestructorCleanup(D, T, Addr);
|
||||
PushDestructorCleanup(D, Addr);
|
||||
}
|
||||
|
||||
void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) {
|
||||
|
|
|
@ -480,12 +480,11 @@ namespace {
|
|||
|
||||
template <class Derived>
|
||||
struct DestroyNRVOVariable : EHScopeStack::Cleanup {
|
||||
DestroyNRVOVariable(Address addr, QualType type, llvm::Value *NRVOFlag)
|
||||
: NRVOFlag(NRVOFlag), Loc(addr), Ty(type) {}
|
||||
DestroyNRVOVariable(Address addr, llvm::Value *NRVOFlag)
|
||||
: NRVOFlag(NRVOFlag), Loc(addr) {}
|
||||
|
||||
llvm::Value *NRVOFlag;
|
||||
Address Loc;
|
||||
QualType Ty;
|
||||
|
||||
void Emit(CodeGenFunction &CGF, Flags flags) override {
|
||||
// Along the exceptions path we always execute the dtor.
|
||||
|
@ -512,24 +511,26 @@ namespace {
|
|||
|
||||
struct DestroyNRVOVariableCXX final
|
||||
: DestroyNRVOVariable<DestroyNRVOVariableCXX> {
|
||||
DestroyNRVOVariableCXX(Address addr, QualType type,
|
||||
const CXXDestructorDecl *Dtor, llvm::Value *NRVOFlag)
|
||||
: DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, type, NRVOFlag),
|
||||
Dtor(Dtor) {}
|
||||
DestroyNRVOVariableCXX(Address addr, const CXXDestructorDecl *Dtor,
|
||||
llvm::Value *NRVOFlag)
|
||||
: DestroyNRVOVariable<DestroyNRVOVariableCXX>(addr, NRVOFlag),
|
||||
Dtor(Dtor) {}
|
||||
|
||||
const CXXDestructorDecl *Dtor;
|
||||
|
||||
void emitDestructorCall(CodeGenFunction &CGF) {
|
||||
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
|
||||
/*ForVirtualBase=*/false,
|
||||
/*Delegating=*/false, Loc, Ty);
|
||||
/*Delegating=*/false, Loc);
|
||||
}
|
||||
};
|
||||
|
||||
struct DestroyNRVOVariableC final
|
||||
: DestroyNRVOVariable<DestroyNRVOVariableC> {
|
||||
DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty)
|
||||
: DestroyNRVOVariable<DestroyNRVOVariableC>(addr, Ty, NRVOFlag) {}
|
||||
: DestroyNRVOVariable<DestroyNRVOVariableC>(addr, NRVOFlag), Ty(Ty) {}
|
||||
|
||||
QualType Ty;
|
||||
|
||||
void emitDestructorCall(CodeGenFunction &CGF) {
|
||||
CGF.destroyNonTrivialCStruct(CGF, Loc, Ty);
|
||||
|
@ -1939,7 +1940,7 @@ void CodeGenFunction::emitAutoVarTypeCleanup(
|
|||
if (emission.NRVOFlag) {
|
||||
assert(!type->isArrayType());
|
||||
CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor();
|
||||
EHStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, type, dtor,
|
||||
EHStack.pushCleanup<DestroyNRVOVariableCXX>(cleanupKind, addr, dtor,
|
||||
emission.NRVOFlag);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -10,13 +10,12 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "CodeGenFunction.h"
|
||||
#include "CGCUDARuntime.h"
|
||||
#include "CGCXXABI.h"
|
||||
#include "CGDebugInfo.h"
|
||||
#include "CGObjCRuntime.h"
|
||||
#include "CodeGenFunction.h"
|
||||
#include "ConstantEmitter.h"
|
||||
#include "TargetInfo.h"
|
||||
#include "clang/Basic/CodeGenOptions.h"
|
||||
#include "clang/CodeGen/CGFunctionInfo.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
|
@ -91,26 +90,12 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall(
|
|||
}
|
||||
|
||||
RValue CodeGenFunction::EmitCXXDestructorCall(
|
||||
GlobalDecl Dtor, const CGCallee &Callee, llvm::Value *This, QualType ThisTy,
|
||||
GlobalDecl Dtor, const CGCallee &Callee, llvm::Value *This,
|
||||
llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE) {
|
||||
const CXXMethodDecl *DtorDecl = cast<CXXMethodDecl>(Dtor.getDecl());
|
||||
|
||||
assert(!ThisTy.isNull());
|
||||
assert(ThisTy->getAsCXXRecordDecl() == DtorDecl->getParent() &&
|
||||
"Pointer/Object mixup");
|
||||
|
||||
LangAS SrcAS = ThisTy.getAddressSpace();
|
||||
LangAS DstAS = DtorDecl->getMethodQualifiers().getAddressSpace();
|
||||
if (SrcAS != DstAS) {
|
||||
QualType DstTy = DtorDecl->getThisType();
|
||||
llvm::Type *NewType = CGM.getTypes().ConvertType(DstTy);
|
||||
This = getTargetHooks().performAddrSpaceCast(*this, This, SrcAS, DstAS,
|
||||
NewType);
|
||||
}
|
||||
|
||||
CallArgList Args;
|
||||
commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam,
|
||||
ImplicitParamTy, CE, Args, nullptr);
|
||||
commonEmitCXXMemberOrOperatorCall(*this, cast<CXXMethodDecl>(Dtor.getDecl()),
|
||||
This, ImplicitParam, ImplicitParamTy, CE,
|
||||
Args, nullptr);
|
||||
return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee,
|
||||
ReturnValueSlot(), Args);
|
||||
}
|
||||
|
@ -360,9 +345,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr(
|
|||
Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(GD, Ty), GD);
|
||||
}
|
||||
|
||||
QualType ThisTy =
|
||||
IsArrow ? Base->getType()->getPointeeType() : Base->getType();
|
||||
EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy,
|
||||
EmitCXXDestructorCall(GD, Callee, This.getPointer(),
|
||||
/*ImplicitParam=*/nullptr,
|
||||
/*ImplicitParamTy=*/QualType(), nullptr);
|
||||
}
|
||||
|
@ -1900,7 +1883,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
|
|||
CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete,
|
||||
/*ForVirtualBase=*/false,
|
||||
/*Delegating=*/false,
|
||||
Ptr, ElementType);
|
||||
Ptr);
|
||||
else if (auto Lifetime = ElementType.getObjCLifetime()) {
|
||||
switch (Lifetime) {
|
||||
case Qualifiers::OCL_None:
|
||||
|
|
|
@ -675,8 +675,7 @@ public:
|
|||
/// PushDestructorCleanup - Push a cleanup to call the
|
||||
/// complete-object variant of the given destructor on the object at
|
||||
/// the given address.
|
||||
void PushDestructorCleanup(const CXXDestructorDecl *Dtor, QualType T,
|
||||
Address Addr);
|
||||
void PushDestructorCleanup(const CXXDestructorDecl *Dtor, Address Addr);
|
||||
|
||||
/// PopCleanupBlock - Will pop the cleanup entry on the stack and
|
||||
/// process all branch fixups.
|
||||
|
@ -2555,8 +2554,8 @@ public:
|
|||
static Destroyer destroyCXXObject;
|
||||
|
||||
void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type,
|
||||
bool ForVirtualBase, bool Delegating, Address This,
|
||||
QualType ThisTy);
|
||||
bool ForVirtualBase, bool Delegating,
|
||||
Address This);
|
||||
|
||||
void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType,
|
||||
llvm::Type *ElementTy, Address NewPtr,
|
||||
|
@ -3678,9 +3677,9 @@ public:
|
|||
llvm::Value *ImplicitParam,
|
||||
QualType ImplicitParamTy, const CallExpr *E,
|
||||
CallArgList *RtlArgs);
|
||||
RValue EmitCXXDestructorCall(GlobalDecl Dtor, const CGCallee &Callee,
|
||||
llvm::Value *This, QualType ThisTy,
|
||||
llvm::Value *ImplicitParam,
|
||||
RValue EmitCXXDestructorCall(GlobalDecl Dtor,
|
||||
const CGCallee &Callee,
|
||||
llvm::Value *This, llvm::Value *ImplicitParam,
|
||||
QualType ImplicitParamTy, const CallExpr *E);
|
||||
RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E,
|
||||
ReturnValueSlot ReturnValue);
|
||||
|
|
|
@ -224,8 +224,7 @@ public:
|
|||
|
||||
void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
|
||||
CXXDtorType Type, bool ForVirtualBase,
|
||||
bool Delegating, Address This,
|
||||
QualType ThisTy) override;
|
||||
bool Delegating, Address This) override;
|
||||
|
||||
void emitVTableDefinitions(CodeGenVTables &CGVT,
|
||||
const CXXRecordDecl *RD) override;
|
||||
|
@ -262,8 +261,9 @@ public:
|
|||
|
||||
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
|
||||
const CXXDestructorDecl *Dtor,
|
||||
CXXDtorType DtorType, Address This,
|
||||
DeleteOrMemberCallExpr E) override;
|
||||
CXXDtorType DtorType,
|
||||
Address This,
|
||||
const CXXMemberCallExpr *CE) override;
|
||||
|
||||
void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override;
|
||||
|
||||
|
@ -1128,7 +1128,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
|
|||
// FIXME: Provide a source location here even though there's no
|
||||
// CXXMemberCallExpr for dtor call.
|
||||
CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
|
||||
EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE);
|
||||
EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr);
|
||||
|
||||
if (UseGlobalDelete)
|
||||
CGF.PopCleanupBlock();
|
||||
|
@ -1539,8 +1539,7 @@ CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs(
|
|||
void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
|
||||
const CXXDestructorDecl *DD,
|
||||
CXXDtorType Type, bool ForVirtualBase,
|
||||
bool Delegating, Address This,
|
||||
QualType ThisTy) {
|
||||
bool Delegating, Address This) {
|
||||
GlobalDecl GD(DD, Type);
|
||||
llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating);
|
||||
QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
|
||||
|
@ -1552,8 +1551,7 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
|
|||
else
|
||||
Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD);
|
||||
|
||||
CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy,
|
||||
nullptr);
|
||||
CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), VTT, VTTTy, nullptr);
|
||||
}
|
||||
|
||||
void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT,
|
||||
|
@ -1741,10 +1739,7 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
|
|||
|
||||
llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
|
||||
CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
|
||||
Address This, DeleteOrMemberCallExpr E) {
|
||||
auto *CE = E.dyn_cast<const CXXMemberCallExpr *>();
|
||||
auto *D = E.dyn_cast<const CXXDeleteExpr *>();
|
||||
assert((CE != nullptr) ^ (D != nullptr));
|
||||
Address This, const CXXMemberCallExpr *CE) {
|
||||
assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
|
||||
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
|
||||
|
||||
|
@ -1754,14 +1749,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall(
|
|||
llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);
|
||||
CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty);
|
||||
|
||||
QualType ThisTy;
|
||||
if (CE)
|
||||
ThisTy = CE->getImplicitObjectArgument()->getType()->getPointeeType();
|
||||
else
|
||||
ThisTy = D->getDestroyedType();
|
||||
|
||||
CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr,
|
||||
QualType(), nullptr);
|
||||
CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), nullptr, QualType(),
|
||||
nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -258,8 +258,7 @@ public:
|
|||
|
||||
void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD,
|
||||
CXXDtorType Type, bool ForVirtualBase,
|
||||
bool Delegating, Address This,
|
||||
QualType ThisTy) override;
|
||||
bool Delegating, Address This) override;
|
||||
|
||||
void emitVTableTypeMetadata(const VPtrInfo &Info, const CXXRecordDecl *RD,
|
||||
llvm::GlobalVariable *VTable);
|
||||
|
@ -297,8 +296,9 @@ public:
|
|||
|
||||
llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF,
|
||||
const CXXDestructorDecl *Dtor,
|
||||
CXXDtorType DtorType, Address This,
|
||||
DeleteOrMemberCallExpr E) override;
|
||||
CXXDtorType DtorType,
|
||||
Address This,
|
||||
const CXXMemberCallExpr *CE) override;
|
||||
|
||||
void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD,
|
||||
CallArgList &CallArgs) override {
|
||||
|
@ -844,7 +844,8 @@ void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
|
|||
// CXXMemberCallExpr for dtor call.
|
||||
bool UseGlobalDelete = DE->isGlobalDelete();
|
||||
CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;
|
||||
llvm::Value *MDThis = EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE);
|
||||
llvm::Value *MDThis =
|
||||
EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr);
|
||||
if (UseGlobalDelete)
|
||||
CGF.EmitDeleteCall(DE->getOperatorDelete(), MDThis, ElementType);
|
||||
}
|
||||
|
@ -1568,8 +1569,7 @@ CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs(
|
|||
void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
|
||||
const CXXDestructorDecl *DD,
|
||||
CXXDtorType Type, bool ForVirtualBase,
|
||||
bool Delegating, Address This,
|
||||
QualType ThisTy) {
|
||||
bool Delegating, Address This) {
|
||||
// Use the base destructor variant in place of the complete destructor variant
|
||||
// if the class has no virtual bases. This effectively implements some of the
|
||||
// -mconstructor-aliases optimization, but as part of the MS C++ ABI.
|
||||
|
@ -1591,7 +1591,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
|
|||
BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF);
|
||||
}
|
||||
|
||||
CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy,
|
||||
CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(),
|
||||
/*ImplicitParam=*/nullptr,
|
||||
/*ImplicitParamTy=*/QualType(), nullptr);
|
||||
if (BaseDtorEndBB) {
|
||||
|
@ -1900,10 +1900,7 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
|
|||
|
||||
llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
|
||||
CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType,
|
||||
Address This, DeleteOrMemberCallExpr E) {
|
||||
auto *CE = E.dyn_cast<const CXXMemberCallExpr *>();
|
||||
auto *D = E.dyn_cast<const CXXDeleteExpr *>();
|
||||
assert((CE != nullptr) ^ (D != nullptr));
|
||||
Address This, const CXXMemberCallExpr *CE) {
|
||||
assert(CE == nullptr || CE->arg_begin() == CE->arg_end());
|
||||
assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);
|
||||
|
||||
|
@ -1920,14 +1917,8 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall(
|
|||
llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()),
|
||||
DtorType == Dtor_Deleting);
|
||||
|
||||
QualType ThisTy;
|
||||
if (CE)
|
||||
ThisTy = CE->getImplicitObjectArgument()->getType()->getPointeeType();
|
||||
else
|
||||
ThisTy = D->getDestroyedType();
|
||||
|
||||
This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true);
|
||||
RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy,
|
||||
RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(),
|
||||
ImplicitParam, Context.IntTy, CE);
|
||||
return RV.getScalarVal();
|
||||
}
|
||||
|
|
|
@ -8190,27 +8190,6 @@ void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) {
|
|||
CheckCXXDefaultArguments(Method);
|
||||
}
|
||||
|
||||
// Emit the given diagnostic for each non-address-space qualifier.
|
||||
// Common part of CheckConstructorDeclarator and CheckDestructorDeclarator.
|
||||
static void checkMethodTypeQualifiers(Sema &S, Declarator &D, unsigned DiagID) {
|
||||
const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
|
||||
if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) {
|
||||
bool DiagOccured = false;
|
||||
FTI.MethodQualifiers->forEachQualifier(
|
||||
[DiagID, &S, &DiagOccured](DeclSpec::TQ, StringRef QualName,
|
||||
SourceLocation SL) {
|
||||
// This diagnostic should be emitted on any qualifier except an addr
|
||||
// space qualifier. However, forEachQualifier currently doesn't visit
|
||||
// addr space qualifiers, so there's no way to write this condition
|
||||
// right now; we just diagnose on everything.
|
||||
S.Diag(SL, DiagID) << QualName << SourceRange(SL);
|
||||
DiagOccured = true;
|
||||
});
|
||||
if (DiagOccured)
|
||||
D.setInvalidType();
|
||||
}
|
||||
}
|
||||
|
||||
/// CheckConstructorDeclarator - Called by ActOnDeclarator to check
|
||||
/// the well-formedness of the constructor declarator @p D with type @p
|
||||
/// R. If there are any errors in the declarator, this routine will
|
||||
|
@ -8251,11 +8230,25 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R,
|
|||
D.setInvalidType();
|
||||
}
|
||||
|
||||
checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_constructor);
|
||||
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
|
||||
if (FTI.hasMethodTypeQualifiers()) {
|
||||
bool DiagOccured = false;
|
||||
FTI.MethodQualifiers->forEachQualifier(
|
||||
[&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
|
||||
// This diagnostic should be emitted on any qualifier except an addr
|
||||
// space qualifier. However, forEachQualifier currently doesn't visit
|
||||
// addr space qualifiers, so there's no way to write this condition
|
||||
// right now; we just diagnose on everything.
|
||||
Diag(SL, diag::err_invalid_qualified_constructor)
|
||||
<< QualName << SourceRange(SL);
|
||||
DiagOccured = true;
|
||||
});
|
||||
if (DiagOccured)
|
||||
D.setInvalidType();
|
||||
}
|
||||
|
||||
// C++0x [class.ctor]p4:
|
||||
// A constructor shall not be declared with a ref-qualifier.
|
||||
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
|
||||
if (FTI.hasRefQualifier()) {
|
||||
Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor)
|
||||
<< FTI.RefQualifierIsLValueRef
|
||||
|
@ -8430,11 +8423,18 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R,
|
|||
}
|
||||
}
|
||||
|
||||
checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_destructor);
|
||||
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
|
||||
if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) {
|
||||
FTI.MethodQualifiers->forEachQualifier(
|
||||
[&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) {
|
||||
Diag(SL, diag::err_invalid_qualified_destructor)
|
||||
<< QualName << SourceRange(SL);
|
||||
});
|
||||
D.setInvalidType();
|
||||
}
|
||||
|
||||
// C++0x [class.dtor]p2:
|
||||
// A destructor shall not be declared with a ref-qualifier.
|
||||
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
|
||||
if (FTI.hasRefQualifier()) {
|
||||
Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor)
|
||||
<< FTI.RefQualifierIsLValueRef
|
||||
|
|
|
@ -5093,10 +5093,12 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType,
|
|||
QualType ClassType = S.Context.getTypeDeclType(ActingContext);
|
||||
// [class.dtor]p2: A destructor can be invoked for a const, volatile or
|
||||
// const volatile object.
|
||||
Qualifiers Quals = Method->getMethodQualifiers();
|
||||
Qualifiers Quals;
|
||||
if (isa<CXXDestructorDecl>(Method)) {
|
||||
Quals.addConst();
|
||||
Quals.addVolatile();
|
||||
} else {
|
||||
Quals = Method->getMethodQualifiers();
|
||||
}
|
||||
|
||||
QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals);
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s
|
||||
|
||||
struct MyType {
|
||||
MyType(int i) : i(i) {}
|
||||
MyType(int i) __constant : i(i) {}
|
||||
int i;
|
||||
};
|
||||
|
||||
//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1)
|
||||
__constant MyType const1 = 1;
|
||||
//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2)
|
||||
__constant MyType const2(2);
|
||||
//CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1)
|
||||
MyType glob(1);
|
|
@ -1,59 +0,0 @@
|
|||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s --check-prefix=CHECK-DEFINITIONS
|
||||
|
||||
// This test ensures the proper address spaces and address space cast are used
|
||||
// for constructors, member functions and destructors.
|
||||
// See also atexit.cl and global_init.cl for other specific tests.
|
||||
|
||||
// CHECK: %struct.MyType = type { i32 }
|
||||
struct MyType {
|
||||
MyType(int i) : i(i) {}
|
||||
MyType(int i) __constant : i(i) {}
|
||||
~MyType() {}
|
||||
~MyType() __constant {}
|
||||
int bar() { return i + 2; }
|
||||
int bar() __constant { return i + 1; }
|
||||
int i;
|
||||
};
|
||||
|
||||
// CHECK: @const1 = addrspace(2) global %struct.MyType zeroinitializer
|
||||
__constant MyType const1 = 1;
|
||||
// CHECK: @const2 = addrspace(2) global %struct.MyType zeroinitializer
|
||||
__constant MyType const2(2);
|
||||
// CHECK: @glob = addrspace(1) global %struct.MyType zeroinitializer
|
||||
MyType glob(1);
|
||||
|
||||
// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1)
|
||||
// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2)
|
||||
// CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1)
|
||||
|
||||
// CHECK-LABEL: define spir_kernel void @fooGlobal()
|
||||
kernel void fooGlobal() {
|
||||
// CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*))
|
||||
glob.bar();
|
||||
// CHECK: call i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* @const1)
|
||||
const1.bar();
|
||||
// CHECK: call void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* @const1)
|
||||
const1.~MyType();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define spir_kernel void @fooLocal()
|
||||
kernel void fooLocal() {
|
||||
// CHECK: [[VAR:%.*]] = alloca %struct.MyType
|
||||
// CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)*
|
||||
// CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* [[REG]], i32 3)
|
||||
MyType myLocal(3);
|
||||
// CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)*
|
||||
// CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* [[REG]])
|
||||
myLocal.bar();
|
||||
// CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)*
|
||||
// CHECK: call void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* [[REG]])
|
||||
}
|
||||
|
||||
// Ensure all members are defined for all the required address spaces.
|
||||
// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* %this, i32 %i)
|
||||
// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* %this, i32 %i)
|
||||
// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* %this)
|
||||
// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* %this)
|
||||
// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* %this)
|
||||
// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* %this)
|
Loading…
Reference in New Issue