Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 19dc435

Browse files
committed
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
1 parent f865452 commit 19dc435

File tree

3 files changed

+66
-44
lines changed

3 files changed

+66
-44
lines changed

Diff for: lib/CodeGen/ItaniumCXXABI.cpp

+42-41
Original file line numberDiff line numberDiff line change
@@ -2474,7 +2474,13 @@ class ItaniumRTTIBuilder {
24742474

24752475
/// PTI_ContainingClassIncomplete - Containing class is incomplete.
24762476
/// (in pointer to member).
2477-
PTI_ContainingClassIncomplete = 0x10
2477+
PTI_ContainingClassIncomplete = 0x10,
2478+
2479+
/// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
2480+
//PTI_TransactionSafe = 0x20,
2481+
2482+
/// PTI_Noexcept - Pointee is noexcept function (C++1z).
2483+
PTI_Noexcept = 0x40,
24782484
};
24792485

24802486
// VMI type info flags.
@@ -3124,21 +3130,6 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force,
31243130
return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy);
31253131
}
31263132

3127-
/// ComputeQualifierFlags - Compute the pointer type info flags from the
3128-
/// given qualifier.
3129-
static unsigned ComputeQualifierFlags(Qualifiers Quals) {
3130-
unsigned Flags = 0;
3131-
3132-
if (Quals.hasConst())
3133-
Flags |= ItaniumRTTIBuilder::PTI_Const;
3134-
if (Quals.hasVolatile())
3135-
Flags |= ItaniumRTTIBuilder::PTI_Volatile;
3136-
if (Quals.hasRestrict())
3137-
Flags |= ItaniumRTTIBuilder::PTI_Restrict;
3138-
3139-
return Flags;
3140-
}
3141-
31423133
/// BuildObjCObjectTypeInfo - Build the appropriate kind of type_info
31433134
/// for the given Objective-C object type.
31443135
void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
@@ -3322,23 +3313,44 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
33223313
}
33233314
}
33243315

3316+
/// Compute the flags for a __pbase_type_info, and remove the corresponding
3317+
/// pieces from \p Type.
3318+
static unsigned extractPBaseFlags(ASTContext &Ctx, QualType &Type) {
3319+
unsigned Flags = 0;
3320+
3321+
if (Type.isConstQualified())
3322+
Flags |= ItaniumRTTIBuilder::PTI_Const;
3323+
if (Type.isVolatileQualified())
3324+
Flags |= ItaniumRTTIBuilder::PTI_Volatile;
3325+
if (Type.isRestrictQualified())
3326+
Flags |= ItaniumRTTIBuilder::PTI_Restrict;
3327+
Type = Type.getUnqualifiedType();
3328+
3329+
// Itanium C++ ABI 2.9.5p7:
3330+
// When the abi::__pbase_type_info is for a direct or indirect pointer to an
3331+
// incomplete class type, the incomplete target type flag is set.
3332+
if (ContainsIncompleteClassType(Type))
3333+
Flags |= ItaniumRTTIBuilder::PTI_Incomplete;
3334+
3335+
if (auto *Proto = Type->getAs<FunctionProtoType>()) {
3336+
if (Proto->isNothrow(Ctx)) {
3337+
Flags |= ItaniumRTTIBuilder::PTI_Noexcept;
3338+
Type = Ctx.getFunctionType(
3339+
Proto->getReturnType(), Proto->getParamTypes(),
3340+
Proto->getExtProtoInfo().withExceptionSpec(EST_None));
3341+
}
3342+
}
3343+
3344+
return Flags;
3345+
}
3346+
33253347
/// BuildPointerTypeInfo - Build an abi::__pointer_type_info struct,
33263348
/// used for pointer types.
33273349
void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
3328-
Qualifiers Quals;
3329-
QualType UnqualifiedPointeeTy =
3330-
CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
3331-
33323350
// Itanium C++ ABI 2.9.5p7:
33333351
// __flags is a flag word describing the cv-qualification and other
33343352
// attributes of the type pointed to
3335-
unsigned Flags = ComputeQualifierFlags(Quals);
3336-
3337-
// Itanium C++ ABI 2.9.5p7:
3338-
// When the abi::__pbase_type_info is for a direct or indirect pointer to an
3339-
// incomplete class type, the incomplete target type flag is set.
3340-
if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
3341-
Flags |= PTI_Incomplete;
3353+
unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
33423354

