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/Frontend/CompilerInstance.h" 18 #include "clang/Frontend/TextDiagnosticPrinter.h" 19 20 #include "llvm/ADT/ArrayRef.h" 21 22 #include "gmock/gmock.h" 23 #include "gtest/gtest.h" 24 25 using namespace clang; 26 27 namespace { 28 using Args = std::vector<const char *>; 29 static std::unique_ptr<Interpreter> 30 createInterpreter(const Args &ExtraArgs = {}, 31 DiagnosticConsumer *Client = nullptr) { 32 Args ClangArgs = {"-Xclang", "-emit-llvm-only"}; 33 ClangArgs.insert(ClangArgs.end(), ExtraArgs.begin(), ExtraArgs.end()); 34 auto CI = cantFail(clang::IncrementalCompilerBuilder::create(ClangArgs)); 35 if (Client) 36 CI->getDiagnostics().setClient(Client, /*ShouldOwnClient=*/false); 37 return cantFail(clang::Interpreter::create(std::move(CI))); 38 } 39 40 TEST(InterpreterTest, Sanity) { 41 std::unique_ptr<Interpreter> Interp = createInterpreter(); 42 Transaction &R1(cantFail(Interp->Parse("void g(); void g() {}"))); 43 EXPECT_EQ(2U, R1.Decls.size()); 44 45 Transaction &R2(cantFail(Interp->Parse("int i;"))); 46 EXPECT_EQ(1U, R2.Decls.size()); 47 } 48 49 static std::string DeclToString(DeclGroupRef DGR) { 50 return llvm::cast<NamedDecl>(DGR.getSingleDecl())->getQualifiedNameAsString(); 51 } 52 53 TEST(InterpreterTest, IncrementalInputTopLevelDecls) { 54 std::unique_ptr<Interpreter> Interp = createInterpreter(); 55 auto R1OrErr = Interp->Parse("int var1 = 42; int f() { return var1; }"); 56 // gtest doesn't expand into explicit bool conversions. 57 EXPECT_TRUE(!!R1OrErr); 58 auto R1 = R1OrErr->Decls; 59 EXPECT_EQ(2U, R1.size()); 60 EXPECT_EQ("var1", DeclToString(R1[0])); 61 EXPECT_EQ("f", DeclToString(R1[1])); 62 63 auto R2OrErr = Interp->Parse("int var2 = f();"); 64 EXPECT_TRUE(!!R2OrErr); 65 auto R2 = R2OrErr->Decls; 66 EXPECT_EQ(1U, R2.size()); 67 EXPECT_EQ("var2", DeclToString(R2[0])); 68 } 69 70 TEST(InterpreterTest, Errors) { 71 Args ExtraArgs = {"-Xclang", "-diagnostic-log-file", "-Xclang", "-"}; 72 73 // Create the diagnostic engine with unowned consumer. 74 std::string DiagnosticOutput; 75 llvm::raw_string_ostream DiagnosticsOS(DiagnosticOutput); 76 auto DiagPrinter = std::make_unique<TextDiagnosticPrinter>( 77 DiagnosticsOS, new DiagnosticOptions()); 78 79 auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get()); 80 auto Err = Interp->Parse("intentional_error v1 = 42; ").takeError(); 81 using ::testing::HasSubstr; 82 EXPECT_THAT(DiagnosticsOS.str(), 83 HasSubstr("error: unknown type name 'intentional_error'")); 84 EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err))); 85 86 #ifdef GTEST_HAS_DEATH_TEST 87 EXPECT_DEATH((void)Interp->Parse("int var1 = 42;"), ""); 88 #endif 89 } 90 91 // Here we test whether the user can mix declarations and statements. The 92 // interpreter should be smart enough to recognize the declarations from the 93 // statements and wrap the latter into a declaration, producing valid code. 94 TEST(InterpreterTest, DeclsAndStatements) { 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 DiagnosticsOS, new DiagnosticOptions()); 102 103 auto Interp = createInterpreter(ExtraArgs, DiagPrinter.get()); 104 auto R1OrErr = Interp->Parse( 105 "int var1 = 42; extern \"C\" int printf(const char*, ...);"); 106 // gtest doesn't expand into explicit bool conversions. 107 EXPECT_TRUE(!!R1OrErr); 108 109 auto R1 = R1OrErr->Decls; 110 EXPECT_EQ(2U, R1.size()); 111 112 // FIXME: Add support for wrapping and running statements. 113 auto R2OrErr = Interp->Parse("var1++; printf(\"var1 value %d\\n\", var1);"); 114 EXPECT_FALSE(!!R2OrErr); 115 using ::testing::HasSubstr; 116 EXPECT_THAT(DiagnosticsOS.str(), 117 HasSubstr("error: unknown type name 'var1'")); 118 auto Err = R2OrErr.takeError(); 119 EXPECT_EQ("Parsing failed.", llvm::toString(std::move(Err))); 120 } 121 122 } // end anonymous namespace 123