blob: 2255d7652c285ffd1546a571845f1a3c2befcb78 [file] [log] [blame]
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +00001//===- unittest/AST/ASTImporterTest.cpp - AST node import test ------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Tests for the correct import of AST nodes from one AST context to another.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/AST/ASTContext.h"
15#include "clang/AST/ASTImporter.h"
16#include "MatchVerifier.h"
17#include "clang/ASTMatchers/ASTMatchFinder.h"
18#include "clang/ASTMatchers/ASTMatchers.h"
19#include "clang/Tooling/Tooling.h"
20#include "gtest/gtest.h"
21
22namespace clang {
23namespace ast_matchers {
24
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000025typedef std::vector<std::string> StringVector;
26
27void getLangArgs(Language Lang, StringVector &Args) {
28 switch (Lang) {
29 case Lang_C:
30 Args.insert(Args.end(), { "-x", "c", "-std=c99" });
31 break;
32 case Lang_C89:
33 Args.insert(Args.end(), { "-x", "c", "-std=c89" });
34 break;
35 case Lang_CXX:
36 Args.push_back("-std=c++98");
37 break;
38 case Lang_CXX11:
39 Args.push_back("-std=c++11");
40 break;
41 case Lang_OpenCL:
42 case Lang_OBJCXX:
43 break;
44 }
45}
46
47template<typename NodeType, typename MatcherType>
48testing::AssertionResult
49testImport(const std::string &FromCode, Language FromLang,
50 const std::string &ToCode, Language ToLang,
51 MatchVerifier<NodeType> &Verifier,
52 const MatcherType &AMatcher) {
53 StringVector FromArgs, ToArgs;
54 getLangArgs(FromLang, FromArgs);
55 getLangArgs(ToLang, ToArgs);
56
57 const char *const InputFileName = "input.cc";
58 const char *const OutputFileName = "output.cc";
59
60 std::unique_ptr<ASTUnit>
61 FromAST = tooling::buildASTFromCodeWithArgs(
62 FromCode, FromArgs, InputFileName),
63 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
64
65 ASTContext &FromCtx = FromAST->getASTContext(),
66 &ToCtx = ToAST->getASTContext();
67
68 // Add input.cc to virtual file system so importer can 'find' it
69 // while importing SourceLocations.
70 vfs::OverlayFileSystem *OFS = static_cast<vfs::OverlayFileSystem *>(
71 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
72 vfs::InMemoryFileSystem *MFS = static_cast<vfs::InMemoryFileSystem *>(
73 OFS->overlays_begin()->get());
Malcolm Parsonsf76f6502016-11-02 10:39:27 +000074 MFS->addFile(InputFileName, 0, llvm::MemoryBuffer::getMemBuffer(FromCode));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000075
76 ASTImporter Importer(ToCtx, ToAST->getFileManager(),
77 FromCtx, FromAST->getFileManager(), false);
78
79 IdentifierInfo *ImportedII = &FromCtx.Idents.get("declToImport");
80 assert(ImportedII && "Declaration with 'declToImport' name"
81 "should be specified in test!");
82 DeclarationName ImportDeclName(ImportedII);
83 SmallVector<NamedDecl *, 4> FoundDecls;
84 FromCtx.getTranslationUnitDecl()->localUncachedLookup(
85 ImportDeclName, FoundDecls);
86
87 if (FoundDecls.size() != 1)
88 return testing::AssertionFailure() << "Multiple declarations were found!";
89
90 auto Imported = Importer.Import(*FoundDecls.begin());
91 if (!Imported)
92 return testing::AssertionFailure() << "Import failed, nullptr returned!";
93
94 // This should dump source locations and assert if some source locations
95 // were not imported
96 SmallString<1024> ImportChecker;
97 llvm::raw_svector_ostream ToNothing(ImportChecker);
98 ToCtx.getTranslationUnitDecl()->print(ToNothing);
99
100 return Verifier.match(Imported, AMatcher);
101}
102
103TEST(ImportExpr, ImportStringLiteral) {
104 MatchVerifier<Decl> Verifier;
105 EXPECT_TRUE(testImport("void declToImport() { \"foo\"; }",
106 Lang_CXX, "", Lang_CXX, Verifier,
107 functionDecl(
108 hasBody(
109 compoundStmt(
110 has(
111 stringLiteral(
112 hasType(
113 asString("const char [4]")))))))));
114 EXPECT_TRUE(testImport("void declToImport() { L\"foo\"; }",
115 Lang_CXX, "", Lang_CXX, Verifier,
116 functionDecl(
117 hasBody(
118 compoundStmt(
119 has(
120 stringLiteral(
121 hasType(
122 asString("const wchar_t [4]")))))))));
123 EXPECT_TRUE(testImport("void declToImport() { \"foo\" \"bar\"; }",
124 Lang_CXX, "", Lang_CXX, Verifier,
125 functionDecl(
126 hasBody(
127 compoundStmt(
128 has(
129 stringLiteral(
130 hasType(
131 asString("const char [7]")))))))));
132}
133
134TEST(ImportExpr, ImportGNUNullExpr) {
135 MatchVerifier<Decl> Verifier;
136 EXPECT_TRUE(testImport("void declToImport() { __null; }",
137 Lang_CXX, "", Lang_CXX, Verifier,
138 functionDecl(
139 hasBody(
140 compoundStmt(
141 has(
142 gnuNullExpr(
143 hasType(isInteger()))))))));
144}
145
146TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
147 MatchVerifier<Decl> Verifier;
148 EXPECT_TRUE(testImport("void declToImport() { nullptr; }",
149 Lang_CXX11, "", Lang_CXX11, Verifier,
150 functionDecl(
151 hasBody(
152 compoundStmt(
153 has(
154 cxxNullPtrLiteralExpr()))))));
155}
156
157
158TEST(ImportExpr, ImportFloatinglLiteralExpr) {
159 MatchVerifier<Decl> Verifier;
160 EXPECT_TRUE(testImport("void declToImport() { 1.0; }",
161 Lang_CXX, "", Lang_CXX, Verifier,
162 functionDecl(
163 hasBody(
164 compoundStmt(
165 has(
166 floatLiteral(
167 equals(1.0),
168 hasType(asString("double")))))))));
169 EXPECT_TRUE(testImport("void declToImport() { 1.0e-5f; }",
170 Lang_CXX, "", Lang_CXX, Verifier,
171 functionDecl(
172 hasBody(
173 compoundStmt(
174 has(
175 floatLiteral(
176 equals(1.0e-5f),
177 hasType(asString("float")))))))));
178}
179
180TEST(ImportExpr, ImportCompoundLiteralExpr) {
181 MatchVerifier<Decl> Verifier;
182 EXPECT_TRUE(
183 testImport(
184 "void declToImport() {"
185 " struct s { int x; long y; unsigned z; }; "
186 " (struct s){ 42, 0L, 1U }; }",
187 Lang_CXX, "", Lang_CXX, Verifier,
188 functionDecl(
189 hasBody(
190 compoundStmt(
191 has(
192 compoundLiteralExpr(
193 hasType(asString("struct s")),
194 has(initListExpr(
195 hasType(asString("struct s")),
196 has(integerLiteral(
197 equals(42), hasType(asString("int")))),
198 has(integerLiteral(
199 equals(0), hasType(asString("long")))),
200 has(integerLiteral(
201 equals(1),
202 hasType(asString("unsigned int"))))
203 )))))))));
204}
205
206TEST(ImportExpr, ImportCXXThisExpr) {
207 MatchVerifier<Decl> Verifier;
208 EXPECT_TRUE(
209 testImport("class declToImport { void f() { this; } };",
210 Lang_CXX, "", Lang_CXX, Verifier,
211 cxxRecordDecl(
212 hasMethod(
213 hasBody(
214 compoundStmt(
215 has(
216 cxxThisExpr(
217 hasType(
218 asString("class declToImport *"))))))))));
219}
220
221TEST(ImportExpr, ImportAtomicExpr) {
222 MatchVerifier<Decl> Verifier;
Piotr Padlewskicfed2bf2016-05-31 15:25:05 +0000223 EXPECT_TRUE(testImport(
224 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", Lang_CXX,
225 "", Lang_CXX, Verifier,
226 functionDecl(hasBody(compoundStmt(has(atomicExpr(
227 has(ignoringParenImpCasts(
228 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
229 hasType(asString("int *"))))),
230 has(integerLiteral(equals(1), hasType(asString("int")))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000231}
232
233TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
234 MatchVerifier<Decl> Verifier;
235 EXPECT_TRUE(
236 testImport(
237 "void declToImport() { loop: goto loop; &&loop; }",
238 Lang_CXX, "", Lang_CXX, Verifier,
239 functionDecl(
240 hasBody(
241 compoundStmt(
242 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
243 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))
244 )))));
245}
246
247AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
248 internal::Matcher<NamedDecl>, InnerMatcher) {
249 const NamedDecl *Template = Node.getTemplatedDecl();
250 return Template && InnerMatcher.matches(*Template, Finder, Builder);
251}
252
253TEST(ImportExpr, ImportParenListExpr) {
254 MatchVerifier<Decl> Verifier;
255 EXPECT_TRUE(
256 testImport(
257 "template<typename T> class dummy { void f() { dummy X(*this); } };"
258 "typedef dummy<int> declToImport;"
259 "template class dummy<int>;",
260 Lang_CXX, "", Lang_CXX, Verifier,
261 typedefDecl(
262 hasType(
263 templateSpecializationType(
264 hasDeclaration(
265 classTemplateDecl(
266 hasTemplateDecl(
267 cxxRecordDecl(
268 hasMethod(
269 allOf(
270 hasName("f"),
271 hasBody(
272 compoundStmt(
273 has(
274 declStmt(
275 hasSingleDecl(
276 varDecl(
277 hasInitializer(
278 parenListExpr(
279 has(
280 unaryOperator(
281 hasOperatorName("*"),
282 hasUnaryOperand(cxxThisExpr())
283 )))))))))))))))))))));
284}
285
286TEST(ImportExpr, ImportStmtExpr) {
287 MatchVerifier<Decl> Verifier;
288 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
289 EXPECT_TRUE(
290 testImport(
291 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
292 Lang_CXX, "", Lang_CXX, Verifier,
293 functionDecl(
294 hasBody(
295 compoundStmt(
296 has(
297 declStmt(
298 hasSingleDecl(
299 varDecl(
300 hasName("C"),
301 hasType(asString("int")),
302 hasInitializer(
303 stmtExpr(
304 hasAnySubstatement(
305 declStmt(
306 hasSingleDecl(
307 varDecl(
308 hasName("X"),
309 hasType(asString("int")),
310 hasInitializer(
311 integerLiteral(equals(4))))))),
312 hasDescendant(
313 implicitCastExpr()
314 ))))))))))));
315}
316
317TEST(ImportExpr, ImportConditionalOperator) {
318 MatchVerifier<Decl> Verifier;
319 EXPECT_TRUE(
320 testImport(
321 "void declToImport() { true ? 1 : -5; }",
322 Lang_CXX, "", Lang_CXX, Verifier,
323 functionDecl(
324 hasBody(
325 compoundStmt(
326 has(
327 conditionalOperator(
328 hasCondition(cxxBoolLiteral(equals(true))),
329 hasTrueExpression(integerLiteral(equals(1))),
330 hasFalseExpression(
331 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
332 ))))))));
333}
334
335TEST(ImportExpr, ImportBinaryConditionalOperator) {
336 MatchVerifier<Decl> Verifier;
337 EXPECT_TRUE(
338 testImport(
339 "void declToImport() { 1 ?: -5; }",
340 Lang_CXX, "", Lang_CXX, Verifier,
341 functionDecl(
342 hasBody(
343 compoundStmt(
344 has(
345 binaryConditionalOperator(
346 hasCondition(
347 implicitCastExpr(
348 hasSourceExpression(
349 opaqueValueExpr(
350 hasSourceExpression(integerLiteral(equals(1))))),
351 hasType(booleanType()))),
352 hasTrueExpression(
353 opaqueValueExpr(hasSourceExpression(
354 integerLiteral(equals(1))))),
355 hasFalseExpression(
356 unaryOperator(hasOperatorName("-"),
357 hasUnaryOperand(integerLiteral(equals(5)))))
358 )))))));
359}
360
361TEST(ImportExpr, ImportDesignatedInitExpr) {
362 MatchVerifier<Decl> Verifier;
363 EXPECT_TRUE(testImport("void declToImport() {"
364 " struct point { double x; double y; };"
365 " struct point ptarray[10] = "
366 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
367 Lang_C, "", Lang_C, Verifier,
368 functionDecl(
369 hasBody(
370 compoundStmt(
371 has(
372 declStmt(
373 hasSingleDecl(
374 varDecl(
375 hasInitializer(
376 initListExpr(
377 hasSyntacticForm(
378 initListExpr(
379 has(
380 designatedInitExpr(
381 designatorCountIs(2),
382 has(floatLiteral(
383 equals(1.0))),
384 has(integerLiteral(
385 equals(2))))),
386 has(
387 designatedInitExpr(
388 designatorCountIs(2),
389 has(floatLiteral(
390 equals(2.0))),
391 has(integerLiteral(
392 equals(2))))),
393 has(
394 designatedInitExpr(
395 designatorCountIs(2),
396 has(floatLiteral(
397 equals(1.0))),
398 has(integerLiteral(
399 equals(0)))))
400 )))))))))))));
401}
402
403
404TEST(ImportExpr, ImportPredefinedExpr) {
405 MatchVerifier<Decl> Verifier;
406 // __func__ expands as StringLiteral("declToImport")
407 EXPECT_TRUE(testImport("void declToImport() { __func__; }",
408 Lang_CXX, "", Lang_CXX, Verifier,
409 functionDecl(
410 hasBody(
411 compoundStmt(
412 has(
413 predefinedExpr(
414 hasType(
415 asString("const char [13]")),
416 has(
417 stringLiteral(
418 hasType(
419 asString("const char [13]")))))))))));
420}
421
422TEST(ImportExpr, ImportInitListExpr) {
423 MatchVerifier<Decl> Verifier;
424 EXPECT_TRUE(
425 testImport(
426 "void declToImport() {"
427 " struct point { double x; double y; };"
428 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
429 " [0].x = 1.0 }; }",
430 Lang_CXX, "", Lang_CXX, Verifier,
431 functionDecl(
432 hasBody(
433 compoundStmt(
434 has(
435 declStmt(
436 hasSingleDecl(
437 varDecl(
438 hasInitializer(
439 initListExpr(
440 has(
441 cxxConstructExpr(
442 requiresZeroInitialization())),
443 has(
444 initListExpr(
445 hasType(asString("struct point")),
446 has(floatLiteral(equals(1.0))),
447 has(implicitValueInitExpr(
448 hasType(asString("double")))))),
449 has(
450 initListExpr(
451 hasType(asString("struct point")),
452 has(floatLiteral(equals(2.0))),
453 has(floatLiteral(equals(1.0)))))
454 )))))))))));
455}
456
457
Aleksei Sidorina693b372016-09-28 10:16:56 +0000458const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
459
460TEST(ImportExpr, ImportVAArgExpr) {
461 MatchVerifier<Decl> Verifier;
462 EXPECT_TRUE(
463 testImport(
464 "void declToImport(__builtin_va_list list, ...) {"
465 " (void)__builtin_va_arg(list, int); }",
466 Lang_CXX, "", Lang_CXX, Verifier,
467 functionDecl(
468 hasBody(
469 compoundStmt(
470 has(
471 cStyleCastExpr(
472 hasSourceExpression(
473 vaArgExpr()))))))));
474}
475
476
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000477} // end namespace ast_matchers
478} // end namespace clang