From 08419a75ac15b96959edfbdde9eebec72fad74a5 Mon Sep 17 00:00:00 2001 From: zebullax Date: Thu, 30 Oct 2025 01:30:51 +0900 Subject: [PATCH] Fix `is_noexcept` for implicit noexcept destructors when marked as default or deleted (#196) --- clang/lib/AST/ExprConstantMeta.cpp | 11 +++++------ clang/lib/Sema/SemaReflect.cpp | 8 +++++++- .../reflection/member-classification.pass.cpp | 10 ++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/clang/lib/AST/ExprConstantMeta.cpp b/clang/lib/AST/ExprConstantMeta.cpp index c8240ec62251..15478d1cfd9f 100644 --- a/clang/lib/AST/ExprConstantMeta.cpp +++ b/clang/lib/AST/ExprConstantMeta.cpp @@ -1481,13 +1481,12 @@ static bool isFunctionOrMethodNoexcept(const QualType QT) { if (T->isFunctionProtoType()) { // This covers (virtual) methods & functions const auto *FPT = T->getAs(); - switch (FPT->getExceptionSpecType()) { - case EST_BasicNoexcept: - case EST_NoexceptTrue: - return true; - default: - return false; + case EST_BasicNoexcept: + case EST_NoexceptTrue: + return true; + default: + return false; } } diff --git a/clang/lib/Sema/SemaReflect.cpp b/clang/lib/Sema/SemaReflect.cpp index 483903acfb00..24896a1407be 100644 --- a/clang/lib/Sema/SemaReflect.cpp +++ b/clang/lib/Sema/SemaReflect.cpp @@ -349,7 +349,13 @@ public: void EnsureInstantiationOfExceptionSpec(SourceLocation Loc, FunctionDecl *FD) override { - S.InstantiateExceptionSpec(Loc, FD); + const FunctionProtoType *Proto = FD->getType()->castAs(); + if (Proto->getExceptionSpecType() == EST_Uninstantiated) { + S.InstantiateExceptionSpec(Loc, FD); + } + if (Proto->getExceptionSpecType() == EST_Unevaluated) { + S.ResolveExceptionSpec(Loc, Proto); + } } QualType Substitute(TypeAliasTemplateDecl *TD, diff --git a/libcxx/test/std/experimental/reflection/member-classification.pass.cpp b/libcxx/test/std/experimental/reflection/member-classification.pass.cpp index cb3e1181dc52..be54037088c1 100644 --- a/libcxx/test/std/experimental/reflection/member-classification.pass.cpp +++ b/libcxx/test/std/experimental/reflection/member-classification.pass.cpp @@ -703,6 +703,16 @@ static_assert(!is_noexcept(type_of(^^EC::Something))); static_assert(!is_noexcept(^^E)); static_assert(!is_noexcept(^^E_Something)); static_assert(!is_noexcept(type_of(^^E_Something))); + +// Defaulted special members +struct DelDest { ~DelDest() = delete; }; +static_assert(is_noexcept (^^DelDest::~DelDest)); + +struct DefDest { ~DefDest() = default; }; +static_assert(is_noexcept (^^DefDest::~DefDest)); + +struct EmptyStruct { }; +static_assert(is_noexcept (^^EmptyStruct::~EmptyStruct)); } // namespace noexcept_functions // ================