From: Richard Smith Date: Thu, 1 Dec 2016 03:32:42 +0000 (+0000) Subject: P0012R1: add Itanium ABI support for throwing non-noexcept function pointers and... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=19dc4350b116842299a2d834d8c827c5b4cf593d;p=clang P0012R1: add Itanium ABI support for throwing non-noexcept function pointers and catching as noexcept. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@288305 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/ItaniumCXXABI.cpp b/lib/CodeGen/ItaniumCXXABI.cpp index 1e506d4655..088454647c 100644 --- a/lib/CodeGen/ItaniumCXXABI.cpp +++ b/lib/CodeGen/ItaniumCXXABI.cpp @@ -2474,7 +2474,13 @@ public: /// PTI_ContainingClassIncomplete - Containing class is incomplete. /// (in pointer to member). - PTI_ContainingClassIncomplete = 0x10 + PTI_ContainingClassIncomplete = 0x10, + + /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS). + //PTI_TransactionSafe = 0x20, + + /// PTI_Noexcept - Pointee is noexcept function (C++1z). + PTI_Noexcept = 0x40, }; // VMI type info flags. @@ -3124,21 +3130,6 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force, return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); } -/// ComputeQualifierFlags - Compute the pointer type info flags from the -/// given qualifier. -static unsigned ComputeQualifierFlags(Qualifiers Quals) { - unsigned Flags = 0; - - if (Quals.hasConst()) - Flags |= ItaniumRTTIBuilder::PTI_Const; - if (Quals.hasVolatile()) - Flags |= ItaniumRTTIBuilder::PTI_Volatile; - if (Quals.hasRestrict()) - Flags |= ItaniumRTTIBuilder::PTI_Restrict; - - return Flags; -} - /// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info /// for the given Objective-C object type. void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) { @@ -3322,23 +3313,44 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) { } } +/// Compute the flags for a __pbase_type_info, and remove the corresponding +/// pieces from \p Type. +static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) { + unsigned Flags = 0; + + if (Type.isConstQualified()) + Flags |= ItaniumRTTIBuilder::PTI_Const; + if (Type.isVolatileQualified()) + Flags |= ItaniumRTTIBuilder::PTI_Volatile; + if (Type.isRestrictQualified()) + Flags |= ItaniumRTTIBuilder::PTI_Restrict; + Type = Type.getUnqualifiedType(); + + // Itanium C++ ABI 2.9.5p7: + // When the abi::__pbase_type_info is for a direct or indirect pointer to an + // incomplete class type, the incomplete target type flag is set. + if (ContainsIncompleteClassType(Type)) + Flags |= ItaniumRTTIBuilder::PTI_Incomplete; + + if (auto *Proto = Type->getAs()) { + if (Proto->isNothrow(Ctx)) { + Flags |= ItaniumRTTIBuilder::PTI_Noexcept; + Type = Ctx.getFunctionType( + Proto->getReturnType(), Proto->getParamTypes(), + Proto->getExtProtoInfo().withExceptionSpec(EST_None)); + } + } + + return Flags; +} + /// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct, /// used for pointer types. void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { - Qualifiers Quals; - QualType UnqualifiedPointeeTy = - CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals); - // Itanium C++ ABI 2.9.5p7: // __flags is a flag word describing the cv-qualification and other // attributes of the type pointed to - unsigned Flags = ComputeQualifierFlags(Quals); - - // Itanium C++ ABI 2.9.5p7: - // When the abi::__pbase_type_info is for a direct or indirect pointer to an - // incomplete class type, the incomplete target type flag is set. - if (ContainsIncompleteClassType(UnqualifiedPointeeTy)) - Flags |= PTI_Incomplete; + unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); llvm::Type *UnsignedIntLTy = CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy); @@ -3348,7 +3360,7 @@ void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) { // __pointee is a pointer to the std::type_info derivation for the // unqualified type being pointed to. llvm::Constant *PointeeTypeInfo = - ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy); + ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy); Fields.push_back(PointeeTypeInfo); } @@ -3358,23 +3370,12 @@ void ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { QualType PointeeTy = Ty->getPointeeType(); - Qualifiers Quals; - QualType UnqualifiedPointeeTy = - CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals); - // Itanium C++ ABI 2.9.5p7: // __flags is a flag word describing the cv-qualification and other // attributes of the type pointed to. - unsigned Flags = ComputeQualifierFlags(Quals); + unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy); const RecordType *ClassType = cast(Ty->getClass()); - - // Itanium C++ ABI 2.9.5p7: - // When the abi::__pbase_type_info is for a direct or indirect pointer to an - // incomplete class type, the incomplete target type flag is set. - if (ContainsIncompleteClassType(UnqualifiedPointeeTy)) - Flags |= PTI_Incomplete; - if (IsIncompleteClassType(ClassType)) Flags |= PTI_ContainingClassIncomplete; @@ -3386,7 +3387,7 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) { // __pointee is a pointer to the std::type_info derivation for the // unqualified type being pointed to. llvm::Constant *PointeeTypeInfo = - ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy); + ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy); Fields.push_back(PointeeTypeInfo); // Itanium C++ ABI 2.9.5p9: diff --git a/test/CodeGenCXX/rtti-qualfn.cpp b/test/CodeGenCXX/rtti-qualfn.cpp new file mode 100644 index 0000000000..329cd50547 --- /dev/null +++ b/test/CodeGenCXX/rtti-qualfn.cpp @@ -0,0 +1,23 @@ +// RUN: %clang_cc1 -std=c++1z -I%S %s -triple x86_64-linux-gnu -emit-llvm -o - -fcxx-exceptions | FileCheck %s + +#include "typeinfo" + +struct A {}; + +// CHECK-DAG: @_ZTIFvvE = linkonce_odr constant { i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv120__function_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([5 x i8], [5 x i8]* @_ZTSFvvE, i32 0, i32 0) }, comdat +// CHECK-DAG: @_ZTIPDoFvvE = linkonce_odr constant { i8*, i8*, i32, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv119__pointer_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([8 x i8], [8 x i8]* @_ZTSPDoFvvE, i32 0, i32 0), i32 64, i8* bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*) }, comdat +auto &ti_noexcept_ptr = typeid(void (A::*)() noexcept); +// CHECK-DAG: @_ZTIM1ADoFvvE = linkonce_odr constant { i8*, i8*, i32, i8*, i8* } { i8* bitcast (i8** getelementptr inbounds (i8*, i8** @_ZTVN10__cxxabiv129__pointer_to_member_type_infoE, i64 2) to i8*), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @_ZTSM1ADoFvvE, i32 0, i32 0), i32 64, i8* bitcast ({ i8*, i8* }* @_ZTIFvvE to i8*), i8* bitcast ({ i8*, i8* }* @_ZTI1A to i8*) }, comdat +auto &ti_noexcept_memptr = typeid(void (A::*)() noexcept); + +// CHECK-LABEL: define void @_Z1fv( +__attribute__((noreturn)) void f() noexcept { + // CHECK: call void @__cxa_throw({{.*}}@_ZTIPDoFvvE + throw f; +} + +// CHECK-LABEL: define void @_Z1gM1ADoFvvE( +void g(__attribute__((noreturn)) void (A::*p)() noexcept) { + // CHECK: call void @__cxa_throw({{.*}}@_ZTIM1ADoFvvE + throw p; +} diff --git a/www/cxx_status.html b/www/cxx_status.html index 86d65d18de..cd11299f85 100644 --- a/www/cxx_status.html +++ b/www/cxx_status.html @@ -612,9 +612,7 @@ as the draft C++1z standard evolves. Make exception specifications part of the type system P0012R1 - Partial - + SVN __has_include in preprocessor conditionals