Skip to content

Commit 8c8a9be

Browse files
committed
Improve the test coverage of the C API
1 parent 16c67f9 commit 8c8a9be

File tree

6 files changed

+133
-17
lines changed

6 files changed

+133
-17
lines changed

lib/Interpreter/CXCppInterOp.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -326,17 +326,15 @@ void clang_Interpreter_addIncludePath(CXInterpreter I, const char* dir) {
326326
getInterpreter(I)->AddIncludePath(dir);
327327
}
328328

329+
namespace Cpp {
330+
int Declare(compat::Interpreter& interp, const char* code, bool silent);
331+
} // namespace Cpp
332+
329333
enum CXErrorCode clang_Interpreter_declare(CXInterpreter I, const char* code,
330334
bool silent) {
331335
auto* interp = getInterpreter(I);
332-
auto& diag = interp->getSema().getDiagnostics();
333-
334-
const bool is_silent_old = diag.getSuppressAllDiagnostics();
335-
336-
diag.setSuppressAllDiagnostics(silent);
337-
const auto result = interp->declare(code);
338-
diag.setSuppressAllDiagnostics(is_silent_old);
339336

337+
const auto result = Cpp::Declare(*interp, code, silent);
340338
if (result)
341339
return CXError_Failure;
342340

lib/Interpreter/CppInterOp.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -818,12 +818,17 @@ namespace Cpp {
818818
return false;
819819
}
820820

821-
TCppFunction_t GetDefaultConstructor(TCppScope_t scope) {
821+
TCppFunction_t GetDefaultConstructor(compat::Interpreter& interp,
822+
TCppScope_t scope) {
822823
if (!HasDefaultConstructor(scope))
823824
return nullptr;
824825

825826
auto *CXXRD = (clang::CXXRecordDecl*)scope;
826-
return getSema().LookupDefaultConstructor(CXXRD);
827+
return interp.getCI()->getSema().LookupDefaultConstructor(CXXRD);
828+
}
829+
830+
TCppFunction_t GetDefaultConstructor(TCppScope_t scope) {
831+
return GetDefaultConstructor(getInterp(), scope);
827832
}
828833

829834
TCppFunction_t GetDestructor(TCppScope_t scope) {
@@ -2983,9 +2988,7 @@ namespace Cpp {
29832988
};
29842989
} // namespace
29852990

2986-
int Declare(const char* code, bool silent) {
2987-
auto& I = getInterp();
2988-
2991+
int Declare(compat::Interpreter& I, const char* code, bool silent) {
29892992
if (silent) {
29902993
clangSilent diagSuppr(I.getSema().getDiagnostics());
29912994
return I.declare(code);
@@ -2994,6 +2997,10 @@ namespace Cpp {
29942997
return I.declare(code);
29952998
}
29962999

3000+
int Declare(const char* code, bool silent) {
3001+
return Declare(getInterp(), code, silent);
3002+
}
3003+
29973004
int Process(const char *code) {
29983005
return getInterp().process(code);
29993006
}
@@ -3477,7 +3484,7 @@ namespace Cpp {
34773484
if (!HasDefaultConstructor(Class))
34783485
return nullptr;
34793486

3480-
auto* const Ctor = GetDefaultConstructor(Class);
3487+
auto* const Ctor = GetDefaultConstructor(interp, Class);
34813488
if (JitCall JC = MakeFunctionCallable(&interp, Ctor)) {
34823489
if (arena) {
34833490
JC.Invoke(&arena, {}, (void*)~0); // Tell Invoke to use placement new.

unittests/CppInterOp/FunctionReflectionTest.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include "clang/Interpreter/CppInterOp.h"
77
#include "clang/Sema/Sema.h"
88

9+
#include "clang-c/CXCppInterOp.h"
10+
911
#include "gtest/gtest.h"
1012

1113
#include <string>
@@ -105,6 +107,20 @@ TEST(FunctionReflectionTest, GetClassMethods) {
105107
std::vector<Cpp::TCppFunction_t> methods5;
106108
Cpp::GetClassMethods(nullptr, methods5);
107109
EXPECT_EQ(methods5.size(), 0);
110+
111+
// C API
112+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
113+
auto C_API_SHIM = [&](Cpp::TCppFunction_t method) {
114+
auto Str = clang_getFunctionSignature(
115+
make_scope(static_cast<clang::Decl*>(method), I));
116+
auto Res = std::string(get_c_string(Str));
117+
dispose_string(Str);
118+
return Res;
119+
};
120+
EXPECT_EQ(C_API_SHIM(methods0[0]), "int A::f1(int a, int b)");
121+
// Clean up resources
122+
clang_Interpreter_takeInterpreterAsPtr(I);
123+
clang_Interpreter_dispose(I);
108124
}
109125

110126
TEST(FunctionReflectionTest, ConstructorInGetClassMethods) {
@@ -161,6 +177,15 @@ TEST(FunctionReflectionTest, HasDefaultConstructor) {
161177
EXPECT_TRUE(Cpp::HasDefaultConstructor(Decls[0]));
162178
EXPECT_TRUE(Cpp::HasDefaultConstructor(Decls[1]));
163179
EXPECT_FALSE(Cpp::HasDefaultConstructor(Decls[3]));
180+
181+
// C API
182+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
183+
EXPECT_TRUE(clang_hasDefaultConstructor(make_scope(Decls[0], I)));
184+
EXPECT_TRUE(clang_hasDefaultConstructor(make_scope(Decls[1], I)));
185+
EXPECT_FALSE(clang_hasDefaultConstructor(make_scope(Decls[3], I)));
186+
// Clean up resources
187+
clang_Interpreter_takeInterpreterAsPtr(I);
188+
clang_Interpreter_dispose(I);
164189
}
165190

166191
TEST(FunctionReflectionTest, GetDestructor) {
@@ -189,6 +214,14 @@ TEST(FunctionReflectionTest, GetDestructor) {
189214
EXPECT_TRUE(DeletedDtor);
190215
EXPECT_TRUE(Cpp::IsFunctionDeleted(DeletedDtor));
191216
EXPECT_FALSE(Cpp::GetDestructor(Decls[3]));
217+
218+
// C API
219+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
220+
EXPECT_TRUE(clang_getDestructor(make_scope(Decls[0], I)).data[0]);
221+
EXPECT_TRUE(clang_getDestructor(make_scope(Decls[1], I)).data[0]);
222+
// Clean up resources
223+
clang_Interpreter_takeInterpreterAsPtr(I);
224+
clang_Interpreter_dispose(I);
192225
}
193226

194227
TEST(FunctionReflectionTest, GetFunctionsUsingName) {
@@ -509,6 +542,17 @@ TEST(FunctionReflectionTest, IsTemplatedFunction) {
509542
EXPECT_FALSE(Cpp::IsTemplatedFunction(Decls[3]));
510543
EXPECT_FALSE(Cpp::IsTemplatedFunction(SubDeclsC1[1]));
511544
EXPECT_TRUE(Cpp::IsTemplatedFunction(SubDeclsC1[2]));
545+
546+
// C API
547+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
548+
EXPECT_FALSE(clang_isTemplatedFunction(make_scope(Decls[0], I)));
549+
EXPECT_TRUE(clang_isTemplatedFunction(make_scope(Decls[1], I)));
550+
EXPECT_FALSE(clang_isTemplatedFunction(make_scope(Decls[3], I)));
551+
EXPECT_FALSE(clang_isTemplatedFunction(make_scope(SubDeclsC1[1], I)));
552+
EXPECT_TRUE(clang_isTemplatedFunction(make_scope(SubDeclsC1[2], I)));
553+
// Clean up resources
554+
clang_Interpreter_takeInterpreterAsPtr(I);
555+
clang_Interpreter_dispose(I);
512556
}
513557

514558
TEST(FunctionReflectionTest, ExistsFunctionTemplate) {
@@ -529,6 +573,14 @@ TEST(FunctionReflectionTest, ExistsFunctionTemplate) {
529573
EXPECT_TRUE(Cpp::ExistsFunctionTemplate("f", 0));
530574
EXPECT_TRUE(Cpp::ExistsFunctionTemplate("f", Decls[1]));
531575
EXPECT_FALSE(Cpp::ExistsFunctionTemplate("f", Decls[2]));
576+
577+
// C API
578+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
579+
EXPECT_TRUE(clang_existsFunctionTemplate("f", make_scope(Decls[1], I)));
580+
EXPECT_FALSE(clang_existsFunctionTemplate("f", make_scope(Decls[2], I)));
581+
// Clean up resources
582+
clang_Interpreter_takeInterpreterAsPtr(I);
583+
clang_Interpreter_dispose(I);
532584
}
533585

534586
TEST(FunctionReflectionTest, InstantiateTemplateFunctionFromString) {
@@ -862,6 +914,17 @@ TEST(FunctionReflectionTest, JitCallAdvanced) {
862914
EXPECT_TRUE(object) << "Failed to call the ctor.";
863915
// Building a wrapper with a typedef decl must be possible.
864916
Cpp::Destruct(object, Decls[1]);
917+
918+
// C API
919+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
920+
auto S = clang_getDefaultConstructor(make_scope(Decls[0], I));
921+
void* object_c = nullptr;
922+
clang_invoke(S, &object_c, nullptr, 0, nullptr);
923+
EXPECT_TRUE(object_c) << "Failed to call the ctor.";
924+
clang_destruct(object_c, make_scope(Decls[1], I), true);
925+
// Clean up resources
926+
clang_Interpreter_takeInterpreterAsPtr(I);
927+
clang_Interpreter_dispose(I);
865928
}
866929

867930

@@ -1210,6 +1273,23 @@ TEST(FunctionReflectionTest, Construct) {
12101273
Cpp::Deallocate(scope, where);
12111274
output = testing::internal::GetCapturedStdout();
12121275
EXPECT_EQ(output, "Constructor Executed");
1276+
output.clear();
1277+
1278+
// C API
1279+
testing::internal::CaptureStdout();
1280+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
1281+
auto scope_c = make_scope(static_cast<clang::Decl*>(scope), I);
1282+
auto object_c = clang_construct(scope_c, nullptr);
1283+
EXPECT_TRUE(object_c != nullptr);
1284+
output = testing::internal::GetCapturedStdout();
1285+
EXPECT_EQ(output, "Constructor Executed");
1286+
output.clear();
1287+
auto dummy = clang_allocate(8);
1288+
EXPECT_TRUE(dummy);
1289+
clang_deallocate(dummy);
1290+
// Clean up resources
1291+
clang_Interpreter_takeInterpreterAsPtr(I);
1292+
clang_Interpreter_dispose(I);
12131293
}
12141294

12151295
TEST(FunctionReflectionTest, Destruct) {
@@ -1250,4 +1330,17 @@ TEST(FunctionReflectionTest, Destruct) {
12501330
Cpp::Deallocate(scope, object);
12511331
output = testing::internal::GetCapturedStdout();
12521332
EXPECT_EQ(output, "Destructor Executed");
1333+
1334+
// C API
1335+
testing::internal::CaptureStdout();
1336+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
1337+
auto scope_c = make_scope(static_cast<clang::Decl*>(scope), I);
1338+
auto object_c = clang_construct(scope_c, nullptr);
1339+
clang_destruct(object_c, scope_c, true);
1340+
output = testing::internal::GetCapturedStdout();
1341+
EXPECT_EQ(output, "Destructor Executed");
1342+
output.clear();
1343+
// Clean up resources
1344+
clang_Interpreter_takeInterpreterAsPtr(I);
1345+
clang_Interpreter_dispose(I);
12531346
}

unittests/CppInterOp/InterpreterTest.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "clang/Basic/Version.h"
1515

16+
#include <clang-c/CXErrorCode.h>
1617
#include "clang-c/CXCppInterOp.h"
1718

1819
#include "llvm/ADT/SmallString.h"
@@ -82,16 +83,26 @@ TEST(InterpreterTest, Process) {
8283
#endif
8384
if (llvm::sys::RunningOnValgrind())
8485
GTEST_SKIP() << "XFAIL due to Valgrind report";
85-
Cpp::CreateInterpreter();
86+
auto* I = Cpp::CreateInterpreter();
8687
EXPECT_TRUE(Cpp::Process("") == 0);
8788
EXPECT_TRUE(Cpp::Process("int a = 12;") == 0);
8889
EXPECT_FALSE(Cpp::Process("error_here;") == 0);
8990
// Linker/JIT error.
9091
EXPECT_FALSE(Cpp::Process("int f(); int res = f();") == 0);
92+
93+
// C API
94+
auto CXI = clang_createInterpreterFromRawPtr(I);
95+
clang_Interpreter_declare(CXI, "#include <iostream>", false);
96+
clang_Interpreter_process(CXI, "int c = 42;");
97+
auto* CXV = clang_createValue();
98+
auto Res = clang_Interpreter_evaluate(CXI, "c", CXV);
99+
EXPECT_EQ(Res, CXError_Success);
100+
clang_Value_dispose(CXV);
101+
clang_Interpreter_dispose(CXI);
91102
}
92103

93104
TEST(InterpreterTest, CreateInterpreter) {
94-
auto I = Cpp::CreateInterpreter();
105+
auto* I = Cpp::CreateInterpreter();
95106
EXPECT_TRUE(I);
96107
// Check if the default standard is c++14
97108

@@ -118,6 +129,9 @@ TEST(InterpreterTest, CreateInterpreter) {
118129
auto CXI = clang_createInterpreterFromRawPtr(I);
119130
auto CLI = clang_Interpreter_getClangInterpreter(CXI);
120131
EXPECT_TRUE(CLI);
132+
133+
clang_Interpreter_addSearchPath(CXI, "dummy", false, false);
134+
clang_Interpreter_addIncludePath(CXI, "dummy");
121135
auto I2 = clang_Interpreter_takeInterpreterAsPtr(CXI);
122136
EXPECT_EQ(I, I2);
123137
clang_Interpreter_dispose(CXI);

unittests/CppInterOp/ScopeReflectionTest.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include "llvm/Support/Valgrind.h"
1717

18+
#include "clang-c/CXCppInterOp.h"
19+
1820
#include "gtest/gtest.h"
1921

2022
#include <string>
@@ -816,7 +818,7 @@ TEST(ScopeReflectionTest, InstantiateNNTPClassTemplate) {
816818
/*type_size*/ args1.size()));
817819

818820
// C API
819-
auto I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
821+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
820822
CXTemplateArgInfo Args1[] = {{IntTy, "5"}};
821823
auto C_API_SHIM = [&](auto Decl) {
822824
return clang_instantiateTemplate(make_scope(Decl, I), Args1, 1).data[0];

unittests/CppInterOp/TypeReflectionTest.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#include "clang/Frontend/CompilerInstance.h"
66
#include "clang/Sema/Sema.h"
77

8+
#include "clang-c/CXCppInterOp.h"
9+
810
#include "gtest/gtest.h"
911

1012
#include <cstdint>
@@ -354,7 +356,7 @@ TEST(TypeReflectionTest, GetComplexType) {
354356
EXPECT_EQ(get_complex_type_as_string("double"), "_Complex double");
355357

356358
// C API
357-
auto I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
359+
auto* I = clang_createInterpreterFromRawPtr(Cpp::GetInterpreter());
358360
auto C_API_SHIM = [&](const std::string& element_type) {
359361
auto ElementQT = Cpp::GetType(element_type);
360362
CXQualType EQT = {CXType_Unexposed, {ElementQT, I}};

0 commit comments

Comments
 (0)