Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #45: Implement is_noexcept meta function #56

Merged
merged 15 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions clang/lib/Sema/Metafunctions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ static bool is_explicit(APValue &Result, Sema &S, EvalFn Evaluator,
QualType ResultTy, SourceRange Range,
ArrayRef<Expr *> Args);

static bool is_noexcept(APValue &Result, Sema &S, EvalFn Evaluator,
QualType ResultTy, SourceRange Range,
ArrayRef<Expr *> Args);

static bool is_bit_field(APValue &Result, Sema &S, EvalFn Evaluator,
QualType ResultTy, SourceRange Range,
ArrayRef<Expr *> Args);
Expand Down Expand Up @@ -396,6 +400,7 @@ static constexpr Metafunction Metafunctions[] = {
{ Metafunction::MFRK_bool, 1, 1, is_deleted },
{ Metafunction::MFRK_bool, 1, 1, is_defaulted },
{ Metafunction::MFRK_bool, 1, 1, is_explicit },
{ Metafunction::MFRK_bool, 1, 1, is_noexcept },
{ Metafunction::MFRK_bool, 1, 1, is_bit_field },
{ Metafunction::MFRK_bool, 1, 1, has_static_storage_duration },
{ Metafunction::MFRK_bool, 1, 1, has_internal_linkage },
Expand Down Expand Up @@ -1103,6 +1108,25 @@ bool isAccessible(Sema &S, DeclContext *AccessDC, NamedDecl *D) {
return Result;
}

static bool isFunctionOrMethodNoexcept(const QualType QT) {
const Type* T = QT.getTypePtr();

if (T->isFunctionProtoType()) {
// This covers (virtual) methods & functions
const auto *FPT = T->getAs<FunctionProtoType>();

switch (FPT->getExceptionSpecType()) {
case EST_BasicNoexcept:
case EST_NoexceptTrue:
return true;
default:
return false;
}
}

return false;
}

// -----------------------------------------------------------------------------
// Metafunction implementations
// -----------------------------------------------------------------------------
Expand Down Expand Up @@ -2645,6 +2669,39 @@ bool is_explicit(APValue &Result, Sema &S, EvalFn Evaluator, QualType ResultTy,
llvm_unreachable("invalid reflection type");
}

bool is_noexcept(APValue &Result, Sema &S, EvalFn Evaluator, QualType ResultTy,
SourceRange Range, ArrayRef<Expr *> Args) {
assert(Args[0]->getType()->isReflectionType());
assert(ResultTy == S.Context.BoolTy);

APValue R;
if (!Evaluator(R, Args[0], true))
return true;

switch (R.getReflection().getKind()) {
case ReflectionValue::RK_null:
case ReflectionValue::RK_expr_result:
case ReflectionValue::RK_template:
case ReflectionValue::RK_namespace:
case ReflectionValue::RK_base_specifier:
case ReflectionValue::RK_data_member_spec:
return SetAndSucceed(Result, makeBool(S.Context, false));
case ReflectionValue::RK_type: {
const QualType QT = R.getReflectedType();
const auto result = isFunctionOrMethodNoexcept(QT);

return SetAndSucceed(Result, makeBool(S.Context, result));
}
case ReflectionValue::RK_declaration: {
const ValueDecl *D = R.getReflectedDecl();
const auto result = isFunctionOrMethodNoexcept(D->getType());

return SetAndSucceed(Result, makeBool(S.Context, result));
}
}
llvm_unreachable("invalid reflection type");
}

bool is_bit_field(APValue &Result, Sema &S, EvalFn Evaluator, QualType ResultTy,
SourceRange Range, ArrayRef<Expr *> Args) {
assert(Args[0]->getType()->isReflectionType());
Expand Down
8 changes: 8 additions & 0 deletions libcxx/include/experimental/meta
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ consteval auto is_override(info) -> bool;
consteval auto is_deleted(info) -> bool;
consteval auto is_defaulted(info) -> bool;
consteval auto is_explicit(info) -> bool;
consteval bool is_noexcept(info) -> bool;
consteval auto is_bit_field(info) -> bool;
consteval auto has_static_storage_duration(info) -> bool;
consteval auto has_internal_linkage(info) -> bool;
Expand Down Expand Up @@ -394,6 +395,7 @@ enum : unsigned {
__metafn_is_deleted,
__metafn_is_defaulted,
__metafn_is_explicit,
__metafn_is_noexcept,
__metafn_is_bit_field,
__metafn_has_static_storage_duration,
__metafn_has_internal_linkage,
Expand Down Expand Up @@ -907,6 +909,12 @@ consteval auto is_explicit(info r) -> bool {
return __metafunction(detail::__metafn_is_explicit, r);
}

// Returns whether the reflected function type, function or member function
// is noexcept.
consteval auto is_noexcept(info r) -> bool {
return __metafunction(detail::__metafn_is_noexcept, r);
}

// Returns whether the reflected class data member is a bit field.
consteval auto is_bit_field(info r) -> bool {
return __metafunction(detail::__metafn_is_bit_field, r);
Expand Down
Loading