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