Skip to content

Commit 05eb59c

Browse files
committed
Add type info interfaces motivated by numba
- Add `IsSameType` used for matching arg types between numba inferred signatures and CppOverloads in cppyy. - Also added interfaces `IsIntegerType` and `IsFloatingType` that check if types have the respective representations. Used in the case of Numba where scoring based on reflection is required.
1 parent 28ba16e commit 05eb59c

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

include/clang/Interpreter/CppInterOp.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ namespace Cpp {
8888

8989
enum OperatorArity { kUnary = 1, kBinary, kBoth };
9090

91+
enum Signedness { kSigned = 1, kUnsigned, kAny };
92+
9193
/// A class modeling function calls for functions produced by the interpreter
9294
/// in compiled code. It provides an information if we are calling a standard
9395
/// function, constructor or destructor.
@@ -523,15 +525,32 @@ namespace Cpp {
523525
/// Checks if the provided parameter is a Plain Old Data Type (POD).
524526
CPPINTEROP_API bool IsPODType(TCppType_t type);
525527

528+
/// Checks if type has an integer representation
529+
CPPINTEROP_API bool IsIntegerType(TCppType_t type,
530+
Signedness s = Signedness::kAny);
531+
532+
/// Checks if type has a floating representation
533+
CPPINTEROP_API bool IsFloatingType(TCppType_t type);
534+
535+
/// Checks if two types are the equivalent
536+
/// i.e. have the same canonical type
537+
CPPINTEROP_API bool IsSameType(TCppType_t type_a, TCppType_t type_b);
538+
526539
/// Checks if type is a pointer
527540
CPPINTEROP_API bool IsPointerType(TCppType_t type);
528541

542+
/// Checks if type is a void pointer
543+
CPPINTEROP_API bool IsVoidPointerType(TCppType_t type);
544+
529545
/// Get the underlying pointee type
530546
CPPINTEROP_API TCppType_t GetPointeeType(TCppType_t type);
531547

532548
/// Checks if type is a reference
533549
CPPINTEROP_API bool IsReferenceType(TCppType_t type);
534550

551+
/// Get the type handle to the unqualified type
552+
CPPINTEROP_API TCppType_t GetUnqualifiedType(TCppType_t type);
553+
535554
/// Get the type that the reference refers to
536555
CPPINTEROP_API TCppType_t GetNonReferenceType(TCppType_t type);
537556

lib/Interpreter/CppInterOp.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,11 +1597,44 @@ namespace Cpp {
15971597
return QT.isPODType(getASTContext());
15981598
}
15991599

1600+
bool IsIntegerType(TCppType_t type, Signedness s) {
1601+
if (!type)
1602+
return false;
1603+
QualType QT = QualType::getFromOpaquePtr(type);
1604+
switch (s) {
1605+
case Signedness::kAny:
1606+
return QT->hasIntegerRepresentation();
1607+
1608+
case Signedness::kSigned:
1609+
return QT->hasSignedIntegerRepresentation();
1610+
1611+
case Signedness::kUnsigned:
1612+
return QT->hasUnsignedIntegerRepresentation();
1613+
}
1614+
return false;
1615+
}
1616+
1617+
bool IsFloatingType(TCppType_t type) {
1618+
QualType QT = QualType::getFromOpaquePtr(type);
1619+
return QT->hasFloatingRepresentation();
1620+
}
1621+
1622+
bool IsSameType(TCppType_t type_a, TCppType_t type_b) {
1623+
clang::QualType QT1 = clang::QualType::getFromOpaquePtr(type_a);
1624+
clang::QualType QT2 = clang::QualType::getFromOpaquePtr(type_b);
1625+
return getASTContext().hasSameType(QT1, QT2);
1626+
}
1627+
16001628
bool IsPointerType(TCppType_t type) {
16011629
QualType QT = QualType::getFromOpaquePtr(type);
16021630
return QT->isPointerType();
16031631
}
16041632

1633+
bool IsVoidPointerType(TCppType_t type) {
1634+
QualType QT = QualType::getFromOpaquePtr(type);
1635+
return QT->isVoidPointerType();
1636+
}
1637+
16051638
TCppType_t GetPointeeType(TCppType_t type) {
16061639
if (!IsPointerType(type))
16071640
return nullptr;
@@ -1621,8 +1654,17 @@ namespace Cpp {
16211654
return QT.getNonReferenceType().getAsOpaquePtr();
16221655
}
16231656

1657+
TCppType_t GetUnqualifiedType(TCppType_t type) {
1658+
if (!type)
1659+
return nullptr;
1660+
QualType QT = QualType::getFromOpaquePtr(type);
1661+
return QT.getUnqualifiedType().getAsOpaquePtr();
1662+
}
1663+
16241664
TCppType_t GetUnderlyingType(TCppType_t type)
16251665
{
1666+
if (!type)
1667+
return nullptr;
16261668
QualType QT = QualType::getFromOpaquePtr(type);
16271669
QT = QT->getCanonicalTypeUnqualified();
16281670

unittests/CppInterOp/TypeReflectionTest.cpp

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,3 +605,111 @@ TEST(TypeReflectionTest, IsFunctionPointerType) {
605605
EXPECT_FALSE(
606606
Cpp::IsFunctionPointerType(Cpp::GetVariableType(Cpp::GetNamed("i"))));
607607
}
608+
609+
TEST(TypeReflectionTest, IntegerTypes) {
610+
Cpp::CreateInterpreter();
611+
std::vector<Decl*> Decls;
612+
std::string code = R"(
613+
int a;
614+
int *b;
615+
double c;
616+
enum A { x, y };
617+
A evar = x;
618+
char k;
619+
long int l;
620+
unsigned int m;
621+
unsigned long n;
622+
)";
623+
624+
GetAllTopLevelDecls(code, Decls);
625+
626+
// Signedness defaults to Any and returns true for both signed and unsigned
627+
// types.
628+
EXPECT_TRUE(Cpp::IsIntegerType(Cpp::GetVariableType(Decls[0])));
629+
EXPECT_FALSE(Cpp::IsIntegerType(Cpp::GetVariableType(Decls[1])));
630+
EXPECT_FALSE(Cpp::IsIntegerType(Cpp::GetVariableType(Decls[2])));
631+
EXPECT_TRUE(Cpp::IsIntegerType(Cpp::GetVariableType(Decls[4])));
632+
EXPECT_TRUE(Cpp::IsIntegerType(Cpp::GetVariableType(Decls[5])));
633+
EXPECT_TRUE(Cpp::IsIntegerType(Cpp::GetVariableType(Decls[6])));
634+
EXPECT_TRUE(Cpp::IsIntegerType(Cpp::GetVariableType(Decls[7]),
635+
Cpp::Signedness::kUnsigned));
636+
EXPECT_FALSE(Cpp::IsIntegerType(Cpp::GetVariableType(Decls[8]),
637+
Cpp::Signedness::kSigned));
638+
}
639+
640+
TEST(TypeReflectionTest, VoidPtrType) {
641+
Cpp::CreateInterpreter();
642+
std::vector<Decl*> Decls;
643+
std::string code = R"(
644+
class A {};
645+
using VoidPtrType = void*;
646+
VoidPtrType a = nullptr;
647+
void * b = nullptr;
648+
A *pa = nullptr;
649+
)";
650+
651+
GetAllTopLevelDecls(code, Decls);
652+
653+
EXPECT_EQ(Cpp::GetTypeAsString(Cpp::GetVariableType(Decls[2])),
654+
"VoidPtrType");
655+
EXPECT_TRUE(Cpp::IsVoidPointerType(Cpp::GetVariableType(Decls[2])));
656+
EXPECT_TRUE(Cpp::IsVoidPointerType(Cpp::GetVariableType(Decls[3])));
657+
EXPECT_FALSE(Cpp::IsVoidPointerType(Cpp::GetVariableType(Decls[4])));
658+
}
659+
660+
TEST(TypeReflectionTest, IsSameType) {
661+
Cpp::CreateInterpreter();
662+
std::vector<Decl*> Decls;
663+
664+
std::string code = R"(
665+
#include <cstdarg>
666+
#include <iostream>
667+
668+
typedef std::va_list VaListAlias;
669+
std::va_list va1;
670+
VaListAlias va2;
671+
672+
const int ci = 0;
673+
int const ic = 0;
674+
675+
signed int si1 = 0;
676+
int si2 = 0;
677+
678+
void *x;
679+
)";
680+
681+
GetAllTopLevelDecls(code, Decls);
682+
683+
#include <iostream>
684+
685+
ASTContext& Ctxt = Interp->getCI()->getASTContext();
686+
687+
Decls.assign(Decls.end() - 8, Decls.end());
688+
689+
EXPECT_TRUE(
690+
Cpp::IsSameType(Cpp::GetType("bool"), Ctxt.BoolTy.getAsOpaquePtr()));
691+
EXPECT_TRUE(
692+
Cpp::IsSameType(Cpp::GetType("float"), Ctxt.FloatTy.getAsOpaquePtr()));
693+
EXPECT_TRUE(
694+
Cpp::IsSameType(Cpp::GetType("long"), Ctxt.LongTy.getAsOpaquePtr()));
695+
EXPECT_TRUE(Cpp::IsSameType(Cpp::GetType("long long"),
696+
Ctxt.LongLongTy.getAsOpaquePtr()));
697+
EXPECT_TRUE(
698+
Cpp::IsSameType(Cpp::GetType("short"), Ctxt.ShortTy.getAsOpaquePtr()));
699+
EXPECT_TRUE(Cpp::IsSameType(Cpp::GetType("char"),
700+
Ctxt.SignedCharTy.getAsOpaquePtr()));
701+
EXPECT_TRUE(Cpp::IsSameType(Cpp::GetType("unsigned char"),
702+
Ctxt.UnsignedCharTy.getAsOpaquePtr()));
703+
EXPECT_TRUE(Cpp::IsSameType(Cpp::GetType("unsigned int"),
704+
Ctxt.UnsignedIntTy.getAsOpaquePtr()));
705+
EXPECT_TRUE(Cpp::IsSameType(Cpp::GetVariableType(Decls[7]),
706+
Ctxt.VoidPtrTy.getAsOpaquePtr()));
707+
708+
// Expect the typedef to std::va_list to be the same type
709+
EXPECT_TRUE(Cpp::IsSameType(Cpp::GetVariableType(Decls[1]),
710+
Cpp::GetVariableType(Decls[2])));
711+
EXPECT_TRUE(Cpp::IsSameType(Cpp::GetVariableType(Decls[3]),
712+
Cpp::GetVariableType(Decls[4])));
713+
EXPECT_TRUE(Cpp::IsSameType(Cpp::GetVariableType(Decls[5]),
714+
Cpp::GetVariableType(Decls[6])));
715+
}

0 commit comments

Comments
 (0)