Skip to content

Commit

Permalink
Issue #45: Implement is_noexcept meta function (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
delimbetov authored Jul 1, 2024
1 parent 9ac1246 commit cbc95f8
Show file tree
Hide file tree
Showing 3 changed files with 358 additions and 0 deletions.
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

0 comments on commit cbc95f8

Please sign in to comment.