Skip to content

Commit eeeece2

Browse files
authored
fix(parser): Implemented __is_member_object_pointer
1 parent 6982197 commit eeeece2

File tree

2 files changed

+73
-9
lines changed

2 files changed

+73
-9
lines changed

src/cxx/semantics.cc

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ void Semantics::name(NameAST* ast, NameSem* nameSem) {
8787

8888
void Semantics::nestedNameSpecifier(
8989
NestedNameSpecifierAST* ast, NestedNameSpecifierSem* nestedNameSpecifier) {
90+
if (!ast) return;
91+
if (ast->symbol) {
92+
nestedNameSpecifier->symbol = ast->symbol;
93+
return;
94+
}
9095
std::swap(nestedNameSpecifier_, nestedNameSpecifier);
9196
accept(ast);
9297
std::swap(nestedNameSpecifier_, nestedNameSpecifier);
@@ -274,18 +279,20 @@ void Semantics::visit(NestedNameSpecifierAST* ast) {
274279
for (auto it = ast->nameList; it; it = it->next) {
275280
NameSem name;
276281
this->name(it->value, &name);
277-
if (checkTypes_ && scope) {
278-
Symbol* sym = nullptr;
279-
if (unqualifiedLookup) {
280-
sym = scope->lookup(name.name, LookupOptions::kTypeOrNamespace);
281-
unqualifiedLookup = false;
282-
} else {
283-
sym = scope->find(name.name, LookupOptions::kTypeOrNamespace);
284-
}
285-
scope = sym ? sym->scope() : nullptr;
282+
if (!scope) continue;
283+
Symbol* sym = nullptr;
284+
if (unqualifiedLookup) {
285+
sym = scope->lookup(name.name, LookupOptions::kTypeOrNamespace);
286+
unqualifiedLookup = false;
287+
} else {
288+
sym = scope->find(name.name, LookupOptions::kTypeOrNamespace);
286289
}
290+
scope = sym ? sym->scope() : nullptr;
287291
}
292+
288293
if (scope) ast->symbol = scope->owner();
294+
295+
nestedNameSpecifier_->symbol = ast->symbol;
289296
}
290297

291298
void Semantics::visit(UsingDeclaratorAST* ast) {
@@ -742,6 +749,20 @@ void Semantics::visit(TypeTraitsExpressionAST* ast) {
742749
break;
743750
}
744751

752+
case TokenKind::T___IS_MEMBER_OBJECT_POINTER: {
753+
bool isMemberObjectPointer = false;
754+
755+
const auto ty = ast->typeIdList->value->type;
756+
757+
if (auto ptrTy = Type::cast<PointerToMemberType>(ty);
758+
ptrTy && !Type::is<FunctionType>(ptrTy->elementType())) {
759+
isMemberObjectPointer = true;
760+
}
761+
762+
ast->constValue = std::uint64_t(isMemberObjectPointer);
763+
break;
764+
}
765+
745766
case TokenKind::T___IS_SIGNED: {
746767
if (auto intTy = Type::cast<IntegerType>(ast->typeIdList->value->type)) {
747768
const auto isSigned = !intTy->isUnsigned();
@@ -1619,9 +1640,26 @@ void Semantics::visit(ReferenceOperatorAST* ast) {
16191640
void Semantics::visit(PtrToMemberOperatorAST* ast) {
16201641
NestedNameSpecifierSem nestedNameSpecifierSem;
16211642
nestedNameSpecifier(ast->nestedNameSpecifier, &nestedNameSpecifierSem);
1643+
16221644
for (auto it = ast->attributeList; it; it = it->next) attribute(it->value);
1645+
16231646
SpecifiersSem specifiers;
16241647
this->specifiers(ast->cvQualifierList, &specifiers);
1648+
1649+
auto qualifiers = specifiers.type.qualifiers();
1650+
1651+
auto classSymbol = dynamic_cast<ClassSymbol*>(nestedNameSpecifierSem.symbol);
1652+
1653+
if (!classSymbol) {
1654+
return;
1655+
}
1656+
1657+
const auto classTy = types_->classType(classSymbol);
1658+
1659+
QualifiedType ptrTy(
1660+
types_->pointerToMemberType(classTy, declarator_->type, qualifiers));
1661+
1662+
declarator_->type = ptrTy;
16251663
}
16261664

16271665
void Semantics::visit(FunctionDeclaratorAST* ast) {

tests/unit_tests/parser/type_traits.001.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,29 @@ static_assert(__is_function(decltype(foo)) == true);
151151
static_assert(__is_function(void) == false);
152152
static_assert(__is_function(int()) == true);
153153
static_assert(__is_function(int (*)()) == false);
154+
155+
// __is_member_object_pointer
156+
157+
struct Class {
158+
int i;
159+
};
160+
161+
using IntFieldT = int(Class::*);
162+
163+
int(Class::*intField) = nullptr;
164+
165+
static_assert(__is_member_object_pointer(decltype(intField)) == true);
166+
static_assert(__is_member_object_pointer(IntFieldT) == true);
167+
static_assert(__is_member_object_pointer(int(Class::*)) == true);
168+
169+
static_assert(__is_member_object_pointer(int (Class::*)()) == false);
170+
171+
namespace ns {
172+
struct list {
173+
struct iterator {
174+
int p;
175+
};
176+
};
177+
} // namespace ns
178+
179+
static_assert(__is_member_object_pointer(int(ns::list::iterator::*)) == true);

0 commit comments

Comments
 (0)