blob: 44f9582841582de2b8ecb4552603b6e3cc5a8c29 [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:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000043 BasicArgs = {"-std=c++98"};
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +000044 break;
45 case Lang_CXX11:
Aleksei Sidorine45ab562017-12-21 17:41:06 +000046 BasicArgs = {"-std=c++11"};
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 Sidorine45ab562017-12-21 17:41:06 +0000545 testImport("template <int K>"
546 "struct dummy { static const int i = K; };"
547 "template <int K> using dummy2 = dummy<K>;"
548 "int declToImport() { return dummy2<3>::i; }",
549 Lang_CXX11, "", Lang_CXX11, Verifier,
550 functionDecl(
551 hasBody(
552 compoundStmt(
553 has(
554 returnStmt(
555 has(
556 implicitCastExpr(
557 has(
558 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000559}
560
Gabor Horvath7a91c082017-11-14 11:30:38 +0000561TEST(ImportType, ImportPackExpansion) {
562 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000563 testImport("template <typename... Args>"
564 "struct dummy {"
565 " dummy(Args... args) {}"
566 " static const int i = 4;"
567 "};"
568 "int declToImport() { return dummy<int>::i; }",
569 Lang_CXX11, "", Lang_CXX11, Verifier,
570 functionDecl(
571 hasBody(
572 compoundStmt(
573 has(
574 returnStmt(
575 has(
576 implicitCastExpr(
577 has(
578 declRefExpr())))))))));
Gabor Horvath7a91c082017-11-14 11:30:38 +0000579}
580
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000581const internal::VariadicDynCastAllOfMatcher<Type,
582 DependentTemplateSpecializationType>
583 dependentTemplateSpecializationType;
584
585TEST(ImportType, ImportDependentTemplateSpecialization) {
586 MatchVerifier<Decl> Verifier;
587 testImport("template<typename T>"
588 "struct A;"
589 "template<typename T>"
590 "struct declToImport {"
591 " typename A<T>::template B<T> a;"
592 "};",
593 Lang_CXX, "", Lang_CXX, Verifier,
594 classTemplateDecl(has(cxxRecordDecl(has(
595 fieldDecl(hasType(dependentTemplateSpecializationType())))))));
596}
597
598const internal::VariadicDynCastAllOfMatcher<Stmt, SizeOfPackExpr>
599 sizeOfPackExpr;
600
601TEST(ImportExpr, ImportSizeOfPackExpr) {
602 MatchVerifier<Decl> Verifier;
603 testImport("template <typename... Ts>"
604 "void declToImport() {"
605 " const int i = sizeof...(Ts);"
606 "};"
607 "void g() { declToImport<int>(); }",
608 Lang_CXX11, "", Lang_CXX11, Verifier,
609 functionTemplateDecl(has(functionDecl(
610 hasBody(compoundStmt(has(declStmt(has(varDecl(hasInitializer(
611 implicitCastExpr(has(sizeOfPackExpr())))))))))))));
612 testImport(
613 "template <typename... Ts>"
614 "using X = int[sizeof...(Ts)];"
615 "template <typename... Us>"
616 "struct Y {"
617 " X<Us..., int, double, int, Us...> f;"
618 "};"
619 "Y<float, int> declToImport;",
620 Lang_CXX11, "", Lang_CXX11, Verifier,
621 varDecl(hasType(classTemplateSpecializationDecl(has(fieldDecl(hasType(
622 hasUnqualifiedDesugaredType(constantArrayType(hasSize(7))))))))));
623}
624
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000625/// \brief Matches __builtin_types_compatible_p:
626/// GNU extension to check equivalent types
627/// Given
628/// \code
629/// __builtin_types_compatible_p(int, int)
630/// \endcode
631// will generate TypeTraitExpr <...> 'int'
632const internal::VariadicDynCastAllOfMatcher<Stmt, TypeTraitExpr> typeTraitExpr;
633
634TEST(ImportExpr, ImportTypeTraitExpr) {
635 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000636 testImport("void declToImport() { "
637 " __builtin_types_compatible_p(int, int);"
638 "}",
639 Lang_C, "", Lang_C, Verifier,
640 functionDecl(
641 hasBody(
642 compoundStmt(
643 has(
644 typeTraitExpr(hasType(asString("int"))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000645}
646
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000647const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTypeidExpr> cxxTypeidExpr;
648
649TEST(ImportExpr, ImportCXXTypeidExpr) {
650 MatchVerifier<Decl> Verifier;
651 testImport(
652 "namespace std { class type_info {}; }"
653 "void declToImport() {"
654 " int x;"
655 " auto a = typeid(int); auto b = typeid(x);"
656 "}",
657 Lang_CXX11, "", Lang_CXX11, Verifier,
658 functionDecl(
659 hasDescendant(varDecl(
660 hasName("a"), hasInitializer(hasDescendant(cxxTypeidExpr())))),
661 hasDescendant(varDecl(
662 hasName("b"), hasInitializer(hasDescendant(cxxTypeidExpr()))))));
663}
664
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000665TEST(ImportExpr, ImportTypeTraitExprValDep) {
666 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000667 testImport("template<typename T> struct declToImport {"
668 " void m() { __is_pod(T); }"
669 "};"
670 "void f() { declToImport<int>().m(); }",
671 Lang_CXX11, "", Lang_CXX11, Verifier,
672 classTemplateDecl(
673 has(
674 cxxRecordDecl(
675 has(
676 functionDecl(
677 hasBody(
678 compoundStmt(
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000679 has(
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000680 typeTraitExpr(
681 hasType(booleanType())
682 ))))))))));
Aleksei Sidorinb05f37a2017-11-26 17:04:06 +0000683}
Gabor Horvath7a91c082017-11-14 11:30:38 +0000684
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000685const internal::VariadicDynCastAllOfMatcher<Expr, CXXPseudoDestructorExpr>
686 cxxPseudoDestructorExpr;
687
688TEST(ImportExpr, ImportCXXPseudoDestructorExpr) {
689 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000690 testImport("typedef int T;"
691 "void declToImport(int *p) {"
692 " T t;"
693 " p->T::~T();"
694 "}",
695 Lang_CXX, "", Lang_CXX, Verifier,
696 functionDecl(has(compoundStmt(has(
697 callExpr(has(cxxPseudoDestructorExpr())))))));
Aleksei Sidorin60ccb7d2017-11-27 10:30:00 +0000698}
699
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000700TEST(ImportDecl, ImportUsingDecl) {
701 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000702 testImport("namespace foo { int bar; }"
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000703 "void declToImport() { using foo::bar; }",
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000704 Lang_CXX, "", Lang_CXX, Verifier,
705 functionDecl(
706 has(
707 compoundStmt(
708 has(
709 declStmt(
710 has(
711 usingDecl())))))));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000712}
713
714/// \brief Matches shadow declarations introduced into a scope by a
715/// (resolved) using declaration.
716///
717/// Given
718/// \code
719/// namespace n { int f; }
720/// namespace declToImport { using n::f; }
721/// \endcode
722/// usingShadowDecl()
723/// matches \code f \endcode
724const internal::VariadicDynCastAllOfMatcher<Decl,
725 UsingShadowDecl> usingShadowDecl;
726
727TEST(ImportDecl, ImportUsingShadowDecl) {
728 MatchVerifier<Decl> Verifier;
Aleksei Sidorine45ab562017-12-21 17:41:06 +0000729 testImport("namespace foo { int bar; }"
730 "namespace declToImport { using foo::bar; }",
731 Lang_CXX, "", Lang_CXX, Verifier,
732 namespaceDecl(has(usingShadowDecl())));
Aleksei Sidorin9d8ba2e2017-12-03 16:04:07 +0000733}
734
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000735TEST(ImportExpr, ImportUnresolvedLookupExpr) {
736 MatchVerifier<Decl> Verifier;
737 testImport("template<typename T> int foo();"
738 "template <typename T> void declToImport() {"
739 " ::foo<T>;"
740 " ::template foo<T>;"
741 "}"
742 "void instantiate() { declToImport<int>(); }",
743 Lang_CXX, "", Lang_CXX, Verifier,
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000744 functionTemplateDecl(has(functionDecl(
745 has(compoundStmt(has(unresolvedLookupExpr())))))));
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000746}
747
748TEST(ImportExpr, ImportCXXUnresolvedConstructExpr) {
749 MatchVerifier<Decl> Verifier;
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000750 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000751 "template <typename T> void declToImport() {"
752 " C<T> d;"
753 " d.t = T();"
754 "}"
755 "void instantiate() { declToImport<int>(); }",
756 Lang_CXX, "", Lang_CXX, Verifier,
757 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
758 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000759 testImport("template <typename T> struct C { T t; };"
Aleksei Sidorine267a0f2018-01-09 16:40:40 +0000760 "template <typename T> void declToImport() {"
761 " C<T> d;"
762 " (&d)->t = T();"
763 "}"
764 "void instantiate() { declToImport<int>(); }",
765 Lang_CXX, "", Lang_CXX, Verifier,
766 functionTemplateDecl(has(functionDecl(has(compoundStmt(has(
767 binaryOperator(has(cxxUnresolvedConstructExpr())))))))));
768}
769
Aleksei Sidorin8fc85102018-01-26 11:36:54 +0000770/// Check that function "declToImport()" (which is the templated function
771/// for corresponding FunctionTemplateDecl) is not added into DeclContext.
772/// Same for class template declarations.
773TEST(ImportDecl, ImportTemplatedDeclForTemplate) {
774 MatchVerifier<Decl> Verifier;
775 testImport("template <typename T> void declToImport() { T a = 1; }"
776 "void instantiate() { declToImport<int>(); }",
777 Lang_CXX, "", Lang_CXX, Verifier,
778 functionTemplateDecl(hasAncestor(translationUnitDecl(
779 unless(has(functionDecl(hasName("declToImport"))))))));
780 testImport("template <typename T> struct declToImport { T t; };"
781 "void instantiate() { declToImport<int>(); }",
782 Lang_CXX, "", Lang_CXX, Verifier,
783 classTemplateDecl(hasAncestor(translationUnitDecl(
784 unless(has(cxxRecordDecl(hasName("declToImport"))))))));
785}
786
Gabor Horvathc78d99a2018-01-27 16:11:45 +0000787TEST(ImportExpr, CXXOperatorCallExpr) {
788 MatchVerifier<Decl> Verifier;
789 testImport("class declToImport {"
790 " void f() { *this = declToImport(); }"
791 "};",
792 Lang_CXX, "", Lang_CXX, Verifier,
793 cxxRecordDecl(has(cxxMethodDecl(hasBody(compoundStmt(
794 has(exprWithCleanups(has(cxxOperatorCallExpr())))))))));
795}
796
797TEST(ImportExpr, DependentSizedArrayType) {
798 MatchVerifier<Decl> Verifier;
799 testImport("template<typename T, int Size> class declToImport {"
800 " T data[Size];"
801 "};",
802 Lang_CXX, "", Lang_CXX, Verifier,
803 classTemplateDecl(has(cxxRecordDecl(
804 has(fieldDecl(hasType(dependentSizedArrayType())))))));
805}
806
Artem Dergachev4e7c6fd2016-04-14 11:51:27 +0000807} // end namespace ast_matchers
808} // end namespace clang