Fix is_public and is_class_member for scoped/unscoped enum (#194)

* Add bubble up for unscoped enum in membership check

Check membership for public check access

Signed-off-by: zebullax <zebullax@gmail.com>

* Fix golden copy for generated headers

Signed-off-by: zebullax <zebullax@gmail.com>

* Skip validation of reflection unittest that introduce non ascii character

Signed-off-by: zebullax <zebullax@gmail.com>

* Check class membership for is_private/protected/public

Signed-off-by: zebullax <zebullax@gmail.com>

---------

Signed-off-by: zebullax <zebullax@gmail.com>
This commit is contained in:
zebullax
2025-10-22 17:46:23 +09:00
committed by GitHub
parent 63a00eeeed
commit 9171cf41ef
4 changed files with 81 additions and 12 deletions

View File

@@ -3324,11 +3324,40 @@ bool is_ACCESS(APValue &Result, ASTContext &C, MetaActions &Meta,
llvm_unreachable("invalid reflection type");
}
template <AccessSpecifier AS>
static inline
bool is_ClassMember_ACCESS(APValue &Result, ASTContext &C, MetaActions &Meta,
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
Decl *ContainingDecl) {
[[maybe_unused]] bool scratch
= is_class_member(Result, C, Meta, Evaluator, Diagnoser,
AllowInjection, ResultTy, Range, Args,
ContainingDecl);
if (const bool isClassMember = Result.getInt().getBoolValue();isClassMember) {
return is_ACCESS<AS>(Result, C, Meta, Evaluator, Diagnoser,
AllowInjection, ResultTy, Range, Args,
ContainingDecl);
}
// fallthrough: base-class relationship
scratch = is_base(Result, C, Meta, Evaluator, Diagnoser,
AllowInjection, ResultTy, Range, Args,
ContainingDecl);
if (const bool isBaseClass = Result.getInt().getBoolValue();isBaseClass) {
return is_ACCESS<AS>(Result, C, Meta, Evaluator, Diagnoser,
AllowInjection, ResultTy, Range, Args,
ContainingDecl);
}
return false;
}
bool is_public(APValue &Result, ASTContext &C, MetaActions &Meta,
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
Decl *ContainingDecl) {
return is_ACCESS<AS_public>(Result, C, Meta, Evaluator, Diagnoser,
return is_ClassMember_ACCESS<AS_public>(
Result, C, Meta, Evaluator, Diagnoser,
AllowInjection, ResultTy, Range, Args,
ContainingDecl);
}
@@ -3337,7 +3366,8 @@ bool is_protected(APValue &Result, ASTContext &C, MetaActions &Meta,
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
Decl *ContainingDecl) {
return is_ACCESS<AS_protected>(Result, C, Meta, Evaluator, Diagnoser,
return is_ClassMember_ACCESS<AS_protected>(
Result, C, Meta, Evaluator, Diagnoser,
AllowInjection, ResultTy, Range, Args,
ContainingDecl);
}
@@ -3346,7 +3376,8 @@ bool is_private(APValue &Result, ASTContext &C, MetaActions &Meta,
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
Decl *ContainingDecl) {
return is_ACCESS<AS_private>(Result, C, Meta, Evaluator, Diagnoser,
return is_ClassMember_ACCESS<AS_private>(
Result, C, Meta, Evaluator, Diagnoser,
AllowInjection, ResultTy, Range, Args,
ContainingDecl);
}
@@ -3890,7 +3921,6 @@ bool is_class_member(APValue &Result, ASTContext &C, MetaActions &Meta,
ArrayRef<Expr *> Args, Decl *ContainingDecl) {
assert(Args[0]->getType()->isReflectionType());
assert(ResultTy == C.BoolTy);
APValue Scratch;
bool result = false;
@@ -3898,9 +3928,16 @@ bool is_class_member(APValue &Result, ASTContext &C, MetaActions &Meta,
if (!parent_of(Scratch, C, Meta, Evaluator, SwallowDiags, AllowInjection,
C.MetaInfoTy, Range, Args, ContainingDecl)) {
assert(Scratch.isReflection());
// For unscoped enumerators, parent_of will return its enumeration type
// We need now to lookup context on that type
if (Scratch.isReflectedType() && Scratch.getReflectedType()->isUnscopedEnumerationType()) {
Decl *D = findTypeDecl(Scratch.getReflectedType());
result = D && D->getDeclContext() && D->getDeclContext()->isRecord();
} else {
result = Scratch.isReflectedType() &&
Scratch.getReflectedType()->isRecordType();
}
}
return SetAndSucceed(Result, makeBool(C, result));
}

View File

@@ -82,6 +82,7 @@ module;
#include <mdspan>
#include <memory>
#include <memory_resource>
#include <meta>
#include <mutex>
#include <new>
#include <numbers>

View File

@@ -392,4 +392,33 @@ struct D : A, protected B, private C {
} // namespace bb_clang_p2996_issue_148_regression_test
// ========================================
// bb_clang_p2996_issue_193_regression_test
// ========================================
namespace bb_clang_p2996_issue_193_regression_test {
struct S {
enum E {
A
};
enum class SE {
B
};
};
static_assert(std::meta::is_class_member(^^S::E));
static_assert(std::meta::is_class_member(^^S::SE));
static_assert(std::meta::is_public(^^S::E));
static_assert(std::meta::is_public(^^S::SE));
static_assert(std::meta::is_class_member(^^S::E::A));
static_assert(!std::meta::is_class_member(^^S::SE::B));
static_assert(std::meta::is_public(^^S::E::A));
static_assert(!std::meta::is_public(^^S::SE::B));
} // namespace bb_clang_p2996_issue_193_regression_test
int main() { }

View File

@@ -282,6 +282,8 @@ check-generated-output)
--exclude 'ostream.pass.cpp' \
--exclude 'transcoding.pass.cpp' \
--exclude 'underflow.pass.cpp' \
--exclude 'define-aggregate.pass.cpp' \
--exclude 'names.pass.cpp' \
|| false
;;
#