Skip to content

Commit 088ba34

Browse files
committed
Support typedefs over anonymous tag declarations.
That's a quite often used idiom in C which hides the implementation details of the underlying tag declaration.
1 parent b122fc1 commit 088ba34

File tree

3 files changed

+36
-9
lines changed

3 files changed

+36
-9
lines changed

lib/Interpreter/CppInterOp.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2194,7 +2194,12 @@ namespace Cpp {
21942194
//
21952195
if (const TypeDecl *TD = dyn_cast<TypeDecl>(D)) {
21962196
// This is a class, struct, or union member.
2197-
QualType QT(TD->getTypeForDecl(), 0);
2197+
// Handle the typedefs to anonymous types.
2198+
QualType QT;
2199+
if (const TypedefDecl *Typedef = dyn_cast<const TypedefDecl>(TD))
2200+
QT = Typedef->getTypeSourceInfo()->getType();
2201+
else
2202+
QT = {TD->getTypeForDecl(), 0};
21982203
get_type_as_string(QT, class_name, Context, Policy);
21992204
} else if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
22002205
// This is a namespace member.

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,28 @@ TEST(FunctionReflectionTest, IsVirtualMethod) {
562562
EXPECT_FALSE(Cpp::IsVirtualMethod(SubDecls[3])); // y()
563563
}
564564

565+
TEST(FunctionReflectionTest, JitCallAdvanced) {
566+
std::vector<Decl*> Decls;
567+
std::string code = R"(
568+
typedef struct _name {
569+
_name() { p[0] = (void*)0x1; p[1] = (void*)0x2; p[2] = (void*)0x3; }
570+
void* p[3];
571+
} name;
572+
)";
573+
574+
GetAllTopLevelDecls(code, Decls);
575+
Sema *S = &Interp->getCI()->getSema();
576+
auto *CtorD =
577+
(clang::CXXConstructorDecl *)Cpp::GetDefaultConstructor(S, Decls[0]);
578+
auto Ctor = Cpp::MakeFunctionCallable((Cpp::TInterp_t)Interp.get(), CtorD);
579+
EXPECT_TRUE((bool)Ctor) << "Failed to build a wrapper for the ctor";
580+
void* object = nullptr;
581+
Ctor.Invoke(&object);
582+
EXPECT_TRUE(object) << "Failed to call the ctor.";
583+
// Building a wrapper with a typedef decl must be possible.
584+
Cpp::Destruct((Cpp::TInterp_t)Interp.get(), object, Decls[1]);
585+
}
586+
565587
TEST(FunctionReflectionTest, GetFunctionCallWrapper) {
566588
std::vector<Decl*> Decls;
567589
std::string code = R"(

unittests/CppInterOp/Utils.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,19 @@ void TestUtils::GetAllTopLevelDecls(const std::string& code, std::vector<Decl*>&
3838
for (auto DCI = T->decls_begin(), E = T->decls_end(); DCI != E; ++DCI) {
3939
if (DCI->m_Call != cling::Transaction::kCCIHandleTopLevelDecl)
4040
continue;
41-
assert(DCI->m_DGR.isSingleDecl());
42-
if (filter_implicitGenerated && (DCI->m_DGR.getSingleDecl())->isImplicit())
43-
continue;
44-
Decls.push_back(DCI->m_DGR.getSingleDecl());
41+
for (Decl *D : DCI->m_DGR) {
42+
if (filter_implicitGenerated && D->isImplicit())
43+
continue;
44+
Decls.push_back(D);
45+
}
4546
}
4647
#else
4748
PartialTranslationUnit *T = nullptr;
4849
Interp->process(code, /*Value*/nullptr, &T);
49-
for (auto DCI = T->TUPart->decls_begin(), E = T->TUPart->decls_end();
50-
DCI != E; ++DCI) {
51-
if (filter_implicitGenerated && (*DCI)->isImplicit())
50+
for (auto *D : T->TUPart->decls()) {
51+
if (filter_implicitGenerated && D->isImplicit())
5252
continue;
53-
Decls.push_back(*DCI);
53+
Decls.push_back(D);
5454
}
5555
#endif
5656
}

0 commit comments

Comments
 (0)