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/Sema/Lookup.h"
21 #include "clang/Sema/Sema.h"
22 
23 #include "llvm/Support/TargetSelect.h"
24 
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 
28 using namespace clang;
29 
30 namespace {
31 using Args = std::vector<const char *>;
32 static std::unique_ptr<Interpreter>
createInterpreter(const Args & ExtraArgs={},DiagnosticConsumer * Client=nullptr)33 createInterpreter(const Args &ExtraArgs = {},
34                   DiagnosticConsumer *Client = nullptr) {
35   Args ClangArgs = {"-Xclang", "-emit-llvm-only"};
36   ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end());
37   auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs));
38   if (Client)
39     CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false);
40   return cantFail(clang::Interpreter::create(std::move(CI)));
41 }
42 
DeclsSize(TranslationUnitDecl * PTUDecl)43 static size_t DeclsSize(TranslationUnitDecl *PTUDecl) {
44   return std::distance(PTUDecl->decls().begin(), PTUDecl->decls().end());
45 }
46 
TEST(InterpreterTest,Sanity)47 TEST(InterpreterTest, Sanity) {
48   std::unique_ptr<Interpreter> Interp = createInterpreter();
49 
50   using PTU = PartialTranslationUnit;
51 
52   PTU &R1(cantFail(Interp->Parse("void g(); void g() {}")));
53   EXPECT_EQ(2U, DeclsSize(R1.TUPart));
54 
55   PTU &R2(cantFail(Interp->Parse("int i;")));
56   EXPECT_EQ(1U, DeclsSize(R2.TUPart));
57 }
58 
DeclToString(Decl * D)59 static std::string DeclToString(Decl *D) {
60   return llvm::cast<NamedDecl>(D)->getQualifiedNameAsString();
61 }
62 
TEST(InterpreterTest,IncrementalInputTopLevelDecls)63 TEST(InterpreterTest, IncrementalInputTopLevelDecls) {
64   std::unique_ptr<Interpreter> Interp = createInterpreter();
65   auto R1 = Interp->Parse("int var1 = 42; int f() { return var1; }");
66   // gtest doesn't expand into explicit bool conversions.
67   EXPECT_TRUE(!!R1);
68   auto R1DeclRange = R1->TUPart->decls();
69   EXPECT_EQ(2U, DeclsSize(R1->TUPart));
70   EXPECT_EQ("var1", DeclToString(*R1DeclRange.begin()));
71   EXPECT_EQ("f", DeclToString(*(++R1DeclRange.begin())));
72 
73   auto R2 = Interp->Parse("int var2 = f();");
74   EXPECT_TRUE(!!R2);
75   auto R2DeclRange = R2->TUPart->decls();
76   EXPECT_EQ(1U, DeclsSize(R2->TUPart));
77   EXPECT_EQ("var2", DeclToString(*R2DeclRange.begin()));
78 }
79 
TEST(InterpreterTest,Errors)80 TEST(InterpreterTest, Errors) {
81   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
82 
83   // Create the diagnostic engine with unowned consumer.
84   std::string DiagnosticOutput;
85   llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
86   auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>(
87       DiagnosticsOS, new DiagnosticOptions());
88 
89   auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get());
90   auto Err = Interp->Parse("intentional_error v1 = 42; ").takeError();
91   using ::testing::HasSubstr;
92   EXPECT_THAT(DiagnosticsOS.str(),
93               HasSubstr("error: unknown type name 'intentional_error'"));
94   EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err)));
95 
96   auto RecoverErr = Interp->Parse("int var1 = 42;");
97   EXPECT_TRUE(!!RecoverErr);
98 }
99 
100 // Here we test whether the user can mix declarations and statements. The
101 // interpreter should be smart enough to recognize the declarations from the
102 // statements and wrap the latter into a declaration, producing valid code.
TEST(InterpreterTest,DeclsAndStatements)103 TEST(InterpreterTest, DeclsAndStatements) {
104   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
105 
106   // Create the diagnostic engine with unowned consumer.
107   std::string DiagnosticOutput;
108   llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
109   auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>(
110       DiagnosticsOS, new DiagnosticOptions());
111 
112   auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get());
113   auto R1 = Interp->Parse(
114       "int var1 = 42; extern \"C\" int printf(const char*, ...);");
115   // gtest doesn't expand into explicit bool conversions.
116   EXPECT_TRUE(!!R1);
117 
118   auto *PTU1 = R1->TUPart;
119   EXPECT_EQ(2U, DeclsSize(PTU1));
120 
121   // FIXME: Add support for wrapping and running statements.
122   auto R2 = Interp->Parse("var1++; printf(\"var1 value %d\\n\", var1);");
123   EXPECT_FALSE(!!R2);
124   using ::testing::HasSubstr;
125   EXPECT_THAT(DiagnosticsOS.str(),
126               HasSubstr("error: unknown type name 'var1'"));
127   auto Err = R2.takeError();
128   EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err)));
129 }
130 
TEST(InterpreterTest,UndoCommand)131 TEST(InterpreterTest, UndoCommand) {
132   Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"};
133 
134   // Create the diagnostic engine with unowned consumer.
135   std::string DiagnosticOutput;
136   llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput);
137   auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>(
138       DiagnosticsOS, new DiagnosticOptions());
139 
140   auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get());
141 
142   // Fail to undo.
143   auto Err1 = Interp->Undo();
144   EXPECT_EQ("Operation failed. Too many undos",
145             llvm::toString(std::move(Err1)));
146   auto Err2 = Interp->Parse("int foo = 42;");
147   EXPECT_TRUE(!!Err2);
148   auto Err3 = Interp->Undo(2);
149   EXPECT_EQ("Operation failed. Too many undos",
150             llvm::toString(std::move(Err3)));
151 
152   // Succeed to undo.
153   auto Err4 = Interp->Parse("int x = 42;");
154   EXPECT_TRUE(!!Err4);
155   auto Err5 = Interp->Undo();
156   EXPECT_FALSE(Err5);
157   auto Err6 = Interp->Parse("int x = 24;");
158   EXPECT_TRUE(!!Err6);
159   auto Err7 = Interp->Parse("#define X 42");
160   EXPECT_TRUE(!!Err7);
161   auto Err8 = Interp->Undo();
162   EXPECT_FALSE(Err8);
163   auto Err9 = Interp->Parse("#define X 24");
164   EXPECT_TRUE(!!Err9);
165 
166   // Undo input contains errors.
167   auto Err10 = Interp->Parse("int y = ;");
168   EXPECT_FALSE(!!Err10);
169   EXPECT_EQ("Parsing failed.", llvm::toString(Err10.takeError()));
170   auto Err11 = Interp->Parse("int y = 42;");
171   EXPECT_TRUE(!!Err11);
172   auto Err12 = Interp->Undo();
173   EXPECT_FALSE(Err12);
174 }
175 
MangleName(NamedDecl * ND)176 static std::string MangleName(NamedDecl *ND) {
177   ASTContext &C = ND->getASTContext();
178   std::unique_ptr<MangleContext> MangleC(C.createMangleContext());
179   std::string mangledName;
180   llvm::raw_string_ostream RawStr(mangledName);
181   MangleC->mangleName(ND, RawStr);
182   return RawStr.str();
183 }
184 
185 struct LLVMInitRAII {
LLVMInitRAII__anonc9140f9d0111::LLVMInitRAII186   LLVMInitRAII() {
187     llvm::InitializeNativeTarget();
188     llvm::InitializeNativeTargetAsmPrinter();
189   }
~LLVMInitRAII__anonc9140f9d0111::LLVMInitRAII190   ~LLVMInitRAII() { llvm::llvm_shutdown(); }
191 } LLVMInit;
192 
193 #ifdef _AIX
TEST(IncrementalProcessing,DISABLED_FindMangledNameSymbol)194 TEST(IncrementalProcessing, DISABLED_FindMangledNameSymbol) {
195 #else
196 TEST(IncrementalProcessing, FindMangledNameSymbol) {
197 #endif
198 
199   std::unique_ptr<Interpreter> Interp = createInterpreter();
200 
201   auto &PTU(cantFail(Interp->Parse("int f(const char*) {return 0;}")));
202   EXPECT_EQ(1U, DeclsSize(PTU.TUPart));
203   auto R1DeclRange = PTU.TUPart->decls();
204 
205   NamedDecl *FD = cast<FunctionDecl>(*R1DeclRange.begin());
206   // Lower the PTU
207   if (llvm::Error Err = Interp->Execute(PTU)) {
208     // We cannot execute on the platform.
209     consumeError(std::move(Err));
210     return;
211   }
212 
213   std::string MangledName = MangleName(FD);
214   auto Addr = cantFail(Interp->getSymbolAddress(MangledName));
215   EXPECT_NE(0U, Addr);
216   GlobalDecl GD(FD);
217   EXPECT_EQ(Addr, cantFail(Interp->getSymbolAddress(GD)));
218 }
219 
220 static void *AllocateObject(TypeDecl *TD, Interpreter &Interp) {
221   std::string Name = TD->getQualifiedNameAsString();
222   const clang::Type *RDTy = TD->getTypeForDecl();
223   clang::ASTContext &C = Interp.getCompilerInstance()->getASTContext();
224   size_t Size = C.getTypeSize(RDTy);
225   void *Addr = malloc(Size);
226 
227   // Tell the interpreter to call the default ctor with this memory. Synthesize:
228   // new (loc) ClassName;
229   static unsigned Counter = 0;
230   std::stringstream SS;
231   SS << "auto _v" << Counter++ << " = "
232      << "new ((void*)"
233      // Windows needs us to prefix the hexadecimal value of a pointer with '0x'.
234      << std::hex << std::showbase << (size_t)Addr << ")" << Name << "();";
235 
236   auto R = Interp.ParseAndExecute(SS.str());
237   if (!R) {
238     free(Addr);
239     return nullptr;
240   }
241 
242   return Addr;
243 }
244 
245 static NamedDecl *LookupSingleName(Interpreter &Interp, const char *Name) {
246   Sema &SemaRef = Interp.getCompilerInstance()->getSema();
247   ASTContext &C = SemaRef.getASTContext();
248   DeclarationName DeclName = &C.Idents.get(Name);
249   LookupResult R(SemaRef, DeclName, SourceLocation(), Sema::LookupOrdinaryName);
250   SemaRef.LookupName(R, SemaRef.TUScope);
251   assert(!R.empty());
252   return R.getFoundDecl();
253 }
254 
255 #ifdef _AIX
256 TEST(IncrementalProcessing, DISABLED_InstantiateTemplate) {
257 #else
258 TEST(IncrementalProcessing, InstantiateTemplate) {
259 #endif
260   // FIXME: We cannot yet handle delayed template parsing. If we run with
261   // -fdelayed-template-parsing we try adding the newly created decl to the
262   // active PTU which causes an assert.
263   std::vector<const char *> Args = {"-fno-delayed-template-parsing"};
264   std::unique_ptr<Interpreter> Interp = createInterpreter(Args);
265 
266   llvm::cantFail(Interp->Parse("void* operator new(__SIZE_TYPE__, void* __p);"
267                                "extern \"C\" int printf(const char*,...);"
268                                "class A {};"
269                                "struct B {"
270                                "  template<typename T>"
271                                "  static int callme(T) { return 42; }"
272                                "};"));
273   auto &PTU = llvm::cantFail(Interp->Parse("auto _t = &B::callme<A*>;"));
274   auto PTUDeclRange = PTU.TUPart->decls();
275   EXPECT_EQ(1, std::distance(PTUDeclRange.begin(), PTUDeclRange.end()));
276 
277   // Lower the PTU
278   if (llvm::Error Err = Interp->Execute(PTU)) {
279     // We cannot execute on the platform.
280     consumeError(std::move(Err));
281     return;
282   }
283 
284   TypeDecl *TD = cast<TypeDecl>(LookupSingleName(*Interp, "A"));
285   void *NewA = AllocateObject(TD, *Interp);
286 
287   // Find back the template specialization
288   VarDecl *VD = static_cast<VarDecl *>(*PTUDeclRange.begin());
289   UnaryOperator *UO = llvm::cast<UnaryOperator>(VD->getInit());
290   NamedDecl *TmpltSpec = llvm::cast<DeclRefExpr>(UO->getSubExpr())->getDecl();
291 
292   std::string MangledName = MangleName(TmpltSpec);
293   typedef int (*TemplateSpecFn)(void *);
294   auto fn = (TemplateSpecFn)cantFail(Interp->getSymbolAddress(MangledName));
295   EXPECT_EQ(42, fn(NewA));
296   free(NewA);
297 }
298 
299 } // end anonymous namespace
300