blob: aea5bfa39e89faf1d0d020cb33e81f8d53466a0a [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
Gabor Horvath480892b2017-10-18 09:25:18 +0000100 // This traverses the AST to catch certain bugs like poorly or not
101 // implemented subtrees.
102 Imported->dump(ToNothing);
103
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000104 return Verifier.match(Imported, AMatcher);
105}
106
107TEST(ImportExpr, ImportStringLiteral) {
108 MatchVerifier<Decl> Verifier;
109 EXPECT_TRUE(testImport("void declToImport() { \"foo\"; }",
110 Lang_CXX, "", Lang_CXX, Verifier,
111 functionDecl(
112 hasBody(
113 compoundStmt(
114 has(
115 stringLiteral(
116 hasType(
117 asString("const char [4]")))))))));
118 EXPECT_TRUE(testImport("void declToImport() { L\"foo\"; }",
119 Lang_CXX, "", Lang_CXX, Verifier,
120 functionDecl(
121 hasBody(
122 compoundStmt(
123 has(
124 stringLiteral(
125 hasType(
126 asString("const wchar_t [4]")))))))));
127 EXPECT_TRUE(testImport("void declToImport() { \"foo\" \"bar\"; }",
128 Lang_CXX, "", Lang_CXX, Verifier,
129 functionDecl(
130 hasBody(
131 compoundStmt(
132 has(
133 stringLiteral(
134 hasType(
135 asString("const char [7]")))))))));
136}
137
138TEST(ImportExpr, ImportGNUNullExpr) {
139 MatchVerifier<Decl> Verifier;
140 EXPECT_TRUE(testImport("void declToImport() { __null; }",
141 Lang_CXX, "", Lang_CXX, Verifier,
142 functionDecl(
143 hasBody(
144 compoundStmt(
145 has(
146 gnuNullExpr(
147 hasType(isInteger()))))))));
148}
149
150TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
151 MatchVerifier<Decl> Verifier;
152 EXPECT_TRUE(testImport("void declToImport() { nullptr; }",
153 Lang_CXX11, "", Lang_CXX11, Verifier,
154 functionDecl(
155 hasBody(
156 compoundStmt(
157 has(
158 cxxNullPtrLiteralExpr()))))));
159}
160
161
162TEST(ImportExpr, ImportFloatinglLiteralExpr) {
163 MatchVerifier<Decl> Verifier;
164 EXPECT_TRUE(testImport("void declToImport() { 1.0; }",
165 Lang_CXX, "", Lang_CXX, Verifier,
166 functionDecl(
167 hasBody(
168 compoundStmt(
169 has(
170 floatLiteral(
171 equals(1.0),
172 hasType(asString("double")))))))));
173 EXPECT_TRUE(testImport("void declToImport() { 1.0e-5f; }",
174 Lang_CXX, "", Lang_CXX, Verifier,
175 functionDecl(
176 hasBody(
177 compoundStmt(
178 has(
179 floatLiteral(
180 equals(1.0e-5f),
181 hasType(asString("float")))))))));
182}
183
184TEST(ImportExpr, ImportCompoundLiteralExpr) {
185 MatchVerifier<Decl> Verifier;
186 EXPECT_TRUE(
187 testImport(
188 "void declToImport() {"
189 " struct s { int x; long y; unsigned z; }; "
190 " (struct s){ 42, 0L, 1U }; }",
191 Lang_CXX, "", Lang_CXX, Verifier,
192 functionDecl(
193 hasBody(
194 compoundStmt(
195 has(
196 compoundLiteralExpr(
197 hasType(asString("struct s")),
198 has(initListExpr(
199 hasType(asString("struct s")),
200 has(integerLiteral(
201 equals(42), hasType(asString("int")))),
202 has(integerLiteral(
203 equals(0), hasType(asString("long")))),
204 has(integerLiteral(
205 equals(1),
206 hasType(asString("unsigned int"))))
207 )))))))));
208}
209
210TEST(ImportExpr, ImportCXXThisExpr) {
211 MatchVerifier<Decl> Verifier;
212 EXPECT_TRUE(
213 testImport("class declToImport { void f() { this; } };",
214 Lang_CXX, "", Lang_CXX, Verifier,
215 cxxRecordDecl(
216 hasMethod(
217 hasBody(
218 compoundStmt(
219 has(
220 cxxThisExpr(
221 hasType(
222 asString("class declToImport *"))))))))));
223}
224
225TEST(ImportExpr, ImportAtomicExpr) {
226 MatchVerifier<Decl> Verifier;
Piotr Padlewskicfed2bf2016-05-31 15:25:05 +0000227 EXPECT_TRUE(testImport(
228 "void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }", Lang_CXX,
229 "", Lang_CXX, Verifier,
230 functionDecl(hasBody(compoundStmt(has(atomicExpr(
231 has(ignoringParenImpCasts(
232 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
233 hasType(asString("int *"))))),
234 has(integerLiteral(equals(1), hasType(asString("int")))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000235}
236
237TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
238 MatchVerifier<Decl> Verifier;
239 EXPECT_TRUE(
240 testImport(
241 "void declToImport() { loop: goto loop; &&loop; }",
242 Lang_CXX, "", Lang_CXX, Verifier,
243 functionDecl(
244 hasBody(
245 compoundStmt(
246 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
247 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))
248 )))));
249}
250
251AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
252 internal::Matcher<NamedDecl>, InnerMatcher) {
253 const NamedDecl *Template = Node.getTemplatedDecl();
254 return Template && InnerMatcher.matches(*Template, Finder, Builder);
255}
256
257TEST(ImportExpr, ImportParenListExpr) {
258 MatchVerifier<Decl> Verifier;
Manuel Klimek696e5052017-08-02 13:04:44 +0000259 EXPECT_TRUE(testImport(
260 "template<typename T> class dummy { void f() { dummy X(*this); } };"
261 "typedef dummy<int> declToImport;"
262 "template class dummy<int>;",
263 Lang_CXX, "", Lang_CXX, Verifier,
264 typedefDecl(hasType(templateSpecializationType(
265 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
266 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
267 hasName("f"),
268 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
269 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
270 hasOperatorName("*"),
271 hasUnaryOperand(cxxThisExpr()))))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000272}
273
Gabor Horvath480892b2017-10-18 09:25:18 +0000274TEST(ImportExpr, ImportSwitch) {
275 MatchVerifier<Decl> Verifier;
276 EXPECT_TRUE(
277 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
278 Lang_CXX, "", Lang_CXX, Verifier,
279 functionDecl(hasBody(compoundStmt(
280 has(switchStmt(has(compoundStmt(has(caseStmt()))))))))));
281}
282
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000283TEST(ImportExpr, ImportStmtExpr) {
284 MatchVerifier<Decl> Verifier;
285 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
286 EXPECT_TRUE(
287 testImport(
288 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
289 Lang_CXX, "", Lang_CXX, Verifier,
290 functionDecl(
291 hasBody(
292 compoundStmt(
293 has(
294 declStmt(
295 hasSingleDecl(
296 varDecl(
297 hasName("C"),
298 hasType(asString("int")),
299 hasInitializer(
300 stmtExpr(
301 hasAnySubstatement(
302 declStmt(
303 hasSingleDecl(
304 varDecl(
305 hasName("X"),
306 hasType(asString("int")),
307 hasInitializer(
308 integerLiteral(equals(4))))))),
309 hasDescendant(
310 implicitCastExpr()
311 ))))))))))));
312}
313
314TEST(ImportExpr, ImportConditionalOperator) {
315 MatchVerifier<Decl> Verifier;
316 EXPECT_TRUE(
317 testImport(
318 "void declToImport() { true ? 1 : -5; }",
319 Lang_CXX, "", Lang_CXX, Verifier,
320 functionDecl(
321 hasBody(
322 compoundStmt(
323 has(
324 conditionalOperator(
325 hasCondition(cxxBoolLiteral(equals(true))),
326 hasTrueExpression(integerLiteral(equals(1))),
327 hasFalseExpression(
328 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
329 ))))))));
330}
331
332TEST(ImportExpr, ImportBinaryConditionalOperator) {
333 MatchVerifier<Decl> Verifier;
334 EXPECT_TRUE(
335 testImport(
336 "void declToImport() { 1 ?: -5; }",
337 Lang_CXX, "", Lang_CXX, Verifier,
338 functionDecl(
339 hasBody(
340 compoundStmt(
341 has(
342 binaryConditionalOperator(
343 hasCondition(
344 implicitCastExpr(
345 hasSourceExpression(
346 opaqueValueExpr(
347 hasSourceExpression(integerLiteral(equals(1))))),
348 hasType(booleanType()))),
349 hasTrueExpression(
350 opaqueValueExpr(hasSourceExpression(
351 integerLiteral(equals(1))))),
352 hasFalseExpression(
353 unaryOperator(hasOperatorName("-"),
354 hasUnaryOperand(integerLiteral(equals(5)))))
355 )))))));
356}
357
358TEST(ImportExpr, ImportDesignatedInitExpr) {
359 MatchVerifier<Decl> Verifier;
360 EXPECT_TRUE(testImport("void declToImport() {"
361 " struct point { double x; double y; };"
362 " struct point ptarray[10] = "
363 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
364 Lang_C, "", Lang_C, Verifier,
365 functionDecl(
366 hasBody(
367 compoundStmt(
368 has(
369 declStmt(
370 hasSingleDecl(
371 varDecl(
372 hasInitializer(
373 initListExpr(
374 hasSyntacticForm(
375 initListExpr(
376 has(
377 designatedInitExpr(
378 designatorCountIs(2),
379 has(floatLiteral(
380 equals(1.0))),
381 has(integerLiteral(
382 equals(2))))),
383 has(
384 designatedInitExpr(
385 designatorCountIs(2),
386 has(floatLiteral(
387 equals(2.0))),
388 has(integerLiteral(
389 equals(2))))),
390 has(
391 designatedInitExpr(
392 designatorCountIs(2),
393 has(floatLiteral(
394 equals(1.0))),
395 has(integerLiteral(
396 equals(0)))))
397 )))))))))))));
398}
399
400
401TEST(ImportExpr, ImportPredefinedExpr) {
402 MatchVerifier<Decl> Verifier;
403 // __func__ expands as StringLiteral("declToImport")
404 EXPECT_TRUE(testImport("void declToImport() { __func__; }",
405 Lang_CXX, "", Lang_CXX, Verifier,
406 functionDecl(
407 hasBody(
408 compoundStmt(
409 has(
410 predefinedExpr(
411 hasType(
412 asString("const char [13]")),
413 has(
414 stringLiteral(
415 hasType(
416 asString("const char [13]")))))))))));
417}
418
419TEST(ImportExpr, ImportInitListExpr) {
420 MatchVerifier<Decl> Verifier;
421 EXPECT_TRUE(
422 testImport(
423 "void declToImport() {"
424 " struct point { double x; double y; };"
425 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
426 " [0].x = 1.0 }; }",
427 Lang_CXX, "", Lang_CXX, Verifier,
428 functionDecl(
429 hasBody(
430 compoundStmt(
431 has(
432 declStmt(
433 hasSingleDecl(
434 varDecl(
435 hasInitializer(
436 initListExpr(
437 has(
438 cxxConstructExpr(
439 requiresZeroInitialization())),
440 has(
441 initListExpr(
442 hasType(asString("struct point")),
443 has(floatLiteral(equals(1.0))),
444 has(implicitValueInitExpr(
445 hasType(asString("double")))))),
446 has(
447 initListExpr(
448 hasType(asString("struct point")),
449 has(floatLiteral(equals(2.0))),
450 has(floatLiteral(equals(1.0)))))
451 )))))))))));
452}
453
454
Aleksei Sidorina693b372016-09-28 10:16:56 +0000455const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
456
457TEST(ImportExpr, ImportVAArgExpr) {
458 MatchVerifier<Decl> Verifier;
459 EXPECT_TRUE(
460 testImport(
461 "void declToImport(__builtin_va_list list, ...) {"
462 " (void)__builtin_va_arg(list, int); }",
463 Lang_CXX, "", Lang_CXX, Verifier,
464 functionDecl(
465 hasBody(
466 compoundStmt(
467 has(
468 cStyleCastExpr(
469 hasSourceExpression(
470 vaArgExpr()))))))));
471}
472
473
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000474TEST(ImportType, ImportAtomicType) {
475 MatchVerifier<Decl> Verifier;
476 EXPECT_TRUE(testImport("void declToImport() { typedef _Atomic(int) a_int; }",
477 Lang_CXX11, "", Lang_CXX11, Verifier,
478 functionDecl(
479 hasBody(
480 compoundStmt(
481 has(
482 declStmt(
483 has(
484 typedefDecl(
485 has(atomicType()))))))))));
486}
487
488
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000489} // end namespace ast_matchers
490} // end namespace clang