1//===- unittests/Interpreter/InterpreterTest.cpp --- Interpreter tests ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Unit tests for Clang's Interpreter library.
10//
11//===----------------------------------------------------------------------===//
12
13#include "clang/Interpreter/Interpreter.h"
14
15#include "clang/AST/Decl.h"
16#include "clang/AST/DeclGroup.h"
17#include "clang/AST/Mangle.h"
18#include "clang/Frontend/CompilerInstance.h"
19#include "clang/Frontend/TextDiagnosticPrinter.h"
20#include "clang/Interpreter/Value.h"
21#include "clang/Sema/Lookup.h"
22#include "clang/Sema/Sema.h"
23
24#include "llvm/ExecutionEngine/Orc/LLJIT.h"
25#include "llvm/Support/ManagedStatic.h"
26#include "llvm/Support/TargetSelect.h"
27
28#include "gmock/gmock.h"
29#include "gtest/gtest.h"
30
31using namespace clang;
32
33#if defined(_AIX)
34#define CLANG_INTERPRETER_NO_SUPPORT_EXEC
35#endif
36
37int Global = 42;
38// JIT reports symbol not found on Windows without the visibility attribute.
39REPL_EXTERNAL_VISIBILITY int getGlobal() { return Global; }
40REPL_EXTERNAL_VISIBILITY void setGlobal(int val) { Global = val; }
41
42namespace {
43using Args = std::vector<const char *>;
44static std::unique_ptr<Interpreter>
45createInterpreter(const Args &ExtraArgs = {},
46 DiagnosticConsumer *Client = nullptr) {
47 Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
48 ClangArgs.insert(position: ClangArgs.end(), first: ExtraArgs.begin(), last: ExtraArgs.end());
49 auto CB = clang::IncrementalCompilerBuilder();
50 CB.SetCompilerArgs(ClangArgs);
51 auto CI = cantFail(ValOrErr: CB.CreateCpp());
52 if (Client)
53 CI->getDiagnostics().setClient(client: Client, /*ShouldOwnClient=*/false);
54 return cantFail(ValOrErr: clang::Interpreter::create(CI: std::move(CI)));
55}
56
57static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
58 return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
59}
60
61TEST(InterpreterTest, Sanity) {
62 std::unique_ptr<Interpreter> Interp = createInterpreter();
63
64 using PTU = PartialTranslationUnit;
65
66 PTU &R1(cantFail(ValOrErr: Interp->Parse(Code: "void g(); void g() {}")));
67 EXPECT_EQ(2U, DeclsSize(R1.TUPart));
68
69 PTU &R2(cantFail(ValOrErr: Interp->Parse(Code: "int i;")));
70 EXPECT_EQ(1U, DeclsSize(R2.TUPart));
71}
72
73static std::string DeclToString(Decl *D) {
74 return llvm::cast<NamedDecl>(Val: D)->getQualifiedNameAsString();
75}
76
77TEST(InterpreterTest, IncrementalInputTopLevelDecls) {
78 std::unique_ptr<Interpreter> Interp = createInterpreter();
79 auto R1 = Interp->Parse(Code: "int var1 = 42; int f() { return var1; }");
80 // gtest doesn't expand into explicit bool conversions.
81 EXPECT_TRUE(!!R1);
82 auto R1DeclRange = R1->TUPart->decls();
83 EXPECT_EQ(2U, DeclsSize(R1->TUPart));
84 EXPECT_EQ("var1", DeclToString(*R1DeclRange.begin()));
85 EXPECT_EQ("f", DeclToString(*(++R1DeclRange.begin())));
86
87 auto R2 = Interp->Parse(Code: "int var2 = f();");
88 EXPECT_TRUE(!!R2);
89 auto R2DeclRange = R2->TUPart->decls();
90 EXPECT_EQ(1U, DeclsSize(R2->TUPart));
91 EXPECT_EQ("var2", DeclToString(*R2DeclRange.begin()));
92}
93
94TEST(InterpreterTest, Errors) {
95 Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
96
97 // Create the diagnostic engine with unowned consumer.
98 std::string DiagnosticOutput;
99 llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
100 auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>(
101 args&: DiagnosticsOS, args: new DiagnosticOptions());
102
103 auto Interp = createInterpreter(ExtraArgs, Client: DiagPrinter.get());
104 auto Err = Interp->Parse(Code: "intentional_error v1 = 42; ").takeError();
105 using ::testing::HasSubstr;
106 EXPECT_THAT(DiagnosticsOS.str(),
107 HasSubstr("error: unknown type name 'intentional_error'"));
108 EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err)));
109
110 auto RecoverErr = Interp->Parse(Code: "int var1 = 42;");
111 EXPECT_TRUE(!!RecoverErr);
112}
113
114// Here we test whether the user can mix declarations and statements. The
115// interpreter should be smart enough to recognize the declarations from the
116// statements and wrap the latter into a declaration, producing valid code.
117TEST(InterpreterTest, DeclsAndStatements) {
118 Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
119
120 // Create the diagnostic engine with unowned consumer.
121 std::string DiagnosticOutput;
122 llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
123 auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>(
124 args&: DiagnosticsOS, args: new DiagnosticOptions());
125
126 auto Interp = createInterpreter(ExtraArgs, Client: DiagPrinter.get());
127 auto R1 = Interp->Parse(
128 Code: "int var1 = 42; extern \"C\" int printf(const char*, ...);");
129 // gtest doesn't expand into explicit bool conversions.
130 EXPECT_TRUE(!!R1);
131
132 auto *PTU1 = R1->TUPart;
133 EXPECT_EQ(2U, DeclsSize(PTU1));
134
135 auto R2 = Interp->Parse(Code: "var1++; printf(\"var1 value %d\\n\", var1);");
136 EXPECT_TRUE(!!R2);
137}
138
139TEST(InterpreterTest, UndoCommand) {
140 Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
141
142 // Create the diagnostic engine with unowned consumer.
143 std::string DiagnosticOutput;
144 llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
145 auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>(
146 args&: DiagnosticsOS, args: new DiagnosticOptions());
147
148 auto Interp = createInterpreter(ExtraArgs, Client: DiagPrinter.get());
149
150 // Fail to undo.
151 auto Err1 = Interp->Undo();
152 EXPECT_EQ("Operation failed. Too many undos",
153 llvm::toString(std::move(Err1)));
154 auto Err2 = Interp->Parse(Code: "int foo = 42;");
155 EXPECT_TRUE(!!Err2);
156 auto Err3 = Interp->Undo(N: 2);
157 EXPECT_EQ("Operation failed. Too many undos",
158 llvm::toString(std::move(Err3)));
159
160 // Succeed to undo.
161 auto Err4 = Interp->Parse(Code: "int x = 42;");
162 EXPECT_TRUE(!!Err4);
163 auto Err5 = Interp->Undo();
164 EXPECT_FALSE(Err5);
165 auto Err6 = Interp->Parse(Code: "int x = 24;");
166 EXPECT_TRUE(!!Err6);
167 auto Err7 = Interp->Parse(Code: "#define X 42");
168 EXPECT_TRUE(!!Err7);
169 auto Err8 = Interp->Undo();
170 EXPECT_FALSE(Err8);
171 auto Err9 = Interp->Parse(Code: "#define X 24");
172 EXPECT_TRUE(!!Err9);
173
174 // Undo input contains errors.
175 auto Err10 = Interp->Parse(Code: "int y = ;");
176 EXPECT_FALSE(!!Err10);
177 EXPECT_EQ("Parsing failed.", llvm::toString(Err10.takeError()));
178 auto Err11 = Interp->Parse(Code: "int y = 42;");
179 EXPECT_TRUE(!!Err11);
180 auto Err12 = Interp->Undo();
181 EXPECT_FALSE(Err12);
182}
183
184static std::string MangleName(NamedDecl *ND) {
185 ASTContext &C = ND->getASTContext();
186 std::unique_ptr<MangleContext> MangleC(C.createMangleContext());
187 std::string mangledName;
188 llvm::raw_string_ostream RawStr(mangledName);
189 MangleC->mangleName(GD: ND, RawStr);
190 return RawStr.str();
191}
192
193static bool HostSupportsJit() {
194 auto J = llvm::orc::LLJITBuilder().create();
195 if (J)
196 return true;
197 LLVMConsumeError(Err: llvm::wrap(Err: J.takeError()));
198 return false;
199}
200
201struct LLVMInitRAII {
202 LLVMInitRAII() {
203 llvm::InitializeNativeTarget();
204 llvm::InitializeNativeTargetAsmPrinter();
205 }
206 ~LLVMInitRAII() { llvm::llvm_shutdown(); }
207} LLVMInit;
208
209#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
210TEST(IncrementalProcessing, DISABLED_FindMangledNameSymbol) {
211#else
212TEST(IncrementalProcessing, FindMangledNameSymbol) {
213#endif
214
215 std::unique_ptr<Interpreter> Interp = createInterpreter();
216
217 auto &PTU(cantFail(ValOrErr: Interp->Parse(Code: "int f(const char*) {return 0;}")));
218 EXPECT_EQ(1U, DeclsSize(PTU.TUPart));
219 auto R1DeclRange = PTU.TUPart->decls();
220
221 // We cannot execute on the platform.
222 if (!HostSupportsJit()) {
223 return;
224 }
225
226 NamedDecl *FD = cast<FunctionDecl>(*R1DeclRange.begin());
227 // Lower the PTU
228 if (llvm::Error Err = Interp->Execute(T&: PTU)) {
229 // We cannot execute on the platform.
230 consumeError(Err: std::move(Err));
231 return;
232 }
233
234 std::string MangledName = MangleName(ND: FD);
235 auto Addr = Interp->getSymbolAddress(IRName: MangledName);
236 EXPECT_FALSE(!Addr);
237 EXPECT_NE(0U, Addr->getValue());
238 GlobalDecl GD(FD);
239 EXPECT_EQ(*Addr, cantFail(Interp->getSymbolAddress(GD)));
240 cantFail(
241 Err: Interp->ParseAndExecute(Code: "extern \"C\" int printf(const char*,...);"));
242 Addr = Interp->getSymbolAddress(IRName: "printf");
243 EXPECT_FALSE(!Addr);
244
245 // FIXME: Re-enable when we investigate the way we handle dllimports on Win.
246#ifndef _WIN32
247 EXPECT_EQ((uintptr_t)&printf, Addr->getValue());
248#endif // _WIN32
249}
250
251static Value AllocateObject(TypeDecl *TD, Interpreter &Interp) {
252 std::string Name = TD->getQualifiedNameAsString();
253 Value Addr;
254 // FIXME: Consider providing an option in clang::Value to take ownership of
255 // the memory created from the interpreter.
256 // cantFail(Interp.ParseAndExecute("new " + Name + "()", &Addr));
257
258 // The lifetime of the temporary is extended by the clang::Value.
259 cantFail(Err: Interp.ParseAndExecute(Code: Name + "()", V: &Addr));
260 return Addr;
261}
262
263static NamedDecl *LookupSingleName(Interpreter &Interp, const char *Name) {
264 Sema &SemaRef = Interp.getCompilerInstance()->getSema();
265 ASTContext &C = SemaRef.getASTContext();
266 DeclarationName DeclName = &C.Idents.get(Name);
267 LookupResult R(SemaRef, DeclName, SourceLocation(), Sema::LookupOrdinaryName);
268 SemaRef.LookupName(R, S: SemaRef.TUScope);
269 assert(!R.empty());
270 return R.getFoundDecl();
271}
272
273#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
274TEST(IncrementalProcessing, DISABLED_InstantiateTemplate) {
275#else
276TEST(IncrementalProcessing, InstantiateTemplate) {
277#endif
278 // FIXME: We cannot yet handle delayed template parsing. If we run with
279 // -fdelayed-template-parsing we try adding the newly created decl to the
280 // active PTU which causes an assert.
281 std::vector<const char *> Args = {"-fno-delayed-template-parsing"};
282 std::unique_ptr<Interpreter> Interp = createInterpreter(ExtraArgs: Args);
283
284 llvm::cantFail(ValOrErr: Interp->Parse(Code: "extern \"C\" int printf(const char*,...);"
285 "class A {};"
286 "struct B {"
287 " template<typename T>"
288 " static int callme(T) { return 42; }"
289 "};"));
290 auto &PTU = llvm::cantFail(ValOrErr: Interp->Parse(Code: "auto _t = &B::callme<A*>;"));
291 auto PTUDeclRange = PTU.TUPart->decls();
292 EXPECT_EQ(1, std::distance(PTUDeclRange.begin(), PTUDeclRange.end()));
293
294 // We cannot execute on the platform.
295 if (!HostSupportsJit()) {
296 return;
297 }
298
299 // Lower the PTU
300 if (llvm::Error Err = Interp->Execute(T&: PTU)) {
301 // We cannot execute on the platform.
302 consumeError(Err: std::move(Err));
303 return;
304 }
305
306 TypeDecl *TD = cast<TypeDecl>(Val: LookupSingleName(Interp&: *Interp, Name: "A"));
307 Value NewA = AllocateObject(TD, Interp&: *Interp);
308
309 // Find back the template specialization
310 VarDecl *VD = static_cast<VarDecl *>(*PTUDeclRange.begin());
311 UnaryOperator *UO = llvm::cast<UnaryOperator>(Val: VD->getInit());
312 NamedDecl *TmpltSpec = llvm::cast<DeclRefExpr>(Val: UO->getSubExpr())->getDecl();
313
314 std::string MangledName = MangleName(ND: TmpltSpec);
315 typedef int (*TemplateSpecFn)(void *);
316 auto fn =
317 cantFail(ValOrErr: Interp->getSymbolAddress(IRName: MangledName)).toPtr<TemplateSpecFn>();
318 EXPECT_EQ(42, fn(NewA.getPtr()));
319}
320
321#ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
322TEST(InterpreterTest, DISABLED_Value) {
323#else
324TEST(InterpreterTest, Value) {
325#endif
326 // We cannot execute on the platform.
327 if (!HostSupportsJit())
328 return;
329
330 std::unique_ptr<Interpreter> Interp = createInterpreter();
331
332 Value V1;
333 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "int x = 42;"));
334 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "x", V: &V1));
335 EXPECT_TRUE(V1.isValid());
336 EXPECT_TRUE(V1.hasValue());
337 EXPECT_EQ(V1.getInt(), 42);
338 EXPECT_EQ(V1.convertTo<int>(), 42);
339 EXPECT_TRUE(V1.getType()->isIntegerType());
340 EXPECT_EQ(V1.getKind(), Value::K_Int);
341 EXPECT_FALSE(V1.isManuallyAlloc());
342
343 Value V1b;
344 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "char c = 42;"));
345 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "c", V: &V1b));
346 EXPECT_TRUE(V1b.getKind() == Value::K_Char_S ||
347 V1b.getKind() == Value::K_Char_U);
348
349 Value V2;
350 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "double y = 3.14;"));
351 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "y", V: &V2));
352 EXPECT_TRUE(V2.isValid());
353 EXPECT_TRUE(V2.hasValue());
354 EXPECT_EQ(V2.getDouble(), 3.14);
355 EXPECT_EQ(V2.convertTo<double>(), 3.14);
356 EXPECT_TRUE(V2.getType()->isFloatingType());
357 EXPECT_EQ(V2.getKind(), Value::K_Double);
358 EXPECT_FALSE(V2.isManuallyAlloc());
359
360 Value V3;
361 llvm::cantFail(Err: Interp->ParseAndExecute(
362 Code: "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
363 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "S{}", V: &V3));
364 EXPECT_TRUE(V3.isValid());
365 EXPECT_TRUE(V3.hasValue());
366 EXPECT_TRUE(V3.getType()->isRecordType());
367 EXPECT_EQ(V3.getKind(), Value::K_PtrOrObj);
368 EXPECT_TRUE(V3.isManuallyAlloc());
369
370 Value V4;
371 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "int getGlobal();"));
372 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "void setGlobal(int);"));
373 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "getGlobal()", V: &V4));
374 EXPECT_EQ(V4.getInt(), 42);
375 EXPECT_TRUE(V4.getType()->isIntegerType());
376
377 Value V5;
378 // Change the global from the compiled code.
379 setGlobal(43);
380 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "getGlobal()", V: &V5));
381 EXPECT_EQ(V5.getInt(), 43);
382 EXPECT_TRUE(V5.getType()->isIntegerType());
383
384 // Change the global from the interpreted code.
385 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "setGlobal(44);"));
386 EXPECT_EQ(getGlobal(), 44);
387
388 Value V6;
389 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "void foo() {}"));
390 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "foo()", V: &V6));
391 EXPECT_TRUE(V6.isValid());
392 EXPECT_FALSE(V6.hasValue());
393 EXPECT_TRUE(V6.getType()->isVoidType());
394 EXPECT_EQ(V6.getKind(), Value::K_Void);
395 EXPECT_FALSE(V2.isManuallyAlloc());
396
397 Value V7;
398 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "foo", V: &V7));
399 EXPECT_TRUE(V7.isValid());
400 EXPECT_TRUE(V7.hasValue());
401 EXPECT_TRUE(V7.getType()->isFunctionProtoType());
402 EXPECT_EQ(V7.getKind(), Value::K_PtrOrObj);
403 EXPECT_FALSE(V7.isManuallyAlloc());
404
405 Value V8;
406 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "struct SS{ void f() {} };"));
407 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "&SS::f", V: &V8));
408 EXPECT_TRUE(V8.isValid());
409 EXPECT_TRUE(V8.hasValue());
410 EXPECT_TRUE(V8.getType()->isMemberFunctionPointerType());
411 EXPECT_EQ(V8.getKind(), Value::K_PtrOrObj);
412 EXPECT_TRUE(V8.isManuallyAlloc());
413
414 Value V9;
415 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "struct A { virtual int f(); };"));
416 llvm::cantFail(
417 Err: Interp->ParseAndExecute(Code: "struct B : A { int f() { return 42; }};"));
418 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "int (B::*ptr)() = &B::f;"));
419 llvm::cantFail(Err: Interp->ParseAndExecute(Code: "ptr", V: &V9));
420 EXPECT_TRUE(V9.isValid());
421 EXPECT_TRUE(V9.hasValue());
422 EXPECT_TRUE(V9.getType()->isMemberFunctionPointerType());
423 EXPECT_EQ(V9.getKind(), Value::K_PtrOrObj);
424 EXPECT_TRUE(V9.isManuallyAlloc());
425}
426} // end anonymous namespace
427

source code of clang/unittests/Interpreter/InterpreterTest.cpp