1 #include "clang/Interpreter/CodeCompletion.h" 2 #include "clang/Frontend/CompilerInstance.h" 3 #include "clang/Interpreter/Interpreter.h" 4 #include "clang/Lex/Preprocessor.h" 5 #include "clang/Sema/CodeCompleteConsumer.h" 6 #include "clang/Sema/Sema.h" 7 #include "llvm/ExecutionEngine/Orc/LLJIT.h" 8 #include "llvm/LineEditor/LineEditor.h" 9 #include "llvm/Support/Error.h" 10 #include "llvm/Support/raw_ostream.h" 11 12 #include "gmock/gmock.h" 13 #include "gtest/gtest.h" 14 15 #if defined(_AIX) || defined(__MVS__) 16 #define CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 17 #endif 18 19 using namespace clang; 20 namespace { 21 auto CB = clang::IncrementalCompilerBuilder(); 22 23 static std::unique_ptr<Interpreter> createInterpreter() { 24 auto CI = cantFail(CB.CreateCpp()); 25 return cantFail(clang::Interpreter::create(std::move(CI))); 26 } 27 28 static std::vector<std::string> runComp(clang::Interpreter &MainInterp, 29 llvm::StringRef Input, 30 llvm::Error &ErrR) { 31 auto CI = CB.CreateCpp(); 32 if (auto Err = CI.takeError()) { 33 ErrR = std::move(Err); 34 return {}; 35 } 36 37 auto Interp = clang::Interpreter::create(std::move(*CI)); 38 if (auto Err = Interp.takeError()) { 39 // log the error and returns an empty vector; 40 ErrR = std::move(Err); 41 42 return {}; 43 } 44 45 std::vector<std::string> Results; 46 std::vector<std::string> Comps; 47 auto *MainCI = (*Interp)->getCompilerInstance(); 48 auto CC = ReplCodeCompleter(); 49 CC.codeComplete(MainCI, Input, /* Lines */ 1, Input.size() + 1, 50 MainInterp.getCompilerInstance(), Results); 51 52 for (auto Res : Results) 53 if (Res.find(CC.Prefix) == 0) 54 Comps.push_back(Res); 55 return Comps; 56 } 57 58 static bool HostSupportsJit() { 59 auto J = llvm::orc::LLJITBuilder().create(); 60 if (J) 61 return true; 62 LLVMConsumeError(llvm::wrap(J.takeError())); 63 return false; 64 } 65 66 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 67 TEST(CodeCompletionTest, DISABLED_Sanity) { 68 #else 69 TEST(CodeCompletionTest, Sanity) { 70 #endif 71 if (!HostSupportsJit()) 72 GTEST_SKIP(); 73 auto Interp = createInterpreter(); 74 cantFail(Interp->Parse("int foo = 12;")); 75 auto Err = llvm::Error::success(); 76 auto comps = runComp(*Interp, "f", Err); 77 EXPECT_EQ((size_t)2, comps.size()); // float and foo 78 EXPECT_EQ(comps[0], std::string("float")); 79 EXPECT_EQ(comps[1], std::string("foo")); 80 EXPECT_EQ((bool)Err, false); 81 } 82 83 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 84 TEST(CodeCompletionTest, DISABLED_SanityNoneValid) { 85 #else 86 TEST(CodeCompletionTest, SanityNoneValid) { 87 #endif 88 if (!HostSupportsJit()) 89 GTEST_SKIP(); 90 auto Interp = createInterpreter(); 91 cantFail(Interp->Parse("int foo = 12;")); 92 auto Err = llvm::Error::success(); 93 auto comps = runComp(*Interp, "babanana", Err); 94 EXPECT_EQ((size_t)0, comps.size()); // foo and float 95 EXPECT_EQ((bool)Err, false); 96 } 97 98 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 99 TEST(CodeCompletionTest, DISABLED_TwoDecls) { 100 #else 101 TEST(CodeCompletionTest, TwoDecls) { 102 #endif 103 if (!HostSupportsJit()) 104 GTEST_SKIP(); 105 auto Interp = createInterpreter(); 106 cantFail(Interp->Parse("int application = 12;")); 107 cantFail(Interp->Parse("int apple = 12;")); 108 auto Err = llvm::Error::success(); 109 auto comps = runComp(*Interp, "app", Err); 110 EXPECT_EQ((size_t)2, comps.size()); 111 EXPECT_EQ((bool)Err, false); 112 } 113 114 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 115 TEST(CodeCompletionTest, DISABLED_CompFunDeclsNoError) { 116 #else 117 TEST(CodeCompletionTest, CompFunDeclsNoError) { 118 #endif 119 if (!HostSupportsJit()) 120 GTEST_SKIP(); 121 auto Interp = createInterpreter(); 122 auto Err = llvm::Error::success(); 123 auto comps = runComp(*Interp, "void app(", Err); 124 EXPECT_EQ((bool)Err, false); 125 } 126 127 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 128 TEST(CodeCompletionTest, DISABLED_TypedDirected) { 129 #else 130 TEST(CodeCompletionTest, TypedDirected) { 131 #endif 132 if (!HostSupportsJit()) 133 GTEST_SKIP(); 134 auto Interp = createInterpreter(); 135 cantFail(Interp->Parse("int application = 12;")); 136 cantFail(Interp->Parse("char apple = '2';")); 137 cantFail(Interp->Parse("void add(int &SomeInt){}")); 138 { 139 auto Err = llvm::Error::success(); 140 auto comps = runComp(*Interp, std::string("add("), Err); 141 EXPECT_EQ((size_t)1, comps.size()); 142 EXPECT_EQ((bool)Err, false); 143 } 144 145 cantFail(Interp->Parse("int banana = 42;")); 146 147 { 148 auto Err = llvm::Error::success(); 149 auto comps = runComp(*Interp, std::string("add("), Err); 150 EXPECT_EQ((size_t)2, comps.size()); 151 EXPECT_EQ(comps[0], "application"); 152 EXPECT_EQ(comps[1], "banana"); 153 EXPECT_EQ((bool)Err, false); 154 } 155 156 { 157 auto Err = llvm::Error::success(); 158 auto comps = runComp(*Interp, std::string("add(b"), Err); 159 EXPECT_EQ((size_t)1, comps.size()); 160 EXPECT_EQ(comps[0], "banana"); 161 EXPECT_EQ((bool)Err, false); 162 } 163 } 164 165 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 166 TEST(CodeCompletionTest, DISABLED_SanityClasses) { 167 #else 168 TEST(CodeCompletionTest, SanityClasses) { 169 #endif 170 if (!HostSupportsJit()) 171 GTEST_SKIP(); 172 auto Interp = createInterpreter(); 173 cantFail(Interp->Parse("struct Apple{};")); 174 cantFail(Interp->Parse("void takeApple(Apple &a1){}")); 175 cantFail(Interp->Parse("Apple a1;")); 176 cantFail(Interp->Parse("void takeAppleCopy(Apple a1){}")); 177 178 { 179 auto Err = llvm::Error::success(); 180 auto comps = runComp(*Interp, "takeApple(", Err); 181 EXPECT_EQ((size_t)1, comps.size()); 182 EXPECT_EQ(comps[0], std::string("a1")); 183 EXPECT_EQ((bool)Err, false); 184 } 185 { 186 auto Err = llvm::Error::success(); 187 auto comps = runComp(*Interp, std::string("takeAppleCopy("), Err); 188 EXPECT_EQ((size_t)1, comps.size()); 189 EXPECT_EQ(comps[0], std::string("a1")); 190 EXPECT_EQ((bool)Err, false); 191 } 192 } 193 194 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 195 TEST(CodeCompletionTest, DISABLED_SubClassing) { 196 #else 197 TEST(CodeCompletionTest, SubClassing) { 198 #endif 199 if (!HostSupportsJit()) 200 GTEST_SKIP(); 201 auto Interp = createInterpreter(); 202 cantFail(Interp->Parse("struct Fruit {};")); 203 cantFail(Interp->Parse("struct Apple : Fruit{};")); 204 cantFail(Interp->Parse("void takeFruit(Fruit &f){}")); 205 cantFail(Interp->Parse("Apple a1;")); 206 cantFail(Interp->Parse("Fruit f1;")); 207 auto Err = llvm::Error::success(); 208 auto comps = runComp(*Interp, std::string("takeFruit("), Err); 209 EXPECT_EQ((size_t)2, comps.size()); 210 EXPECT_EQ(comps[0], std::string("a1")); 211 EXPECT_EQ(comps[1], std::string("f1")); 212 EXPECT_EQ((bool)Err, false); 213 } 214 215 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 216 TEST(CodeCompletionTest, DISABLED_MultipleArguments) { 217 #else 218 TEST(CodeCompletionTest, MultipleArguments) { 219 #endif 220 if (!HostSupportsJit()) 221 GTEST_SKIP(); 222 auto Interp = createInterpreter(); 223 cantFail(Interp->Parse("int foo = 42;")); 224 cantFail(Interp->Parse("char fowl = 'A';")); 225 cantFail(Interp->Parse("void takeTwo(int &a, char b){}")); 226 auto Err = llvm::Error::success(); 227 auto comps = runComp(*Interp, std::string("takeTwo(foo, "), Err); 228 EXPECT_EQ((size_t)1, comps.size()); 229 EXPECT_EQ(comps[0], std::string("fowl")); 230 EXPECT_EQ((bool)Err, false); 231 } 232 233 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 234 TEST(CodeCompletionTest, DISABLED_Methods) { 235 #else 236 TEST(CodeCompletionTest, Methods) { 237 #endif 238 if (!HostSupportsJit()) 239 GTEST_SKIP(); 240 auto Interp = createInterpreter(); 241 cantFail(Interp->Parse( 242 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 243 cantFail(Interp->Parse("Foo f1;")); 244 245 auto Err = llvm::Error::success(); 246 auto comps = runComp(*Interp, std::string("f1."), Err); 247 EXPECT_EQ((size_t)2, comps.size()); 248 EXPECT_EQ(comps[0], std::string("add")); 249 EXPECT_EQ(comps[1], std::string("par")); 250 EXPECT_EQ((bool)Err, false); 251 } 252 253 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 254 TEST(CodeCompletionTest, DISABLED_MethodsInvocations) { 255 #else 256 TEST(CodeCompletionTest, MethodsInvocations) { 257 #endif 258 if (!HostSupportsJit()) 259 GTEST_SKIP(); 260 auto Interp = createInterpreter(); 261 cantFail(Interp->Parse( 262 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 263 cantFail(Interp->Parse("Foo f1;")); 264 cantFail(Interp->Parse("int a = 84;")); 265 266 auto Err = llvm::Error::success(); 267 auto comps = runComp(*Interp, std::string("f1.add("), Err); 268 EXPECT_EQ((size_t)1, comps.size()); 269 EXPECT_EQ(comps[0], std::string("a")); 270 EXPECT_EQ((bool)Err, false); 271 } 272 273 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 274 TEST(CodeCompletionTest, DISABLED_NestedInvocations) { 275 #else 276 TEST(CodeCompletionTest, NestedInvocations) { 277 #endif 278 if (!HostSupportsJit()) 279 GTEST_SKIP(); 280 auto Interp = createInterpreter(); 281 cantFail(Interp->Parse( 282 "struct Foo{int add(int a){return 42;} int par(int b){return 42;}};")); 283 cantFail(Interp->Parse("Foo f1;")); 284 cantFail(Interp->Parse("int a = 84;")); 285 cantFail(Interp->Parse("int plus(int a, int b) { return a + b; }")); 286 287 auto Err = llvm::Error::success(); 288 auto comps = runComp(*Interp, std::string("plus(42, f1.add("), Err); 289 EXPECT_EQ((size_t)1, comps.size()); 290 EXPECT_EQ(comps[0], std::string("a")); 291 EXPECT_EQ((bool)Err, false); 292 } 293 294 #ifdef CLANG_INTERPRETER_PLATFORM_CANNOT_CREATE_LLJIT 295 TEST(CodeCompletionTest, DISABLED_TemplateFunctions) { 296 #else 297 TEST(CodeCompletionTest, TemplateFunctions) { 298 #endif 299 if (!HostSupportsJit()) 300 GTEST_SKIP(); 301 auto Interp = createInterpreter(); 302 cantFail( 303 Interp->Parse("template <typename T> T id(T a) { return a;} ")); 304 cantFail(Interp->Parse("int apple = 84;")); 305 { 306 auto Err = llvm::Error::success(); 307 auto comps = runComp(*Interp, std::string("id<int>("), Err); 308 EXPECT_EQ((size_t)1, comps.size()); 309 EXPECT_EQ(comps[0], std::string("apple")); 310 EXPECT_EQ((bool)Err, false); 311 } 312 313 cantFail(Interp->Parse( 314 "template <typename T> T pickFirst(T a, T b) { return a;} ")); 315 cantFail(Interp->Parse("char pear = '4';")); 316 { 317 auto Err = llvm::Error::success(); 318 auto comps = runComp(*Interp, std::string("pickFirst(apple, "), Err); 319 EXPECT_EQ((size_t)1, comps.size()); 320 EXPECT_EQ(comps[0], std::string("apple")); 321 EXPECT_EQ((bool)Err, false); 322 } 323 } 324 325 } // anonymous namespace 326