33433355
llvm::Type *UnsignedIntLTy =
33443356
CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
@@ -3348,7 +3360,7 @@ void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
33483360
// __pointee is a pointer to the std::type_info derivation for the
33493361
// unqualified type being pointed to.
33503362
llvm::Constant *PointeeTypeInfo =
3351-
ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy);
3363+
ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
33523364
Fields.push_back(PointeeTypeInfo);
33533365
}
33543366

@@ -3358,23 +3370,12 @@ void
33583370
ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
33593371
QualType PointeeTy = Ty->getPointeeType();
33603372

3361-
Qualifiers Quals;
3362-
QualType UnqualifiedPointeeTy =
3363-
CGM.getContext().getUnqualifiedArrayType(PointeeTy, Quals);
3364-
33653373
// Itanium C++ ABI 2.9.5p7:
33663374
// __flags is a flag word describing the cv-qualification and other
33673375
// attributes of the type pointed to.
3368-
unsigned Flags = ComputeQualifierFlags(Quals);
3376+
unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
33693377

33703378
const RecordType *ClassType = cast<RecordType>(Ty->getClass());
3371-
3372-
// Itanium C++ ABI 2.9.5p7:
3373-
// When the abi::__pbase_type_info is for a direct or indirect pointer to an
3374-
// incomplete class type, the incomplete target type flag is set.
3375-
if (ContainsIncompleteClassType(UnqualifiedPointeeTy))
3376-
Flags |= PTI_Incomplete;
3377-
33783379
if (IsIncompleteClassType(ClassType))
33793380
Flags |= PTI_ContainingClassIncomplete;
33803381

@@ -3386,7 +3387,7 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
33863387
// __pointee is a pointer to the std::type_info derivation for the
33873388
// unqualified type being pointed to.
33883389
llvm::Constant *PointeeTypeInfo =
3389-
ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(UnqualifiedPointeeTy);
3390+
ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(PointeeTy);
33903391
Fields.push_back(PointeeTypeInfo);
33913392

33923393
// Itanium C++ ABI 2.9.5p9:

Diff for: test/CodeGenCXX/rtti-qualfn.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -std=c++1z -I%S %s -triple x86_64-linux-gnu -emit-llvm -o - -fcxx-exceptions | FileCheck %s
2+
3+
#include "typeinfo"
4+
5+
struct A {};
6+
7+
// 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
8+
// 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
9+
auto &ti_noexcept_ptr = typeid(void (A::*)() noexcept);
10+
// 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
11+
auto &ti_noexcept_memptr = typeid(void (A::*)() noexcept);
12+
13+
// CHECK-LABEL: define void @_Z1fv(
14+
__attribute__((noreturn)) void f() noexcept {
15+
// CHECK: call void @__cxa_throw({{.*}}@_ZTIPDoFvvE
16+
throw f;
17+
}
18+
19+
// CHECK-LABEL: define void @_Z1gM1ADoFvvE(
20+
void g(__attribute__((noreturn)) void (A::*p)() noexcept) {
21+
// CHECK: call void @__cxa_throw({{.*}}@_ZTIM1ADoFvvE
22+
throw p;
23+
}

Diff for: www/cxx_status.html

+1-3
Original file line numberDiff line numberDiff line change
@@ -612,9 +612,7 @@ <h2 id="cxx17">C++1z implementation status</h2>
612612
<tr>
613613
<td>Make exception specifications part of the type system</td>
614614
<td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html">P0012R1</a></td>
615-
<td class="partial" align="center">Partial</td>
616-
<!-- We don't correctly support throwing noexcept function types and
617-
catching as non-noexcept yet. -->
615+
<td class="svn" align="center">SVN</td>
618616
</tr>
619617
<tr>
620618
<td><tt>__has_include</tt> in preprocessor conditionals</td>

0 commit comments

Comments
 (0)