@@ -147,10 +147,11 @@ TEST_F(InterpreterTest, DeclsAndStatements) {
147147}
148148
149149TEST_F (InterpreterTest, UndoCommand) {
150- #FIXME : This test doesn' t current work for Emscripten builds.
151- #It should be possible to make it work.For details on how it fails and
152- #the current progress to enable this test see
153- #the following Github issue https: // github.com/llvm/llvm-project/issues/153461
150+ // FIXME : This test doesn't current work for Emscripten builds.
151+ // It should be possible to make it work.For details on how it fails and
152+ // the current progress to enable this test see
153+ // the following Github issue https: //
154+ // github.com/llvm/llvm-project/issues/153461
154155#ifdef __EMSCRIPTEN__
155156 GTEST_SKIP () << " Test fails for Emscipten builds" ;
156157#endif
@@ -263,10 +264,11 @@ static NamedDecl *LookupSingleName(Interpreter &Interp, const char *Name) {
263264}
264265
265266TEST_F (InterpreterTest, InstantiateTemplate) {
266- #FIXME : This test doesn' t current work for Emscripten builds.
267- #It should be possible to make it work.For details on how it fails and
268- #the current progress to enable this test see
269- #the following Github issue https: // github.com/llvm/llvm-project/issues/153461
267+ // FIXME : This test doesn't current work for Emscripten builds.
268+ // It should be possible to make it work.For details on how it fails and
269+ // the current progress to enable this test see
270+ // the following Github issue https: //
271+ // github.com/llvm/llvm-project/issues/153461
270272#ifdef __EMSCRIPTEN__
271273 GTEST_SKIP () << " Test fails for Emscipten builds" ;
272274#endif
@@ -309,10 +311,211 @@ TEST_F(InterpreterTest, InstantiateTemplate) {
309311}
310312
311313TEST_F (InterpreterTest, Value) {
312- #FIXME : This test doesn' t current work for Emscripten builds.
313- #It should be possible to make it work.For details on how it fails and
314- #the current progress to enable this test see
315- #the following Github issue https: // github.com/llvm/llvm-project/issues/153461
314+ // FIXME : This test doesn't current work for Emscripten builds.
315+ // It should be possible to make it work.For details on how it fails and
316+ // the current progress to enable this test see
317+ // the following Github issue https: //
318+ // github.com/llvm/llvm-project/issues/153461
319+ ECT_TRUE (!!RecoverErr);
320+ }
321+
322+ // Here we test whether the user can mix declarations and statements. The
323+ // interpreter should be smart enough to recognize the declarations from the
324+ // statements and wrap the latter into a declaration, producing valid code.
325+
326+ TEST_F (InterpreterTest, DeclsAndStatements) {
327+ Args ExtraArgs = {" -Xclang" , " -diagnostic-log-file" , " -Xclang" , " -" };
328+
329+ // Create the diagnostic engine with unowned consumer.
330+ std::string DiagnosticOutput;
331+ llvm::raw_string_ostream DiagnosticsOS (DiagnosticOutput);
332+ DiagnosticOptions DiagOpts;
333+ auto DiagPrinter =
334+ std::make_unique<TextDiagnosticPrinter>(DiagnosticsOS, DiagOpts);
335+
336+ auto Interp = createInterpreter (ExtraArgs, DiagPrinter.get ());
337+ auto R1 = Interp->Parse (
338+ " int var1 = 42; extern \" C\" int printf(const char*, ...);" );
339+ // gtest doesn't expand into explicit bool conversions.
340+ EXPECT_TRUE (!!R1);
341+
342+ auto *PTU1 = R1->TUPart ;
343+ EXPECT_EQ (2U , DeclsSize (PTU1));
344+
345+ auto R2 = Interp->Parse (" var1++; printf(\" var1 value %d\\ n\" , var1);" );
346+ EXPECT_TRUE (!!R2);
347+ }
348+
349+ TEST_F (InterpreterTest, UndoCommand) {
350+ // FIXME : This test doesn't current work for Emscripten builds.
351+ // It should be possible to make it work.For details on how it fails and
352+ // the current progress to enable this test see
353+ // the following Github issue https: //
354+ // github.com/llvm/llvm-project/issues/153461
355+ #ifdef __EMSCRIPTEN__
356+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
357+ #endif
358+ Args ExtraArgs = {" -Xclang" , " -diagnostic-log-file" , " -Xclang" , " -" };
359+
360+ // Create the diagnostic engine with unowned consumer.
361+ std::string DiagnosticOutput;
362+ llvm::raw_string_ostream DiagnosticsOS (DiagnosticOutput);
363+ DiagnosticOptions DiagOpts;
364+ auto DiagPrinter =
365+ std::make_unique<TextDiagnosticPrinter>(DiagnosticsOS, DiagOpts);
366+
367+ auto Interp = createInterpreter (ExtraArgs, DiagPrinter.get ());
368+
369+ // Fail to undo.
370+ auto Err1 = Interp->Undo ();
371+ EXPECT_EQ (" Operation failed. No input left to undo" ,
372+ llvm::toString (std::move (Err1)));
373+ auto Err2 = Interp->Parse (" int foo = 42;" );
374+ EXPECT_TRUE (!!Err2);
375+ auto Err3 = Interp->Undo (2 );
376+ EXPECT_EQ (" Operation failed. Wanted to undo 2 inputs, only have 1." ,
377+ llvm::toString (std::move (Err3)));
378+
379+ // Succeed to undo.
380+ auto Err4 = Interp->Parse (" int x = 42;" );
381+ EXPECT_TRUE (!!Err4);
382+ auto Err5 = Interp->Undo ();
383+ EXPECT_FALSE (Err5);
384+ auto Err6 = Interp->Parse (" int x = 24;" );
385+ EXPECT_TRUE (!!Err6);
386+ auto Err7 = Interp->Parse (" #define X 42" );
387+ EXPECT_TRUE (!!Err7);
388+ auto Err8 = Interp->Undo ();
389+ EXPECT_FALSE (Err8);
390+ auto Err9 = Interp->Parse (" #define X 24" );
391+ EXPECT_TRUE (!!Err9);
392+
393+ // Undo input contains errors.
394+ auto Err10 = Interp->Parse (" int y = ;" );
395+ EXPECT_FALSE (!!Err10);
396+ EXPECT_EQ (" Parsing failed." , llvm::toString (Err10.takeError ()));
397+ auto Err11 = Interp->Parse (" int y = 42;" );
398+ EXPECT_TRUE (!!Err11);
399+ auto Err12 = Interp->Undo ();
400+ EXPECT_FALSE (Err12);
401+ }
402+
403+ static std::string MangleName (NamedDecl *ND) {
404+ ASTContext &C = ND->getASTContext ();
405+ std::unique_ptr<MangleContext> MangleC (C.createMangleContext ());
406+ std::string mangledName;
407+ llvm::raw_string_ostream RawStr (mangledName);
408+ MangleC->mangleName (ND, RawStr);
409+ return mangledName;
410+ }
411+
412+ TEST_F (InterpreterTest, FindMangledNameSymbol) {
413+ std::unique_ptr<Interpreter> Interp = createInterpreter ();
414+
415+ auto &PTU (cantFail (Interp->Parse (" int f(const char*) {return 0;}" )));
416+ EXPECT_EQ (1U , DeclsSize (PTU.TUPart ));
417+ auto R1DeclRange = PTU.TUPart ->decls ();
418+
419+ NamedDecl *FD = cast<FunctionDecl>(*R1DeclRange.begin ());
420+ // Lower the PTU
421+ if (llvm::Error Err = Interp->Execute (PTU)) {
422+ // We cannot execute on the platform.
423+ consumeError (std::move (Err));
424+ return ;
425+ }
426+
427+ std::string MangledName = MangleName (FD);
428+ auto Addr = Interp->getSymbolAddress (MangledName);
429+ EXPECT_FALSE (!Addr);
430+ EXPECT_NE (0U , Addr->getValue ());
431+ GlobalDecl GD (FD);
432+ EXPECT_EQ (*Addr, cantFail (Interp->getSymbolAddress (GD)));
433+ cantFail (
434+ Interp->ParseAndExecute (" extern \" C\" int printf(const char*,...);" ));
435+ Addr = Interp->getSymbolAddress (" printf" );
436+ EXPECT_FALSE (!Addr);
437+
438+ // FIXME: Re-enable when we investigate the way we handle dllimports on Win.
439+ #ifndef _WIN32
440+ EXPECT_EQ ((uintptr_t )&printf, Addr->getValue ());
441+ #endif // _WIN32
442+ }
443+
444+ static Value AllocateObject (TypeDecl *TD, Interpreter &Interp) {
445+ std::string Name = TD->getQualifiedNameAsString ();
446+ Value Addr;
447+ // FIXME: Consider providing an option in clang::Value to take ownership of
448+ // the memory created from the interpreter.
449+ // cantFail(Interp.ParseAndExecute("new " + Name + "()", &Addr));
450+
451+ // The lifetime of the temporary is extended by the clang::Value.
452+ cantFail (Interp.ParseAndExecute (Name + " ()" , &Addr));
453+ return Addr;
454+ }
455+
456+ static NamedDecl *LookupSingleName (Interpreter &Interp, const char *Name) {
457+ Sema &SemaRef = Interp.getCompilerInstance ()->getSema ();
458+ ASTContext &C = SemaRef.getASTContext ();
459+ DeclarationName DeclName = &C.Idents .get (Name);
460+ LookupResult R (SemaRef, DeclName, SourceLocation (), Sema::LookupOrdinaryName);
461+ SemaRef.LookupName (R, SemaRef.TUScope );
462+ assert (!R.empty ());
463+ return R.getFoundDecl ();
464+ }
465+
466+ TEST_F (InterpreterTest, InstantiateTemplate) {
467+ // FIXME : This test doesn't current work for Emscripten builds.
468+ // It should be possible to make it work.For details on how it fails and
469+ // the current progress to enable this test see
470+ // the following Github issue https: //
471+ // github.com/llvm/llvm-project/issues/153461
472+ #ifdef __EMSCRIPTEN__
473+ GTEST_SKIP () << " Test fails for Emscipten builds" ;
474+ #endif
475+ // FIXME: We cannot yet handle delayed template parsing. If we run with
476+ // -fdelayed-template-parsing we try adding the newly created decl to the
477+ // active PTU which causes an assert.
478+ std::vector<const char *> Args = {" -fno-delayed-template-parsing" };
479+ std::unique_ptr<Interpreter> Interp = createInterpreter (Args);
480+
481+ llvm::cantFail (Interp->Parse (" extern \" C\" int printf(const char*,...);"
482+ " class A {};"
483+ " struct B {"
484+ " template<typename T>"
485+ " static int callme(T) { return 42; }"
486+ " };" ));
487+ auto &PTU = llvm::cantFail (Interp->Parse (" auto _t = &B::callme<A*>;" ));
488+ auto PTUDeclRange = PTU.TUPart ->decls ();
489+ EXPECT_EQ (1 , std::distance (PTUDeclRange.begin (), PTUDeclRange.end ()));
490+
491+ // Lower the PTU
492+ if (llvm::Error Err = Interp->Execute (PTU)) {
493+ // We cannot execute on the platform.
494+ consumeError (std::move (Err));
495+ return ;
496+ }
497+
498+ TypeDecl *TD = cast<TypeDecl>(LookupSingleName (*Interp, " A" ));
499+ Value NewA = AllocateObject (TD, *Interp);
500+
501+ // Find back the template specialization
502+ VarDecl *VD = static_cast <VarDecl *>(*PTUDeclRange.begin ());
503+ UnaryOperator *UO = llvm::cast<UnaryOperator>(VD->getInit ());
504+ NamedDecl *TmpltSpec = llvm::cast<DeclRefExpr>(UO->getSubExpr ())->getDecl ();
505+
506+ std::string MangledName = MangleName (TmpltSpec);
507+ typedef int (*TemplateSpecFn)(void *);
508+ auto fn =
509+ cantFail (Interp->getSymbolAddress (MangledName)).toPtr <TemplateSpecFn>();
510+ EXPECT_EQ (42 , fn (NewA.getPtr ()));
511+ }
512+
513+ TEST_F (InterpreterTest, Value) {
514+ // FIXME : This test doesn't current work for Emscripten builds.
515+ // It should be possible to make it work.For details on how it fails and
516+ // the current progress to enable this test see
517+ // the following Github issue https: //
518+ // github.com/llvm/llvm-project/issues/153461
316519#ifdef __EMSCRIPTEN__
317520 GTEST_SKIP () << " Test fails for Emscipten builds" ;
318521#endif
0 commit comments