blob: feadd94dded470b11ed2f9d24a4577ee325c67fb [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
Aleksei Sidorin8fc85102018-01-26 11:36:54 +000014#include "MatchVerifier.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000015#include "clang/AST/ASTContext.h"
16#include "clang/AST/ASTImporter.h"
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000017#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
Aleksei Sidorine45ab562017-12-21 17:41:06 +000025typedef std::vector<std::string> ArgVector;
26typedef std::vector<ArgVector> RunOptions;
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000027
Aleksei Sidorine45ab562017-12-21 17:41:06 +000028static bool isCXX(Language Lang) {
29 return Lang == Lang_CXX || Lang == Lang_CXX11;
30}
31
32static RunOptions getRunOptionsForLanguage(Language Lang) {
33 ArgVector BasicArgs;
34 // Test with basic arguments.
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000035 switch (Lang) {
36 case Lang_C:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000037 BasicArgs = {"-x", "c", "-std=c99"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000038 break;
39 case Lang_C89:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000040 BasicArgs = {"-x", "c", "-std=c89"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000041 break;
42 case Lang_CXX:
Gabor Horvathd2c562d2018-01-27 16:38:56 +000043 BasicArgs = {"-std=c++98", "-frtti"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000044 break;
45 case Lang_CXX11:
Gabor Horvathd2c562d2018-01-27 16:38:56 +000046 BasicArgs = {"-std=c++11", "-frtti"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000047 break;
48 case Lang_OpenCL:
49 case Lang_OBJCXX:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000050 llvm_unreachable("Not implemented yet!");
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000051 }
Aleksei Sidorine45ab562017-12-21 17:41:06 +000052
53 // For C++, test with "-fdelayed-template-parsing" enabled to handle MSVC
54 // default behaviour.
55 if (isCXX(Lang)) {
56 ArgVector ArgsForDelayedTemplateParse = BasicArgs;
57 ArgsForDelayedTemplateParse.emplace_back("-fdelayed-template-parsing");
58 return {BasicArgs, ArgsForDelayedTemplateParse};
59 }
60
61 return {BasicArgs};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000062}
63
64template<typename NodeType, typename MatcherType>
65testing::AssertionResult
Aleksei Sidorine45ab562017-12-21 17:41:06 +000066testImport(const std::string &FromCode, const ArgVector &FromArgs,
67 const std::string &ToCode, const ArgVector &ToArgs,
68 MatchVerifier<NodeType> &Verifier, const MatcherType &AMatcher) {
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000069 const char *const InputFileName = "input.cc";
70 const char *const OutputFileName = "output.cc";
71
72 std::unique_ptr<ASTUnit>
73 FromAST = tooling::buildASTFromCodeWithArgs(
74 FromCode, FromArgs, InputFileName),
75 ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName);
76
77 ASTContext &FromCtx = FromAST->getASTContext(),
78 &ToCtx = ToAST->getASTContext();
79
80 // Add input.cc to virtual file system so importer can 'find' it
81 // while importing SourceLocations.
82 vfs::OverlayFileSystem *OFS = static_cast<vfs::OverlayFileSystem *>(
83 ToCtx.getSourceManager().getFileManager().getVirtualFileSystem().get());
84 vfs::InMemoryFileSystem *MFS = static_cast<vfs::InMemoryFileSystem *>(
85 OFS->overlays_begin()->get());
Malcolm Parsonsf76f6502016-11-02 10:39:27 +000086 MFS->addFile(InputFileName, 0, llvm::MemoryBuffer::getMemBuffer(FromCode));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000087
88 ASTImporter Importer(ToCtx, ToAST->getFileManager(),
89 FromCtx, FromAST->getFileManager(), false);
90
91 IdentifierInfo *ImportedII = &FromCtx.Idents.get("declToImport");
92 assert(ImportedII && "Declaration with 'declToImport' name"
93 "should be specified in test!");
94 DeclarationName ImportDeclName(ImportedII);
95 SmallVector<NamedDecl *, 4> FoundDecls;
96 FromCtx.getTranslationUnitDecl()->localUncachedLookup(
97 ImportDeclName, FoundDecls);
98
99 if (FoundDecls.size() != 1)
100 return testing::AssertionFailure() << "Multiple declarations were found!";
101
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000102 // Sanity check: the node being imported should match in the same way as
103 // the result node.
104 EXPECT_TRUE(Verifier.match(FoundDecls.front(), AMatcher));
105
106 auto Imported = Importer.Import(FoundDecls.front());
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000107 if (!Imported)
108 return testing::AssertionFailure() << "Import failed, nullptr returned!";
109
110 // This should dump source locations and assert if some source locations
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000111 // were not imported.
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000112 SmallString<1024> ImportChecker;
113 llvm::raw_svector_ostream ToNothing(ImportChecker);
114 ToCtx.getTranslationUnitDecl()->print(ToNothing);
115
Gabor Horvath480892b2017-10-18 09:25:18 +0000116 // This traverses the AST to catch certain bugs like poorly or not
117 // implemented subtrees.
118 Imported->dump(ToNothing);
119
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000120 return Verifier.match(Imported, AMatcher);
121}
122
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000123template<typename NodeType, typename MatcherType>
124void testImport(const std::string &FromCode, Language FromLang,
125 const std::string &ToCode, Language ToLang,
126 MatchVerifier<NodeType> &Verifier,
127 const MatcherType &AMatcher) {
128 auto RunOptsFrom = getRunOptionsForLanguage(FromLang);
129 auto RunOptsTo = getRunOptionsForLanguage(ToLang);
130 for (const auto &FromArgs : RunOptsFrom)
131 for (const auto &ToArgs : RunOptsTo)
132 EXPECT_TRUE(testImport(FromCode, FromArgs, ToCode, ToArgs,
133 Verifier, AMatcher));
134}
135
136
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000137TEST(ImportExpr, ImportStringLiteral) {
138 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000139 testImport("void declToImport() { \"foo\"; }",
140 Lang_CXX, "", Lang_CXX, Verifier,
141 functionDecl(
142 hasBody(
143 compoundStmt(
144 has(
145 stringLiteral(
146 hasType(
147 asString("const char [4]"))))))));
148 testImport("void declToImport() { L\"foo\"; }",
149 Lang_CXX, "", Lang_CXX, Verifier,
150 functionDecl(
151 hasBody(
152 compoundStmt(
153 has(
154 stringLiteral(
155 hasType(
156 asString("const wchar_t [4]"))))))));
157 testImport("void declToImport() { \"foo\" \"bar\"; }",
158 Lang_CXX, "", Lang_CXX, Verifier,
159 functionDecl(
160 hasBody(
161 compoundStmt(
162 has(
163 stringLiteral(
164 hasType(
165 asString("const char [7]"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000166}
167
168TEST(ImportExpr, ImportGNUNullExpr) {
169 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000170 testImport("void declToImport() { __null; }",
171 Lang_CXX, "", Lang_CXX, Verifier,
172 functionDecl(
173 hasBody(
174 compoundStmt(
175 has(
176 gnuNullExpr(
177 hasType(isInteger())))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000178}
179
180TEST(ImportExpr, ImportCXXNullPtrLiteralExpr) {
181 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000182 testImport("void declToImport() { nullptr; }",
183 Lang_CXX11, "", Lang_CXX11, Verifier,
184 functionDecl(
185 hasBody(
186 compoundStmt(
187 has(
188 cxxNullPtrLiteralExpr())))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000189}
190
191
192TEST(ImportExpr, ImportFloatinglLiteralExpr) {
193 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000194 testImport("void declToImport() { 1.0; }",
195 Lang_C, "", Lang_C, Verifier,
196 functionDecl(
197 hasBody(
198 compoundStmt(
199 has(
200 floatLiteral(
201 equals(1.0),
202 hasType(asString("double"))))))));
203 testImport("void declToImport() { 1.0e-5f; }",
204 Lang_C, "", Lang_C, Verifier,
205 functionDecl(
206 hasBody(
207 compoundStmt(
208 has(
209 floatLiteral(
210 equals(1.0e-5f),
211 hasType(asString("float"))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000212}
213
214TEST(ImportExpr, ImportCompoundLiteralExpr) {
215 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000216 testImport("void declToImport() {"
217 " struct s { int x; long y; unsigned z; }; "
218 " (struct s){ 42, 0L, 1U }; }",
219 Lang_CXX, "", Lang_CXX, Verifier,
220 functionDecl(
221 hasBody(
222 compoundStmt(
223 has(
224 compoundLiteralExpr(
225 hasType(asString("struct s")),
226 has(initListExpr(
227 hasType(asString("struct s")),
228 has(integerLiteral(
229 equals(42), hasType(asString("int")))),
230 has(integerLiteral(
231 equals(0), hasType(asString("long")))),
232 has(integerLiteral(
233 equals(1),
234 hasType(asString("unsigned int"))))
235 ))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000236}
237
238TEST(ImportExpr, ImportCXXThisExpr) {
239 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000240 testImport("class declToImport { void f() { this; } };",
241 Lang_CXX, "", Lang_CXX, Verifier,
242 cxxRecordDecl(
243 hasMethod(
244 hasBody(
245 compoundStmt(
246 has(
247 cxxThisExpr(
248 hasType(
249 asString("class declToImport *")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000250}
251
252TEST(ImportExpr, ImportAtomicExpr) {
253 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000254 testImport("void declToImport() { int *ptr; __atomic_load_n(ptr, 1); }",
255 Lang_C, "", Lang_C, Verifier,
256 functionDecl(hasBody(compoundStmt(has(atomicExpr(
257 has(ignoringParenImpCasts(
258 declRefExpr(hasDeclaration(varDecl(hasName("ptr"))),
259 hasType(asString("int *"))))),
260 has(integerLiteral(equals(1), hasType(asString("int"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000261}
262
263TEST(ImportExpr, ImportLabelDeclAndAddrLabelExpr) {
264 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000265 testImport(
266 "void declToImport() { loop: goto loop; &&loop; }", Lang_C, "", Lang_C,
267 Verifier,
268 functionDecl(hasBody(compoundStmt(
269 has(labelStmt(hasDeclaration(labelDecl(hasName("loop"))))),
270 has(addrLabelExpr(hasDeclaration(labelDecl(hasName("loop")))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000271}
272
273AST_MATCHER_P(TemplateDecl, hasTemplateDecl,
274 internal::Matcher<NamedDecl>, InnerMatcher) {
275 const NamedDecl *Template = Node.getTemplatedDecl();
276 return Template && InnerMatcher.matches(*Template, Finder, Builder);
277}
278
279TEST(ImportExpr, ImportParenListExpr) {
280 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000281 testImport(
Manuel Klimek696e5052017-08-02 13:04:44 +0000282 "template<typename T> class dummy { void f() { dummy X(*this); } };"
283 "typedef dummy<int> declToImport;"
284 "template class dummy<int>;",
285 Lang_CXX, "", Lang_CXX, Verifier,
286 typedefDecl(hasType(templateSpecializationType(
287 hasDeclaration(classTemplateSpecializationDecl(hasSpecializedTemplate(
288 classTemplateDecl(hasTemplateDecl(cxxRecordDecl(hasMethod(allOf(
289 hasName("f"),
290 hasBody(compoundStmt(has(declStmt(hasSingleDecl(
291 varDecl(hasInitializer(parenListExpr(has(unaryOperator(
292 hasOperatorName("*"),
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000293 hasUnaryOperand(cxxThisExpr())))))))))))))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000294}
295
Gabor Horvath480892b2017-10-18 09:25:18 +0000296TEST(ImportExpr, ImportSwitch) {
297 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000298 testImport("void declToImport() { int b; switch (b) { case 1: break; } }",
299 Lang_C, "", Lang_C, Verifier,
300 functionDecl(hasBody(compoundStmt(
301 has(switchStmt(has(compoundStmt(has(caseStmt())))))))));
Gabor Horvath480892b2017-10-18 09:25:18 +0000302}
303
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000304TEST(ImportExpr, ImportStmtExpr) {
305 MatchVerifier<Decl> Verifier;
306 // NOTE: has() ignores implicit casts, using hasDescendant() to match it
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000307 testImport(
308 "void declToImport() { int b; int a = b ?: 1; int C = ({int X=4; X;}); }",
309 Lang_C, "", Lang_C, Verifier,
310 functionDecl(
311 hasBody(
312 compoundStmt(
313 has(
314 declStmt(
315 hasSingleDecl(
316 varDecl(
317 hasName("C"),
318 hasType(asString("int")),
319 hasInitializer(
320 stmtExpr(
321 hasAnySubstatement(
322 declStmt(
323 hasSingleDecl(
324 varDecl(
325 hasName("X"),
326 hasType(asString("int")),
327 hasInitializer(
328 integerLiteral(equals(4))))))),
329 hasDescendant(
330 implicitCastExpr()
331 )))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000332}
333
334TEST(ImportExpr, ImportConditionalOperator) {
335 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000336 testImport(
337 "void declToImport() { true ? 1 : -5; }",
338 Lang_CXX, "", Lang_CXX, Verifier,
339 functionDecl(
340 hasBody(
341 compoundStmt(
342 has(
343 conditionalOperator(
344 hasCondition(cxxBoolLiteral(equals(true))),
345 hasTrueExpression(integerLiteral(equals(1))),
346 hasFalseExpression(
347 unaryOperator(hasUnaryOperand(integerLiteral(equals(5))))
348 )))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000349}
350
351TEST(ImportExpr, ImportBinaryConditionalOperator) {
352 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000353 testImport(
354 "void declToImport() { 1 ?: -5; }", Lang_CXX, "", Lang_CXX, Verifier,
355 functionDecl(
356 hasBody(
357 compoundStmt(
358 has(
359 binaryConditionalOperator(
360 hasCondition(
361 implicitCastExpr(
362 hasSourceExpression(
363 opaqueValueExpr(
364 hasSourceExpression(integerLiteral(equals(1))))),
365 hasType(booleanType()))),
366 hasTrueExpression(
367 opaqueValueExpr(hasSourceExpression(
368 integerLiteral(equals(1))))),
369 hasFalseExpression(
370 unaryOperator(hasOperatorName("-"),
371 hasUnaryOperand(integerLiteral(equals(5)))))
372 ))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000373}
374
375TEST(ImportExpr, ImportDesignatedInitExpr) {
376 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000377 testImport("void declToImport() {"
378 " struct point { double x; double y; };"
379 " struct point ptarray[10] = "
380 "{ [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; }",
381 Lang_C, "", Lang_C, Verifier,
382 functionDecl(
383 hasBody(
384 compoundStmt(
385 has(
386 declStmt(
387 hasSingleDecl(
388 varDecl(
389 hasInitializer(
390 initListExpr(
391 hasSyntacticForm(
392 initListExpr(
393 has(
394 designatedInitExpr(
395 designatorCountIs(2),
396 has(floatLiteral(
397 equals(1.0))),
398 has(integerLiteral(
399 equals(2))))),
400 has(
401 designatedInitExpr(
402 designatorCountIs(2),
403 has(floatLiteral(
404 equals(2.0))),
405 has(integerLiteral(
406 equals(2))))),
407 has(
408 designatedInitExpr(
409 designatorCountIs(2),
410 has(floatLiteral(
411 equals(1.0))),
412 has(integerLiteral(
413 equals(0)))))
414 ))))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000415}
416
417
418TEST(ImportExpr, ImportPredefinedExpr) {
419 MatchVerifier<Decl> Verifier;
420 // __func__ expands as StringLiteral("declToImport")
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000421 testImport("void declToImport() { __func__; }",
422 Lang_CXX, "", Lang_CXX, Verifier,
423 functionDecl(
424 hasBody(
425 compoundStmt(
426 has(
427 predefinedExpr(
428 hasType(
429 asString("const char [13]")),
430 has(
431 stringLiteral(
432 hasType(
433 asString("const char [13]"))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000434}
435
436TEST(ImportExpr, ImportInitListExpr) {
437 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000438 testImport(
439 "void declToImport() {"
440 " struct point { double x; double y; };"
441 " point ptarray[10] = { [2].y = 1.0, [2].x = 2.0,"
442 " [0].x = 1.0 }; }",
443 Lang_CXX, "", Lang_CXX, Verifier,
444 functionDecl(
445 hasBody(
446 compoundStmt(
447 has(
448 declStmt(
449 hasSingleDecl(
450 varDecl(
451 hasInitializer(
452 initListExpr(
453 has(
454 cxxConstructExpr(
455 requiresZeroInitialization())),
456 has(
457 initListExpr(
458 hasType(asString("struct point")),
459 has(floatLiteral(equals(1.0))),
460 has(implicitValueInitExpr(
461 hasType(asString("double")))))),
462 has(
463 initListExpr(
464 hasType(asString("struct point")),
465 has(floatLiteral(equals(2.0))),
466 has(floatLiteral(equals(1.0)))))
467 ))))))))));
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000468}
469
470
Aleksei Sidorina693b372016-09-28 10:16:56 +0000471const internal::VariadicDynCastAllOfMatcher<Expr, VAArgExpr> vaArgExpr;
472
473TEST(ImportExpr, ImportVAArgExpr) {
474 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000475 testImport("void declToImport(__builtin_va_list list, ...) {"
476 " (void)__builtin_va_arg(list, int); }",
477 Lang_CXX, "", Lang_CXX, Verifier,
478 functionDecl(
479 hasBody(
480 compoundStmt(
481 has(
482 cStyleCastExpr(
483 hasSourceExpression(
484 vaArgExpr())))))));
Aleksei Sidorina693b372016-09-28 10:16:56 +0000485}
486
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000487TEST(ImportExpr, CXXTemporaryObjectExpr) {
488 MatchVerifier<Decl> Verifier;
489 testImport("struct C {};"
490 "void declToImport() { C c = C(); }",
491 Lang_CXX, "", Lang_CXX, Verifier,
492 functionDecl(hasBody(compoundStmt(has(
493 declStmt(has(varDecl(has(exprWithCleanups(has(cxxConstructExpr(
494 has(materializeTemporaryExpr(has(implicitCastExpr(
495 has(cxxTemporaryObjectExpr())))))))))))))))));
496}
Aleksei Sidorina693b372016-09-28 10:16:56 +0000497
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000498TEST(ImportType, ImportAtomicType) {
499 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000500 testImport("void declToImport() { typedef _Atomic(int) a_int; }",
501 Lang_CXX11, "", Lang_CXX11, Verifier,
502 functionDecl(
503 hasBody(
504 compoundStmt(
505 has(
506 declStmt(
507 has(
508 typedefDecl(
509 has(atomicType())))))))));
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000510}
511
Aleksei Sidorin7f758b62017-12-27 17:04:42 +0000512TEST(ImportDecl, ImportFunctionTemplateDecl) {
513 MatchVerifier<Decl> Verifier;
514 testImport("template <typename T> void declToImport() { };", Lang_CXX, "",
515 Lang_CXX, Verifier, functionTemplateDecl());
516}
517
518const internal::VariadicDynCastAllOfMatcher<Expr, CXXDependentScopeMemberExpr>
519 cxxDependentScopeMemberExpr;
520
521TEST(ImportExpr, ImportCXXDependentScopeMemberExpr) {
522 MatchVerifier<Decl> Verifier;
523 testImport("template <typename T> struct C { T t; };"
524 "template <typename T> void declToImport() {"
525 " C<T> d;"
526 " d.t;"
527 "}"
528 "void instantiate() { declToImport<int>(); }",
529 Lang_CXX, "", Lang_CXX, Verifier,
530 functionTemplateDecl(has(functionDecl(
531 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
532 testImport("template <typename T> struct C { T t; };"
533 "template <typename T> void declToImport() {"
534 " C<T> d;"
535 " (&d)->t;"
536 "}"
537 "void instantiate() { declToImport<int>(); }",
538 Lang_CXX, "", Lang_CXX, Verifier,
539 functionTemplateDecl(has(functionDecl(
540 has(compoundStmt(has(cxxDependentScopeMemberExpr())))))));
541}
Gabor Horvath0866c2f2016-11-23 15:24:23 +0000542
Gabor Horvath7a91c082017-11-14 11:30:38 +0000543TEST(ImportType, ImportTypeAliasTemplate) {
544 MatchVerifier<Decl> Verifier;
Aleksei Sidorin4c05f142018-02-14 11:18:00 +0000545 testImport(
546 "template <int K>"
547 "struct dummy { static const int i = K; };"
548 "template <int K> using dummy2 = dummy<K>;"
549 "int declToImport() { return dummy2<3>::i; }",
550 Lang_CXX11, "", Lang_CXX11, Verifier,
551 functionDecl(
552 hasBody(compoundStmt(
553 has(returnStmt(has(implicitCastExpr(has(declRefExpr()))))))),
554 unless(hasAncestor(translationUnitDecl(has(typeAliasDecl()))))));
555}
556
557const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateSpecializationDecl>
558 varTemplateSpecializationDecl;
559
560TEST(ImportDecl, ImportVarTemplate) {
561 MatchVerifier<Decl> Verifier;
562 testImport(
563 "template <typename T>"
564 "T pi = T(3.1415926535897932385L);"
565 "void declToImport() { pi<int>; }",
566 Lang_CXX11, "", Lang_CXX11, Verifier,
567 functionDecl(
568 hasBody(has(declRefExpr(to(varTemplateSpecializationDecl())))),
569 unless(hasAncestor(translationUnitDecl(has(varDecl(
570 hasName("pi"), unless(varTemplateSpecializationDecl()))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000571}
572
Gabor Horvath7a91c082017-11-14 11:30:38 +0000573TEST(ImportType, ImportPackExpansion) {
574 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000575 testImport("template <typename... Args>"
576 "struct dummy {"
577 " dummy(Args... args) {}"
578 " static const int i = 4;"
579 "};"
580 "int declToImport() { return dummy<int>::i; }",
581 Lang_CXX11, "", Lang_CXX11, Verifier,
582 functionDecl(
583 hasBody(
584 compoundStmt(
585 has(
586 returnStmt(
587 has(
588 implicitCastExpr(
589 has(
590 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000591}
592
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000593const internal::VariadicDynCastAllOfMatcher<Type,
594 DependentTemplateSpecializationType>
595 dependentTemplateSpecializationType;
596
597TEST(ImportType, ImportDependentTemplateSpecialization) {
598 MatchVerifier<Decl> Verifier;
599 testImport("template<typename T>"
600 "struct A;"
601 "template<typename T>"
602 "struct declToImport {"
603 " typename A<T>::template B<T> a;"
604 "};",
605 Lang_CXX, "", Lang_CXX, Verifier,
606 classTemplateDecl(has(cxxRecordDecl(has(
607 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
608}
609
610const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
611 sizeOfPackExpr;
612
613TEST(ImportExpr, ImportSizeOfPackExpr) {
614 MatchVerifier<Decl> Verifier;
615 testImport("template <typename... Ts>"
616 "void declToImport() {"
617 " const int i = sizeof...(Ts);"
618 "};"
619 "void g() { declToImport<int>(); }",
620 Lang_CXX11, "", Lang_CXX11, Verifier,
621 functionTemplateDecl(has(functionDecl(
622 hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer(
623 implicitCastExpr(has(sizeOfPackExpr())))))))))))));
624 testImport(
625 "template <typename... Ts>"
626 "using X = int[sizeof...(Ts)];"
627 "template <typename... Us>"
628 "struct Y {"
629 " X<Us..., int, double, int, Us...> f;"
630 "};"
631 "Y<float, int> declToImport;",
632 Lang_CXX11, "", Lang_CXX11, Verifier,
633 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
634 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
635}
636
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000637/// \brief Matches __builtin_types_compatible_p:
638/// GNU extension to check equivalent types
639/// Given
640/// \code
641/// __builtin_types_compatible_p(int, int)
642/// \endcode
643// will generate TypeTraitExpr <...> 'int'
644const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
645
646TEST(ImportExpr, ImportTypeTraitExpr) {
647 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000648 testImport("void declToImport() { "
649 " __builtin_types_compatible_p(int, int);"
650 "}",
651 Lang_C, "", Lang_C, Verifier,
652 functionDecl(
653 hasBody(
654 compoundStmt(
655 has(
656 typeTraitExpr(hasType(asString("int"))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000657}
658
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000659const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
660
661TEST(ImportExpr, ImportCXXTypeidExpr) {
662 MatchVerifier<Decl> Verifier;
663 testImport(
664 "namespace std { class type_info {}; }"
665 "void declToImport() {"
666 " int x;"
667 " auto a = typeid(int); auto b = typeid(x);"
668 "}",
669 Lang_CXX11, "", Lang_CXX11, Verifier,
670 functionDecl(
671 hasDescendant(varDecl(
672 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
673 hasDescendant(varDecl(
674 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
675}
676
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000677TEST(ImportExpr, ImportTypeTraitExprValDep) {
678 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000679 testImport("template<typename T> struct declToImport {"
680 " void m() { __is_pod(T); }"
681 "};"
682 "void f() { declToImport<int>().m(); }",
683 Lang_CXX11, "", Lang_CXX11, Verifier,
684 classTemplateDecl(
685 has(
686 cxxRecordDecl(
687 has(
688 functionDecl(
689 hasBody(
690 compoundStmt(
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000691 has(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000692 typeTraitExpr(
693 hasType(booleanType())
694 ))))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000695}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000696
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000697const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
698 cxxPseudoDestructorExpr;
699
700TEST(ImportExpr, ImportCXXPseudoDestructorExpr) {
701 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000702 testImport("typedef int T;"
703 "void declToImport(int *p) {"
704 " T t;"
705 " p->T::~T();"
706 "}",
707 Lang_CXX, "", Lang_CXX, Verifier,
708 functionDecl(has(compoundStmt(has(
709 callExpr(has(cxxPseudoDestructorExpr())))))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000710}
711
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000712TEST(ImportDecl, ImportUsingDecl) {
713 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000714 testImport("namespace foo { int bar; }"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000715 "void declToImport() { using foo::bar; }",
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000716 Lang_CXX, "", Lang_CXX, Verifier,
717 functionDecl(
718 has(
719 compoundStmt(
720 has(
721 declStmt(
722 has(
723 usingDecl())))))));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000724}
725
726/// \brief Matches shadow declarations introduced into a scope by a
727/// (resolved) using declaration.
728///
729/// Given
730/// \code
731/// namespace n { int f; }
732/// namespace declToImport { using n::f; }
733/// \endcode
734/// usingShadowDecl()
735/// matches \code f \endcode
736const internal::VariadicDynCastAllOfMatcher<Decl,
737 UsingShadowDecl> usingShadowDecl;
738
739TEST(ImportDecl, ImportUsingShadowDecl) {
740 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000741 testImport("namespace foo { int bar; }"
742 "namespace declToImport { using foo::bar; }",
743 Lang_CXX, "", Lang_CXX, Verifier,
744 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000745}
746
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000747TEST(ImportExpr, ImportUnresolvedLookupExpr) {
748 MatchVerifier<Decl> Verifier;
749 testImport("template<typename T> int foo();"
750 "template <typename T> void declToImport() {"
751 " ::foo<T>;"
752 " ::template foo<T>;"
753 "}"
754 "void instantiate() { declToImport<int>(); }",
755 Lang_CXX, "", Lang_CXX, Verifier,
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000756 functionTemplateDecl(has(functionDecl(
757 has(compoundStmt(has(unresolvedLookupExpr())))))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000758}
759
760TEST(ImportExpr, ImportCXXUnresolvedConstructExpr) {
761 MatchVerifier<Decl> Verifier;
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000762 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000763 "template <typename T> void declToImport() {"
764 " C<T> d;"
765 " d.t = T();"
766 "}"
767 "void instantiate() { declToImport<int>(); }",
768 Lang_CXX, "", Lang_CXX, Verifier,
769 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
770 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000771 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000772 "template <typename T> void declToImport() {"
773 " C<T> d;"
774 " (&d)->t = T();"
775 "}"
776 "void instantiate() { declToImport<int>(); }",
777 Lang_CXX, "", Lang_CXX, Verifier,
778 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
779 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
780}
781
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000782/// Check that function "declToImport()" (which is the templated function
783/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
784/// Same for class template declarations.
785TEST(ImportDecl, ImportTemplatedDeclForTemplate) {
786 MatchVerifier<Decl> Verifier;
787 testImport("template <typename T> void declToImport() { T a = 1; }"
788 "void instantiate() { declToImport<int>(); }",
789 Lang_CXX, "", Lang_CXX, Verifier,
790 functionTemplateDecl(hasAncestor(translationUnitDecl(
791 unless(has(functionDecl(hasName("declToImport"))))))));
792 testImport("template <typename T> struct declToImport { T t; };"
793 "void instantiate() { declToImport<int>(); }",
794 Lang_CXX, "", Lang_CXX, Verifier,
795 classTemplateDecl(hasAncestor(translationUnitDecl(
796 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
797}
798
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000799TEST(ImportExpr, CXXOperatorCallExpr) {
800 MatchVerifier<Decl> Verifier;
801 testImport("class declToImport {"
802 " void f() { *this = declToImport(); }"
803 "};",
804 Lang_CXX, "", Lang_CXX, Verifier,
805 cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
806 has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
807}
808
809TEST(ImportExpr, DependentSizedArrayType) {
810 MatchVerifier<Decl> Verifier;
811 testImport("template<typename T, int Size> class declToImport {"
812 " T data[Size];"
813 "};",
814 Lang_CXX, "", Lang_CXX, Verifier,
815 classTemplateDecl(has(cxxRecordDecl(
816 has(fieldDecl(hasType(dependentSizedArrayType())))))));
817}
818
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000819} // end namespace ast_matchers
820} // end namespace clang