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:
@@ -3324,31 +3324,62 @@ bool is_ACCESS(APValue &Result, ASTContext &C, MetaActions &Meta,
|
|||||||
llvm_unreachable("invalid reflection type");
|
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,
|
bool is_public(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||||
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
||||||
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
|
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
|
||||||
Decl *ContainingDecl) {
|
Decl *ContainingDecl) {
|
||||||
return is_ACCESS<AS_public>(Result, C, Meta, Evaluator, Diagnoser,
|
return is_ClassMember_ACCESS<AS_public>(
|
||||||
AllowInjection, ResultTy, Range, Args,
|
Result, C, Meta, Evaluator, Diagnoser,
|
||||||
ContainingDecl);
|
AllowInjection, ResultTy, Range, Args,
|
||||||
|
ContainingDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_protected(APValue &Result, ASTContext &C, MetaActions &Meta,
|
bool is_protected(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||||
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
||||||
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
|
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
|
||||||
Decl *ContainingDecl) {
|
Decl *ContainingDecl) {
|
||||||
return is_ACCESS<AS_protected>(Result, C, Meta, Evaluator, Diagnoser,
|
return is_ClassMember_ACCESS<AS_protected>(
|
||||||
AllowInjection, ResultTy, Range, Args,
|
Result, C, Meta, Evaluator, Diagnoser,
|
||||||
ContainingDecl);
|
AllowInjection, ResultTy, Range, Args,
|
||||||
|
ContainingDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_private(APValue &Result, ASTContext &C, MetaActions &Meta,
|
bool is_private(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||||
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
EvalFn Evaluator, DiagFn Diagnoser, bool AllowInjection,
|
||||||
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
|
QualType ResultTy, SourceRange Range, ArrayRef<Expr *> Args,
|
||||||
Decl *ContainingDecl) {
|
Decl *ContainingDecl) {
|
||||||
return is_ACCESS<AS_private>(Result, C, Meta, Evaluator, Diagnoser,
|
return is_ClassMember_ACCESS<AS_private>(
|
||||||
AllowInjection, ResultTy, Range, Args,
|
Result, C, Meta, Evaluator, Diagnoser,
|
||||||
ContainingDecl);
|
AllowInjection, ResultTy, Range, Args,
|
||||||
|
ContainingDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_virtual(APValue &Result, ASTContext &C, MetaActions &Meta,
|
bool is_virtual(APValue &Result, ASTContext &C, MetaActions &Meta,
|
||||||
@@ -3890,7 +3921,6 @@ bool is_class_member(APValue &Result, ASTContext &C, MetaActions &Meta,
|
|||||||
ArrayRef<Expr *> Args, Decl *ContainingDecl) {
|
ArrayRef<Expr *> Args, Decl *ContainingDecl) {
|
||||||
assert(Args[0]->getType()->isReflectionType());
|
assert(Args[0]->getType()->isReflectionType());
|
||||||
assert(ResultTy == C.BoolTy);
|
assert(ResultTy == C.BoolTy);
|
||||||
|
|
||||||
APValue Scratch;
|
APValue Scratch;
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
@@ -3898,8 +3928,15 @@ bool is_class_member(APValue &Result, ASTContext &C, MetaActions &Meta,
|
|||||||
if (!parent_of(Scratch, C, Meta, Evaluator, SwallowDiags, AllowInjection,
|
if (!parent_of(Scratch, C, Meta, Evaluator, SwallowDiags, AllowInjection,
|
||||||
C.MetaInfoTy, Range, Args, ContainingDecl)) {
|
C.MetaInfoTy, Range, Args, ContainingDecl)) {
|
||||||
assert(Scratch.isReflection());
|
assert(Scratch.isReflection());
|
||||||
result = Scratch.isReflectedType() &&
|
// For unscoped enumerators, parent_of will return its enumeration type
|
||||||
Scratch.getReflectedType()->isRecordType();
|
// 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));
|
return SetAndSucceed(Result, makeBool(C, result));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ module;
|
|||||||
#include <mdspan>
|
#include <mdspan>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <memory_resource>
|
#include <memory_resource>
|
||||||
|
#include <meta>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <numbers>
|
#include <numbers>
|
||||||
|
|||||||
@@ -392,4 +392,33 @@ struct D : A, protected B, private C {
|
|||||||
|
|
||||||
} // namespace bb_clang_p2996_issue_148_regression_test
|
} // 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() { }
|
int main() { }
|
||||||
|
|||||||
@@ -282,6 +282,8 @@ check-generated-output)
|
|||||||
--exclude 'ostream.pass.cpp' \
|
--exclude 'ostream.pass.cpp' \
|
||||||
--exclude 'transcoding.pass.cpp' \
|
--exclude 'transcoding.pass.cpp' \
|
||||||
--exclude 'underflow.pass.cpp' \
|
--exclude 'underflow.pass.cpp' \
|
||||||
|
--exclude 'define-aggregate.pass.cpp' \
|
||||||
|
--exclude 'names.pass.cpp' \
|
||||||
|| false
|
|| false
|
||||||
;;
|
;;
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in New Issue
Block a user