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