blob: 485cf252c15c61b826dd378761a49b67b7d83509 [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;
Manuel Klimek696e5052017-08-02 13:04:44 +0000255 EXPECT_TRUE(testImport(
256 "template<typename T> class dummy { void f() { dummy X(*this); } };"
257 "typedef dummy<int> declToImport;"
258 "template class dummy<int>;",
259 Lang_CXX, "", Lang_CXX, Verifier,
260 typedefDecl(hasType(templateSpecializationType(
261 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
262 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
263 hasName("f"),
264 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
265 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
266 hasOperatorName("*"),
267 hasUnaryOperand(cxxThisExpr()))))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000268}
269
270TEST(ImportExpr, ImportStmtExpr) {
271 MatchVerifier<Decl> Verifier;
272 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
273 EXPECT_TRUE(
274 testImport(
275 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
276 Lang_CXX, "", Lang_CXX, Verifier,
277 functionDecl(
278 hasBody(
279 compoundStmt(
280 has(
281 declStmt(
282 hasSingleDecl(
283 varDecl(
284 hasName("C"),
285 hasType(asString("int")),
286 hasInitializer(
287 stmtExpr(
288 hasAnySubstatement(
289 declStmt(
290 hasSingleDecl(
291 varDecl(
292 hasName("X"),
293 hasType(asString("int")),
294 hasInitializer(
295 integerLiteral(equals(4))))))),
296 hasDescendant(
297 implicitCastExpr()
298 ))))))))))));
299}
300
301TEST(ImportExpr, ImportConditionalOperator) {
302 MatchVerifier<Decl> Verifier;
303 EXPECT_TRUE(
304 testImport(
305 "void declToImport() { true ? 1 : -5; }",
306 Lang_CXX, "", Lang_CXX, Verifier,
307 functionDecl(
308 hasBody(
309 compoundStmt(
310 has(
311 conditionalOperator(
312 hasCondition(cxxBoolLiteral(equals(true))),
313 hasTrueExpression(integerLiteral(equals(1))),
314 hasFalseExpression(
315 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
316 ))))))));
317}
318
319TEST(ImportExpr, ImportBinaryConditionalOperator) {
320 MatchVerifier<Decl> Verifier;
321 EXPECT_TRUE(
322 testImport(
323 "void declToImport() { 1 ?: -5; }",
324 Lang_CXX, "", Lang_CXX, Verifier,
325 functionDecl(
326 hasBody(
327 compoundStmt(
328 has(
329 binaryConditionalOperator(
330 hasCondition(
331 implicitCastExpr(
332 hasSourceExpression(
333 opaqueValueExpr(
334 hasSourceExpression(integerLiteral(equals(1))))),
335 hasType(booleanType()))),
336 hasTrueExpression(
337 opaqueValueExpr(hasSourceExpression(
338 integerLiteral(equals(1))))),
339 hasFalseExpression(
340 unaryOperator(hasOperatorName("-"),
341 hasUnaryOperand(integerLiteral(equals(5)))))
342 )))))));
343}
344
345TEST(ImportExpr, ImportDesignatedInitExpr) {
346 MatchVerifier<Decl> Verifier;
347 EXPECT_TRUE(testImport("void declToImport() {"
348 " struct point { double x; double y; };"
349 " struct point ptarray[10] = "
350 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
351 Lang_C, "", Lang_C, Verifier,
352 functionDecl(
353 hasBody(
354 compoundStmt(
355 has(
356 declStmt(
357 hasSingleDecl(
358 varDecl(
359 hasInitializer(
360 initListExpr(
361 hasSyntacticForm(
362 initListExpr(
363 has(
364 designatedInitExpr(
365 designatorCountIs(2),
366 has(floatLiteral(
367 equals(1.0))),
368 has(integerLiteral(
369 equals(2))))),
370 has(
371 designatedInitExpr(
372 designatorCountIs(2),
373 has(floatLiteral(
374 equals(2.0))),
375 has(integerLiteral(
376 equals(2))))),
377 has(
378 designatedInitExpr(
379 designatorCountIs(2),
380 has(floatLiteral(
381 equals(1.0))),
382 has(integerLiteral(
383 equals(0)))))
384 )))))))))))));
385}
386
387
388TEST(ImportExpr, ImportPredefinedExpr) {
389 MatchVerifier<Decl> Verifier;
390 // __func__ expands as StringLiteral("declToImport")
391 EXPECT_TRUE(testImport("void declToImport() { __func__; }",
392 Lang_CXX, "", Lang_CXX, Verifier,
393 functionDecl(
394 hasBody(
395 compoundStmt(
396 has(
397 predefinedExpr(
398 hasType(
399 asString("const char [13]")),
400 has(
401 stringLiteral(
402 hasType(
403 asString("const char [13]")))))))))));
404}
405
406TEST(ImportExpr, ImportInitListExpr) {
407 MatchVerifier<Decl> Verifier;
408 EXPECT_TRUE(
409 testImport(
410 "void declToImport() {"
411 " struct point { double x; double y; };"
412 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
413 " [0].x = 1.0 }; }",
414 Lang_CXX, "", Lang_CXX, Verifier,
415 functionDecl(
416 hasBody(
417 compoundStmt(
418 has(
419 declStmt(
420 hasSingleDecl(
421 varDecl(
422 hasInitializer(
423 initListExpr(
424 has(
425 cxxConstructExpr(
426 requiresZeroInitialization())),
427 has(
428 initListExpr(
429 hasType(asString("struct point")),
430 has(floatLiteral(equals(1.0))),
431 has(implicitValueInitExpr(
432 hasType(asString("double")))))),
433 has(
434 initListExpr(
435 hasType(asString("struct point")),
436 has(floatLiteral(equals(2.0))),
437 has(floatLiteral(equals(1.0)))))
438 )))))))))));
439}
440
441
Aleksei Sidorina693b372016-09-28 10:16:56 +0000442const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
443
444TEST(ImportExpr, ImportVAArgExpr) {
445 MatchVerifier<Decl> Verifier;
446 EXPECT_TRUE(
447 testImport(
448 "void declToImport(__builtin_va_list list, ...) {"
449 " (void)__builtin_va_arg(list, int); }",
450 Lang_CXX, "", Lang_CXX, Verifier,
451 functionDecl(
452 hasBody(
453 compoundStmt(
454 has(
455 cStyleCastExpr(
456 hasSourceExpression(
457 vaArgExpr()))))))));
458}
459
460
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000461TEST(ImportType, ImportAtomicType) {
462 MatchVerifier<Decl> Verifier;
463 EXPECT_TRUE(testImport("void declToImport() { typedef _Atomic(int) a_int; }",
464 Lang_CXX11, "", Lang_CXX11, Verifier,
465 functionDecl(
466 hasBody(
467 compoundStmt(
468 has(
469 declStmt(
470 has(
471 typedefDecl(
472 has(atomicType()))))))))));
473}
474
475
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000476} // end namespace ast_matchers
477} // end namespace clang