1 //===- unittests/Interpreter/InterpreterTest.cpp --- Interpreter tests ----===//
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
7 //===----------------------------------------------------------------------===//
9 // Unit tests for Clang's Interpreter library.
11 //===----------------------------------------------------------------------===//
13 #include "clang/Interpreter/Interpreter.h"
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"
24 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
25 #include "llvm/Support/ManagedStatic.h"
26 #include "llvm/Support/TargetSelect.h"
28 #include "gmock/gmock.h"
29 #include "gtest/gtest.h"
31 using namespace clang
;
34 #define CLANG_INTERPRETER_NO_SUPPORT_EXEC
38 // JIT reports symbol not found on Windows without the visibility attribute.
39 REPL_EXTERNAL_VISIBILITY
int getGlobal() { return Global
; }
40 REPL_EXTERNAL_VISIBILITY
void setGlobal(int val
) { Global
= val
; }
43 using Args
= std::vector
<const char *>;
44 static std::unique_ptr
<Interpreter
>
45 createInterpreter(const Args
&ExtraArgs
= {},
46 DiagnosticConsumer
*Client
= nullptr) {
47 Args ClangArgs
= {"-Xclang", "-emit-llvm-only"};
48 ClangArgs
.insert(ClangArgs
.end(), ExtraArgs
.begin(), ExtraArgs
.end());
49 auto CB
= clang::IncrementalCompilerBuilder();
50 CB
.SetCompilerArgs(ClangArgs
);
51 auto CI
= cantFail(CB
.CreateCpp());
53 CI
->getDiagnostics().setClient(Client
, /*ShouldOwnClient=*/false);
54 return cantFail(clang::Interpreter::create(std::move(CI
)));
57 static size_t DeclsSize(TranslationUnitDecl
*PTUDecl
) {
58 return std::distance(PTUDecl
->decls().begin(), PTUDecl
->decls().end());
61 TEST(InterpreterTest
, Sanity
) {
62 std::unique_ptr
<Interpreter
> Interp
= createInterpreter();
64 using PTU
= PartialTranslationUnit
;
66 PTU
&R1(cantFail(Interp
->Parse("void g(); void g() {}")));
67 EXPECT_EQ(2U, DeclsSize(R1
.TUPart
));
69 PTU
&R2(cantFail(Interp
->Parse("int i;")));
70 EXPECT_EQ(1U, DeclsSize(R2
.TUPart
));
73 static std::string
DeclToString(Decl
*D
) {
74 return llvm::cast
<NamedDecl
>(D
)->getQualifiedNameAsString();
77 TEST(InterpreterTest
, IncrementalInputTopLevelDecls
) {
78 std::unique_ptr
<Interpreter
> Interp
= createInterpreter();
79 auto R1
= Interp
->Parse("int var1 = 42; int f() { return var1; }");
80 // gtest doesn't expand into explicit bool conversions.
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())));
87 auto R2
= Interp
->Parse("int var2 = f();");
89 auto R2DeclRange
= R2
->TUPart
->decls();
90 EXPECT_EQ(1U, DeclsSize(R2
->TUPart
));
91 EXPECT_EQ("var2", DeclToString(*R2DeclRange
.begin()));
94 TEST(InterpreterTest
, Errors
) {
95 Args ExtraArgs
= {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
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 DiagnosticsOS
, new DiagnosticOptions());
103 auto Interp
= createInterpreter(ExtraArgs
, DiagPrinter
.get());
104 auto Err
= Interp
->Parse("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
)));
110 auto RecoverErr
= Interp
->Parse("int var1 = 42;");
111 EXPECT_TRUE(!!RecoverErr
);
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.
117 TEST(InterpreterTest
, DeclsAndStatements
) {
118 Args ExtraArgs
= {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
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 DiagnosticsOS
, new DiagnosticOptions());
126 auto Interp
= createInterpreter(ExtraArgs
, DiagPrinter
.get());
127 auto R1
= Interp
->Parse(
128 "int var1 = 42; extern \"C\" int printf(const char*, ...);");
129 // gtest doesn't expand into explicit bool conversions.
132 auto *PTU1
= R1
->TUPart
;
133 EXPECT_EQ(2U, DeclsSize(PTU1
));
135 auto R2
= Interp
->Parse("var1++; printf(\"var1 value %d\\n\", var1);");
139 TEST(InterpreterTest
, UndoCommand
) {
140 Args ExtraArgs
= {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
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 DiagnosticsOS
, new DiagnosticOptions());
148 auto Interp
= createInterpreter(ExtraArgs
, DiagPrinter
.get());
151 auto Err1
= Interp
->Undo();
152 EXPECT_EQ("Operation failed. Too many undos",
153 llvm::toString(std::move(Err1
)));
154 auto Err2
= Interp
->Parse("int foo = 42;");
156 auto Err3
= Interp
->Undo(2);
157 EXPECT_EQ("Operation failed. Too many undos",
158 llvm::toString(std::move(Err3
)));
161 auto Err4
= Interp
->Parse("int x = 42;");
163 auto Err5
= Interp
->Undo();
165 auto Err6
= Interp
->Parse("int x = 24;");
167 auto Err7
= Interp
->Parse("#define X 42");
169 auto Err8
= Interp
->Undo();
171 auto Err9
= Interp
->Parse("#define X 24");
174 // Undo input contains errors.
175 auto Err10
= Interp
->Parse("int y = ;");
176 EXPECT_FALSE(!!Err10
);
177 EXPECT_EQ("Parsing failed.", llvm::toString(Err10
.takeError()));
178 auto Err11
= Interp
->Parse("int y = 42;");
179 EXPECT_TRUE(!!Err11
);
180 auto Err12
= Interp
->Undo();
184 static 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(ND
, RawStr
);
193 static bool HostSupportsJit() {
194 auto J
= llvm::orc::LLJITBuilder().create();
197 LLVMConsumeError(llvm::wrap(J
.takeError()));
201 struct LLVMInitRAII
{
203 llvm::InitializeNativeTarget();
204 llvm::InitializeNativeTargetAsmPrinter();
206 ~LLVMInitRAII() { llvm::llvm_shutdown(); }
209 #ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
210 TEST(IncrementalProcessing
, DISABLED_FindMangledNameSymbol
) {
212 TEST(IncrementalProcessing
, FindMangledNameSymbol
) {
215 std::unique_ptr
<Interpreter
> Interp
= createInterpreter();
217 auto &PTU(cantFail(Interp
->Parse("int f(const char*) {return 0;}")));
218 EXPECT_EQ(1U, DeclsSize(PTU
.TUPart
));
219 auto R1DeclRange
= PTU
.TUPart
->decls();
221 // We cannot execute on the platform.
222 if (!HostSupportsJit()) {
226 NamedDecl
*FD
= cast
<FunctionDecl
>(*R1DeclRange
.begin());
228 if (llvm::Error Err
= Interp
->Execute(PTU
)) {
229 // We cannot execute on the platform.
230 consumeError(std::move(Err
));
234 std::string MangledName
= MangleName(FD
);
235 auto Addr
= Interp
->getSymbolAddress(MangledName
);
237 EXPECT_NE(0U, Addr
->getValue());
239 EXPECT_EQ(*Addr
, cantFail(Interp
->getSymbolAddress(GD
)));
241 Interp
->ParseAndExecute("extern \"C\" int printf(const char*,...);"));
242 Addr
= Interp
->getSymbolAddress("printf");
245 // FIXME: Re-enable when we investigate the way we handle dllimports on Win.
247 EXPECT_EQ((uintptr_t)&printf
, Addr
->getValue());
251 static void *AllocateObject(TypeDecl
*TD
, Interpreter
&Interp
) {
252 std::string Name
= TD
->getQualifiedNameAsString();
253 const clang::Type
*RDTy
= TD
->getTypeForDecl();
254 clang::ASTContext
&C
= Interp
.getCompilerInstance()->getASTContext();
255 size_t Size
= C
.getTypeSize(RDTy
);
256 void *Addr
= malloc(Size
);
258 // Tell the interpreter to call the default ctor with this memory. Synthesize:
259 // new (loc) ClassName;
260 static unsigned Counter
= 0;
261 std::stringstream SS
;
262 SS
<< "auto _v" << Counter
++ << " = "
264 // Windows needs us to prefix the hexadecimal value of a pointer with '0x'.
265 << std::hex
<< std::showbase
<< (size_t)Addr
<< ")" << Name
<< "();";
267 auto R
= Interp
.ParseAndExecute(SS
.str());
276 static NamedDecl
*LookupSingleName(Interpreter
&Interp
, const char *Name
) {
277 Sema
&SemaRef
= Interp
.getCompilerInstance()->getSema();
278 ASTContext
&C
= SemaRef
.getASTContext();
279 DeclarationName DeclName
= &C
.Idents
.get(Name
);
280 LookupResult
R(SemaRef
, DeclName
, SourceLocation(), Sema::LookupOrdinaryName
);
281 SemaRef
.LookupName(R
, SemaRef
.TUScope
);
283 return R
.getFoundDecl();
286 #ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
287 TEST(IncrementalProcessing
, DISABLED_InstantiateTemplate
) {
289 TEST(IncrementalProcessing
, InstantiateTemplate
) {
291 // FIXME: We cannot yet handle delayed template parsing. If we run with
292 // -fdelayed-template-parsing we try adding the newly created decl to the
293 // active PTU which causes an assert.
294 std::vector
<const char *> Args
= {"-fno-delayed-template-parsing"};
295 std::unique_ptr
<Interpreter
> Interp
= createInterpreter(Args
);
297 llvm::cantFail(Interp
->Parse("extern \"C\" int printf(const char*,...);"
300 " template<typename T>"
301 " static int callme(T) { return 42; }"
303 auto &PTU
= llvm::cantFail(Interp
->Parse("auto _t = &B::callme<A*>;"));
304 auto PTUDeclRange
= PTU
.TUPart
->decls();
305 EXPECT_EQ(1, std::distance(PTUDeclRange
.begin(), PTUDeclRange
.end()));
307 // We cannot execute on the platform.
308 if (!HostSupportsJit()) {
313 if (llvm::Error Err
= Interp
->Execute(PTU
)) {
314 // We cannot execute on the platform.
315 consumeError(std::move(Err
));
319 TypeDecl
*TD
= cast
<TypeDecl
>(LookupSingleName(*Interp
, "A"));
320 void *NewA
= AllocateObject(TD
, *Interp
);
322 // Find back the template specialization
323 VarDecl
*VD
= static_cast<VarDecl
*>(*PTUDeclRange
.begin());
324 UnaryOperator
*UO
= llvm::cast
<UnaryOperator
>(VD
->getInit());
325 NamedDecl
*TmpltSpec
= llvm::cast
<DeclRefExpr
>(UO
->getSubExpr())->getDecl();
327 std::string MangledName
= MangleName(TmpltSpec
);
328 typedef int (*TemplateSpecFn
)(void *);
330 cantFail(Interp
->getSymbolAddress(MangledName
)).toPtr
<TemplateSpecFn
>();
331 EXPECT_EQ(42, fn(NewA
));
335 #ifdef CLANG_INTERPRETER_NO_SUPPORT_EXEC
336 TEST(InterpreterTest
, DISABLED_Value
) {
338 TEST(InterpreterTest
, Value
) {
340 // We cannot execute on the platform.
341 if (!HostSupportsJit())
344 std::unique_ptr
<Interpreter
> Interp
= createInterpreter();
347 llvm::cantFail(Interp
->ParseAndExecute("int x = 42;"));
348 llvm::cantFail(Interp
->ParseAndExecute("x", &V1
));
349 EXPECT_TRUE(V1
.isValid());
350 EXPECT_TRUE(V1
.hasValue());
351 EXPECT_EQ(V1
.getInt(), 42);
352 EXPECT_EQ(V1
.convertTo
<int>(), 42);
353 EXPECT_TRUE(V1
.getType()->isIntegerType());
354 EXPECT_EQ(V1
.getKind(), Value::K_Int
);
355 EXPECT_FALSE(V1
.isManuallyAlloc());
358 llvm::cantFail(Interp
->ParseAndExecute("double y = 3.14;"));
359 llvm::cantFail(Interp
->ParseAndExecute("y", &V2
));
360 EXPECT_TRUE(V2
.isValid());
361 EXPECT_TRUE(V2
.hasValue());
362 EXPECT_EQ(V2
.getDouble(), 3.14);
363 EXPECT_EQ(V2
.convertTo
<double>(), 3.14);
364 EXPECT_TRUE(V2
.getType()->isFloatingType());
365 EXPECT_EQ(V2
.getKind(), Value::K_Double
);
366 EXPECT_FALSE(V2
.isManuallyAlloc());
369 llvm::cantFail(Interp
->ParseAndExecute(
370 "struct S { int* p; S() { p = new int(42); } ~S() { delete p; }};"));
371 llvm::cantFail(Interp
->ParseAndExecute("S{}", &V3
));
372 EXPECT_TRUE(V3
.isValid());
373 EXPECT_TRUE(V3
.hasValue());
374 EXPECT_TRUE(V3
.getType()->isRecordType());
375 EXPECT_EQ(V3
.getKind(), Value::K_PtrOrObj
);
376 EXPECT_TRUE(V3
.isManuallyAlloc());
379 llvm::cantFail(Interp
->ParseAndExecute("int getGlobal();"));
380 llvm::cantFail(Interp
->ParseAndExecute("void setGlobal(int);"));
381 llvm::cantFail(Interp
->ParseAndExecute("getGlobal()", &V4
));
382 EXPECT_EQ(V4
.getInt(), 42);
383 EXPECT_TRUE(V4
.getType()->isIntegerType());
386 // Change the global from the compiled code.
388 llvm::cantFail(Interp
->ParseAndExecute("getGlobal()", &V5
));
389 EXPECT_EQ(V5
.getInt(), 43);
390 EXPECT_TRUE(V5
.getType()->isIntegerType());
392 // Change the global from the interpreted code.
393 llvm::cantFail(Interp
->ParseAndExecute("setGlobal(44);"));
394 EXPECT_EQ(getGlobal(), 44);
397 llvm::cantFail(Interp
->ParseAndExecute("void foo() {}"));
398 llvm::cantFail(Interp
->ParseAndExecute("foo()", &V6
));
399 EXPECT_TRUE(V6
.isValid());
400 EXPECT_FALSE(V6
.hasValue());
401 EXPECT_TRUE(V6
.getType()->isVoidType());
402 EXPECT_EQ(V6
.getKind(), Value::K_Void
);
403 EXPECT_FALSE(V2
.isManuallyAlloc());
406 llvm::cantFail(Interp
->ParseAndExecute("foo", &V7
));
407 EXPECT_TRUE(V7
.isValid());
408 EXPECT_TRUE(V7
.hasValue());
409 EXPECT_TRUE(V7
.getType()->isFunctionProtoType());
410 EXPECT_EQ(V7
.getKind(), Value::K_PtrOrObj
);
411 EXPECT_FALSE(V7
.isManuallyAlloc());
414 llvm::cantFail(Interp
->ParseAndExecute("struct SS{ void f() {} };"));
415 llvm::cantFail(Interp
->ParseAndExecute("&SS::f", &V8
));
416 EXPECT_TRUE(V8
.isValid());
417 EXPECT_TRUE(V8
.hasValue());
418 EXPECT_TRUE(V8
.getType()->isMemberFunctionPointerType());
419 EXPECT_EQ(V8
.getKind(), Value::K_PtrOrObj
);
420 EXPECT_TRUE(V8
.isManuallyAlloc());
423 llvm::cantFail(Interp
->ParseAndExecute("struct A { virtual int f(); };"));
425 Interp
->ParseAndExecute("struct B : A { int f() { return 42; }};"));
426 llvm::cantFail(Interp
->ParseAndExecute("int (B::*ptr)() = &B::f;"));
427 llvm::cantFail(Interp
->ParseAndExecute("ptr", &V9
));
428 EXPECT_TRUE(V9
.isValid());
429 EXPECT_TRUE(V9
.hasValue());
430 EXPECT_TRUE(V9
.getType()->isMemberFunctionPointerType());
431 EXPECT_EQ(V9
.getKind(), Value::K_PtrOrObj
);
432 EXPECT_TRUE(V9
.isManuallyAlloc());
434 } // end anonymous namespace